@cliff-studio/sanity-plugin-bunny-input 2.0.1 → 2.0.3
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.
package/dist/index.js
CHANGED
|
@@ -2,10 +2,8 @@ import { set, unset, defineType, defineField, definePlugin } from "sanity";
|
|
|
2
2
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useRef, useCallback, useEffect } from "react";
|
|
4
4
|
import { Dialog, Box, TextInput, Card, Text, Flex, Spinner, Grid, Stack, Button } from "@sanity/ui";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import { VideoIcon } from "@sanity/icons/Video";
|
|
8
|
-
const BUNNY_API_BASE = "https://video.bunnycdn.com";
|
|
5
|
+
import { Icon } from "@sanity/icons";
|
|
6
|
+
const UploadIcon = (props) => /* @__PURE__ */ jsx(Icon, { symbol: "upload", ...props }), SearchIcon = (props) => /* @__PURE__ */ jsx(Icon, { symbol: "search", ...props }), VideoIcon = (props) => /* @__PURE__ */ jsx(Icon, { symbol: "video", ...props }), BUNNY_API_BASE = "https://video.bunnycdn.com";
|
|
9
7
|
function mapBunnyStatus(status) {
|
|
10
8
|
switch (status) {
|
|
11
9
|
case 0:
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/api.js","../src/components/BunnyBrowserModal.jsx","../src/components/BunnyInput.jsx","../src/components/BunnyPreview.jsx","../src/schema.js","../src/index.js"],"sourcesContent":["const BUNNY_API_BASE = 'https://video.bunnycdn.com'\n\n/**\n * Maps Bunny's numeric status to our string status\n * @param {number} status\n * @returns {'uploading' | 'processing' | 'ready' | 'error'}\n */\nexport function mapBunnyStatus(status) {\n switch (status) {\n case 0: // created\n case 1: // uploaded\n return 'uploading'\n case 2: // processing\n case 3: // transcoding\n return 'processing'\n case 4: // finished\n return 'ready'\n case 5: // error\n default:\n return 'error'\n }\n}\n\n/**\n * Get the thumbnail URL for a video\n * @param {string} cdnHostname - The CDN hostname (e.g., 'vz-fbd37838-a6a.b-cdn.net')\n * @param {string} videoId\n * @returns {string}\n */\nexport function getThumbnailUrl(cdnHostname, videoId) {\n return `https://${cdnHostname}/${videoId}/thumbnail.jpg`\n}\n\n/**\n * Get the HLS playback URL for a video\n * @param {string} cdnHostname - The CDN hostname (e.g., 'vz-fbd37838-a6a.b-cdn.net')\n * @param {string} videoId\n * @returns {string}\n */\nexport function getPlaybackUrl(cdnHostname, videoId) {\n return `https://${cdnHostname}/${videoId}/playlist.m3u8`\n}\n\n/**\n * Get the direct MP4 URL (if available)\n * @param {string} cdnHostname - The CDN hostname (e.g., 'vz-fbd37838-a6a.b-cdn.net')\n * @param {string} videoId\n * @param {string} availableResolutions - Comma-separated string (e.g. \"360p,480p,240p\")\n * @returns {string}\n */\nexport function getMp4Url(cdnHostname, videoId, availableResolutions = '') {\n // Parse to numbers so we can pick the highest; URL format requires \"480p\" etc.\n const parsedResolutions = (availableResolutions || '')\n .split(',')\n .map((s) => Number.parseInt(String(s.trim()).replace(/p$/i, ''), 10))\n .filter((n) => Number.isFinite(n))\n\n const bestResolution = parsedResolutions.length ? Math.max(...parsedResolutions) : 720\n return `https://${cdnHostname}/${videoId}/play_${bestResolution}p.mp4`\n}\n\nfunction createHeaders(config, includeJsonContentType = false, useDirectApi = false) {\n const headers = {\n Accept: 'application/json',\n }\n\n if (includeJsonContentType) {\n headers['Content-Type'] = 'application/json'\n }\n\n if (config.apiKey && (useDirectApi || !config.proxyEndpoint)) {\n headers.AccessKey = config.apiKey\n }\n\n return headers\n}\n\nfunction getCollectionListUrl(config, searchTerm) {\n if (config.proxyEndpoint && !config.apiKey) {\n return `${config.proxyEndpoint}/collections?search=${encodeURIComponent(searchTerm)}`\n }\n\n return `${BUNNY_API_BASE}/library/${config.libraryId}/collections?search=${encodeURIComponent(\n searchTerm\n )}&page=1&itemsPerPage=100`\n}\n\nfunction getCreateCollectionUrl(config) {\n if (config.proxyEndpoint && !config.apiKey) {\n return `${config.proxyEndpoint}/collections`\n }\n\n return `${BUNNY_API_BASE}/library/${config.libraryId}/collections`\n}\n\nasync function getCollectionList(config, searchTerm) {\n const url = getCollectionListUrl(config, searchTerm)\n\n const response = await fetch(url, {\n headers: createHeaders(config, false, !config.proxyEndpoint || Boolean(config.apiKey)),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to list collections: ${error}`)\n }\n\n const payload = await response.json()\n return payload.items || []\n}\n\n/**\n * Get or create a Bunny Stream collection by name\n * @param {Object} config\n * @param {string} collectionName\n * @returns {Promise<{guid: string, name: string}>}\n */\nexport async function getOrCreateCollection(config, collectionName) {\n const normalizedCollectionName = collectionName?.trim()\n\n if (!normalizedCollectionName) {\n throw new Error('Collection name cannot be empty')\n }\n\n const collections = await getCollectionList(config, normalizedCollectionName)\n const existingCollection = collections.find(\n (collection) => collection.name?.toLowerCase() === normalizedCollectionName.toLowerCase()\n )\n\n if (existingCollection) {\n return existingCollection\n }\n\n const response = await fetch(getCreateCollectionUrl(config), {\n method: 'POST',\n headers: createHeaders(config, true, !config.proxyEndpoint || Boolean(config.apiKey)),\n body: JSON.stringify({name: normalizedCollectionName}),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to create collection: ${error}`)\n }\n\n return response.json()\n}\n\n/**\n * Create a new video object in Bunny Stream\n * @param {Object} config\n * @param {string} title\n * @param {string} [collectionId]\n * @returns {Promise<Object>}\n */\nexport async function createVideo(config, title, collectionId) {\n const url = config.proxyEndpoint\n ? `${config.proxyEndpoint}/create`\n : `${BUNNY_API_BASE}/library/${config.libraryId}/videos`\n\n const headers = createHeaders(config, true)\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n title,\n ...(collectionId ? {collectionId} : {}),\n }),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to create video: ${error}`)\n }\n\n return response.json()\n}\n\n/**\n * Upload video file to Bunny Stream\n * @param {Object} config\n * @param {string} videoId\n * @param {File} file\n * @param {Function} onProgress\n * @returns {Promise<Object>}\n */\nexport async function uploadVideo(config, videoId, file, onProgress) {\n const url = config.proxyEndpoint\n ? `${config.proxyEndpoint}/upload/${videoId}`\n : `${BUNNY_API_BASE}/library/${config.libraryId}/videos/${videoId}`\n\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest()\n\n xhr.upload.addEventListener('progress', (event) => {\n if (event.lengthComputable && onProgress) {\n const progress = Math.round((event.loaded / event.total) * 100)\n onProgress(progress)\n }\n })\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n try {\n const response = JSON.parse(xhr.responseText)\n resolve(response)\n } catch {\n resolve({success: true, message: 'OK'})\n }\n } else {\n reject(new Error(`Upload failed: ${xhr.statusText}`))\n }\n })\n\n xhr.addEventListener('error', () => {\n reject(new Error('Upload failed: Network error'))\n })\n\n xhr.open('PUT', url)\n xhr.setRequestHeader('Accept', 'application/json')\n\n if (!config.proxyEndpoint && config.apiKey) {\n xhr.setRequestHeader('AccessKey', config.apiKey)\n }\n\n xhr.send(file)\n })\n}\n\n/**\n * Get video details from Bunny Stream\n * @param {Object} config\n * @param {string} videoId\n * @returns {Promise<Object>}\n */\nexport async function getVideo(config, videoId) {\n const url = config.proxyEndpoint\n ? `${config.proxyEndpoint}/video/${videoId}`\n : `${BUNNY_API_BASE}/library/${config.libraryId}/videos/${videoId}`\n\n const headers = createHeaders(config)\n\n const response = await fetch(url, {headers})\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to get video: ${error}`)\n }\n\n return response.json()\n}\n\n/**\n * List videos in a collection (or entire library if no collectionId)\n * @param {Object} config\n * @param {Object} options\n * @param {string} [options.collectionId]\n * @param {string} [options.search]\n * @param {number} [options.page]\n * @param {number} [options.itemsPerPage]\n * @returns {Promise<{items: Array, totalItems: number, currentPage: number, itemsPerPage: number}>}\n */\nexport async function listVideos(config, {collectionId, search = '', page = 1, itemsPerPage = 50} = {}) {\n const params = new URLSearchParams({\n page: String(page),\n itemsPerPage: String(itemsPerPage),\n orderBy: 'date',\n })\n\n if (collectionId) params.set('collection', collectionId)\n if (search) params.set('search', search)\n\n const url = config.proxyEndpoint\n ? `${config.proxyEndpoint}/videos?${params}`\n : `${BUNNY_API_BASE}/library/${config.libraryId}/videos?${params}`\n\n const response = await fetch(url, {\n headers: createHeaders(config, false, !config.proxyEndpoint || Boolean(config.apiKey)),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to list videos: ${error}`)\n }\n\n const payload = await response.json()\n return {\n items: payload.items || [],\n totalItems: payload.totalItems ?? 0,\n currentPage: payload.currentPage ?? page,\n itemsPerPage: payload.itemsPerPage ?? itemsPerPage,\n }\n}\n\n/**\n * Delete a video from Bunny Stream\n * @param {Object} config\n * @param {string} videoId\n * @returns {Promise<Object>}\n */\nexport async function deleteVideo(config, videoId) {\n const url = config.proxyEndpoint\n ? `${config.proxyEndpoint}/video/${videoId}`\n : `${BUNNY_API_BASE}/library/${config.libraryId}/videos/${videoId}`\n\n const headers = createHeaders(config)\n\n const response = await fetch(url, {\n method: 'DELETE',\n headers,\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to delete video: ${error}`)\n }\n\n return response.json()\n}\n","import {useCallback, useEffect, useRef, useState} from 'react'\nimport {Box, Button, Card, Dialog, Flex, Grid, Spinner, Stack, Text, TextInput} from '@sanity/ui'\nimport {SearchIcon} from '@sanity/icons/Search'\nimport {listVideos, getThumbnailUrl, getPlaybackUrl, getMp4Url, mapBunnyStatus, getOrCreateCollection} from '../api'\n\nconst ITEMS_PER_PAGE = 48\n\nexport function BunnyBrowserModal({config, collectionId: collectionIdProp, onSelect, onClose}) {\n const [videos, setVideos] = useState([])\n const [search, setSearch] = useState('')\n const [page, setPage] = useState(1)\n const [totalItems, setTotalItems] = useState(0)\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState(null)\n // Resolved collection ID (may come from prop or be looked up from collectionName)\n const [resolvedCollectionId, setResolvedCollectionId] = useState(collectionIdProp || null)\n const searchTimeoutRef = useRef(null)\n\n const fetchVideos = useCallback(\n async (searchTerm, pageNum, collId) => {\n setIsLoading(true)\n setError(null)\n try {\n const result = await listVideos(config, {\n collectionId: collId,\n search: searchTerm,\n page: pageNum,\n itemsPerPage: ITEMS_PER_PAGE,\n })\n setVideos(result.items)\n setTotalItems(result.totalItems)\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load videos')\n } finally {\n setIsLoading(false)\n }\n },\n [config]\n )\n\n // Resolve collectionId from collectionName if needed, then fetch\n useEffect(() => {\n async function init() {\n let collId = collectionIdProp || null\n\n if (!collId && config.collectionName) {\n try {\n const collection = await getOrCreateCollection(config, config.collectionName)\n collId = collection.guid\n setResolvedCollectionId(collId)\n } catch (err) {\n // Fall back to browsing entire library if collection lookup fails\n console.warn('Could not resolve collection, browsing full library:', err)\n }\n }\n\n fetchVideos('', 1, collId)\n }\n init()\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleSearchChange = useCallback(\n (e) => {\n const value = e.target.value\n setSearch(value)\n setPage(1)\n if (searchTimeoutRef.current) clearTimeout(searchTimeoutRef.current)\n searchTimeoutRef.current = setTimeout(() => {\n fetchVideos(value, 1, resolvedCollectionId)\n }, 400)\n },\n [fetchVideos, resolvedCollectionId]\n )\n\n const handlePageChange = useCallback(\n (newPage) => {\n setPage(newPage)\n fetchVideos(search, newPage, resolvedCollectionId)\n },\n [fetchVideos, search, resolvedCollectionId]\n )\n\n const handleSelect = useCallback(\n (video) => {\n const videoStatus = mapBunnyStatus(video.status)\n if (videoStatus !== 'ready') return\n\n const width = Number(video.width)\n const height = Number(video.height)\n const hasDims = Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0\n const ratio = hasDims ? Number((width / height).toFixed(6)) : null\n const orientation = hasDims\n ? width > height\n ? 'landscape'\n : width < height\n ? 'portrait'\n : 'square'\n : null\n\n onSelect({\n _type: 'bunnyVideo',\n videoId: video.guid,\n libraryId: String(video.videoLibraryId),\n title: video.title,\n status: 'ready',\n duration: video.length,\n width: hasDims ? width : null,\n height: hasDims ? height : null,\n ratio,\n orientation,\n thumbnailUrl: getThumbnailUrl(config.cdnHostname, video.guid),\n playbackUrl: getPlaybackUrl(config.cdnHostname, video.guid),\n mp4Url: getMp4Url(config.cdnHostname, video.guid, video.availableResolutions),\n ...(resolvedCollectionId ? {collectionId: resolvedCollectionId} : {}),\n ...(video.collectionId ? {collectionId: video.collectionId} : {}),\n })\n },\n [config, resolvedCollectionId, onSelect]\n )\n\n const totalPages = Math.ceil(totalItems / ITEMS_PER_PAGE)\n\n return (\n <Dialog\n header=\"Browse videos\"\n id=\"bunny-browser-modal\"\n onClose={onClose}\n width={3}\n >\n <Box padding={4}>\n <Box marginBottom={4}>\n <TextInput\n icon={SearchIcon}\n placeholder=\"Search videos…\"\n value={search}\n onChange={handleSearchChange}\n />\n </Box>\n\n {error && (\n <Card padding={3} radius={2} tone=\"critical\" marginBottom={4}>\n <Text size={1}>{error}</Text>\n </Card>\n )}\n\n {isLoading ? (\n <Flex align=\"center\" justify=\"center\" padding={6}>\n <Spinner />\n </Flex>\n ) : videos.length === 0 ? (\n <Flex align=\"center\" justify=\"center\" padding={6}>\n <Text muted size={1}>\n {search ? 'No videos found matching your search' : 'No videos in this collection'}\n </Text>\n </Flex>\n ) : (\n <>\n <Grid columns={[2, 2, 3, 4]} gap={3}>\n {videos.map((video) => {\n const status = mapBunnyStatus(video.status)\n const isReady = status === 'ready'\n const thumbUrl = getThumbnailUrl(config.cdnHostname, video.guid)\n\n return (\n <Card\n key={video.guid}\n radius={2}\n shadow={1}\n style={{\n cursor: isReady ? 'pointer' : 'not-allowed',\n opacity: isReady ? 1 : 0.5,\n }}\n onClick={() => isReady && handleSelect(video)}\n >\n <Box\n style={{\n position: 'relative',\n paddingBottom: '56.25%',\n backgroundColor: '#111',\n borderRadius: '2px',\n overflow: 'hidden',\n }}\n >\n <img\n src={thumbUrl}\n alt={video.title || 'Video thumbnail'}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n }}\n />\n {!isReady && (\n <Flex\n align=\"center\"\n justify=\"center\"\n style={{\n position: 'absolute',\n inset: 0,\n backgroundColor: 'rgba(0,0,0,0.5)',\n }}\n >\n <Text size={0} style={{color: '#fff'}}>\n {status === 'processing' ? 'Processing…' : status}\n </Text>\n </Flex>\n )}\n </Box>\n <Box padding={3}>\n <Stack space={2}>\n <Text size={1} weight=\"semibold\">\n {video.title || 'Untitled'}\n </Text>\n {video.length > 0 && (\n <Text size={1} muted>\n {Math.floor(video.length / 60)}:\n {String(Math.floor(video.length % 60)).padStart(2, '0')}\n </Text>\n )}\n </Stack>\n </Box>\n </Card>\n )\n })}\n </Grid>\n\n {totalPages > 1 && (\n <Flex align=\"center\" justify=\"center\" gap={2} marginTop={4}>\n <Button\n text=\"Previous\"\n mode=\"ghost\"\n disabled={page <= 1}\n onClick={() => handlePageChange(page - 1)}\n />\n <Text size={1} muted>\n Page {page} of {totalPages}\n </Text>\n <Button\n text=\"Next\"\n mode=\"ghost\"\n disabled={page >= totalPages}\n onClick={() => handlePageChange(page + 1)}\n />\n </Flex>\n )}\n </>\n )}\n </Box>\n </Dialog>\n )\n}\n","import {useCallback, useEffect, useRef, useState} from 'react'\nimport {set, unset} from 'sanity'\nimport {Box, Button, Card, Flex, Spinner, Stack, Text} from '@sanity/ui'\nimport {UploadIcon} from '@sanity/icons/Upload'\nimport {SearchIcon} from '@sanity/icons/Search'\nimport {VideoIcon} from '@sanity/icons/Video'\nimport {\n createVideo,\n uploadVideo,\n getVideo,\n deleteVideo,\n getOrCreateCollection,\n mapBunnyStatus,\n getThumbnailUrl,\n getPlaybackUrl,\n getMp4Url,\n} from '../api'\nimport {BunnyBrowserModal} from './BunnyBrowserModal'\n\nexport function BunnyInput(props) {\n const {value, onChange, config} = props\n const [uploadProgress, setUploadProgress] = useState(0)\n const [isUploading, setIsUploading] = useState(false)\n const [error, setError] = useState(null)\n const [isBrowserOpen, setIsBrowserOpen] = useState(false)\n const fileInputRef = useRef(null)\n const pollIntervalRef = useRef(null)\n\n // Poll for video status when processing\n useEffect(() => {\n if (value?.videoId && value?.status === 'processing') {\n pollIntervalRef.current = window.setInterval(async () => {\n try {\n const videoData = await getVideo(config, value.videoId)\n const status = mapBunnyStatus(videoData.status)\n\n if (status === 'ready' || status === 'error') {\n // Clear interval when done\n if (pollIntervalRef.current) {\n clearInterval(pollIntervalRef.current)\n pollIntervalRef.current = null\n }\n\n const width = Number(videoData.width)\n const height = Number(videoData.height)\n\n const hasDims = Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0\n const ratio = hasDims ? Number((width / height).toFixed(6)) : null\n const orientation = hasDims\n ? width > height\n ? 'landscape'\n : width < height\n ? 'portrait'\n : 'square'\n : null\n\n onChange(\n set({\n ...value,\n status,\n duration: videoData.length,\n height: hasDims ? height : null,\n width: hasDims ? width : null,\n ratio: ratio,\n orientation: orientation,\n thumbnailUrl: getThumbnailUrl(config.cdnHostname, value.videoId),\n playbackUrl: getPlaybackUrl(config.cdnHostname, value.videoId),\n mp4Url: getMp4Url(\n config.cdnHostname,\n value.videoId,\n videoData.availableResolutions\n ),\n })\n )\n }\n } catch (err) {\n console.error('Error polling video status:', err)\n }\n }, 5000) // Poll every 5 seconds\n }\n\n return () => {\n if (pollIntervalRef.current) {\n clearInterval(pollIntervalRef.current)\n }\n }\n }, [value?.videoId, value?.status, config, onChange, value])\n\n const handleFileSelect = useCallback(\n async (file) => {\n if (!file.type.startsWith('video/')) {\n setError('Please select a video file')\n return\n }\n\n setError(null)\n setIsUploading(true)\n setUploadProgress(0)\n\n try {\n // Step 1: Create video object in Bunny\n const title = file.name.replace(/\\.[^/.]+$/, '') // Remove extension\n let collectionId = config.collectionId\n let collectionName = config.collectionName\n\n if (!collectionId && collectionName) {\n const collection = await getOrCreateCollection(config, collectionName)\n collectionId = collection.guid\n collectionName = collection.name\n }\n\n const created = await createVideo(config, title, collectionId)\n\n // Update Sanity with initial data\n onChange(\n set({\n _type: 'bunnyVideo',\n videoId: created.guid,\n libraryId: String(created.videoLibraryId),\n title,\n status: 'uploading',\n ...(collectionId ? {collectionId} : {}),\n ...(collectionName ? {collectionName} : {}),\n })\n )\n\n // Step 2: Upload the actual file\n await uploadVideo(config, created.guid, file, setUploadProgress)\n\n // Step 3: Update status to processing\n onChange(\n set({\n _type: 'bunnyVideo',\n videoId: created.guid,\n libraryId: String(created.videoLibraryId),\n title,\n status: 'processing',\n ...(collectionId ? {collectionId} : {}),\n ...(collectionName ? {collectionName} : {}),\n })\n )\n } catch (err) {\n console.error('Upload error:', err)\n setError(err instanceof Error ? err.message : 'Upload failed')\n onChange(\n set({\n ...value,\n status: 'error',\n errorMessage: err instanceof Error ? err.message : 'Upload failed',\n })\n )\n } finally {\n setIsUploading(false)\n setUploadProgress(0)\n }\n },\n [config, onChange, value]\n )\n\n const handleInputChange = useCallback(\n (e) => {\n const file = e.target.files?.[0]\n if (file) {\n handleFileSelect(file)\n }\n },\n [handleFileSelect]\n )\n\n const handleBrowseSelect = useCallback(\n (videoData) => {\n setIsBrowserOpen(false)\n onChange(set(videoData))\n },\n [onChange]\n )\n\n const handleRemove = useCallback(async () => {\n if (value?.videoId) {\n try {\n await deleteVideo(config, value.videoId)\n } catch (err) {\n // Log but don't block removal from Sanity\n console.error('Error deleting from Bunny:', err)\n }\n }\n onChange(unset())\n }, [config, value, onChange])\n\n // Render video preview if we have one\n if (value?.videoId && value?.status === 'ready') {\n return (\n <>\n <Card padding={3} radius={2} shadow={1}>\n <Stack space={3}>\n <Box\n style={{\n position: 'relative',\n paddingBottom: '56.25%',\n backgroundColor: '#000',\n borderRadius: '4px',\n overflow: 'hidden',\n }}\n >\n {value.thumbnailUrl && (\n <img\n src={value.thumbnailUrl}\n alt={value.title || 'Video thumbnail'}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'contain',\n }}\n />\n )}\n </Box>\n <Flex justify=\"space-between\" align=\"center\">\n <Stack space={2}>\n <Text size={1} weight=\"semibold\">\n {value.title}\n </Text>\n {value.duration && (\n <Text size={1} muted>\n {Math.floor(value.duration / 60)}:\n {String(Math.floor(value.duration % 60)).padStart(2, '0')}\n </Text>\n )}\n </Stack>\n <Flex gap={2}>\n <Button\n text=\"Browse\"\n mode=\"ghost\"\n onClick={() => setIsBrowserOpen(true)}\n />\n <Button text=\"Remove\" tone=\"critical\" mode=\"ghost\" onClick={handleRemove} />\n </Flex>\n </Flex>\n </Stack>\n </Card>\n {isBrowserOpen && (\n <BunnyBrowserModal\n config={config}\n collectionId={value.collectionId || config.collectionId}\n onSelect={handleBrowseSelect}\n onClose={() => setIsBrowserOpen(false)}\n />\n )}\n </>\n )\n }\n\n // Render processing state\n if (value?.status === 'processing') {\n return (\n <Card padding={4} radius={2} shadow={1}>\n <Flex direction=\"column\" align=\"center\" justify=\"center\" gap={3}>\n <Spinner />\n <Text size={1}>Processing video...</Text>\n <Text size={0} muted>\n This may take a few minutes\n </Text>\n </Flex>\n </Card>\n )\n }\n\n // Render uploading state\n if (isUploading) {\n return (\n <Card padding={4} radius={2} shadow={1}>\n <Stack space={3}>\n <Flex direction=\"column\" align=\"center\" justify=\"center\" gap={2}>\n <Spinner />\n <Text size={1}>Uploading... {uploadProgress}%</Text>\n </Flex>\n <Box\n style={{\n height: '4px',\n backgroundColor: '#e5e5e5',\n borderRadius: '2px',\n overflow: 'hidden',\n }}\n >\n <Box\n style={{\n height: '100%',\n width: `${uploadProgress}%`,\n backgroundColor: '#2563eb',\n transition: 'width 0.3s ease',\n }}\n />\n </Box>\n </Stack>\n </Card>\n )\n }\n\n // Render error state\n if (error || value?.status === 'error') {\n return (\n <Stack space={3}>\n <Card padding={3} radius={2} tone=\"critical\">\n <Text size={1}>Error: {error || value?.errorMessage}</Text>\n </Card>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"video/*\"\n onChange={handleInputChange}\n />\n </Stack>\n )\n }\n\n // Render file input + browse option\n return (\n <>\n <div style={{padding: 1}}>\n <Card tone=\"inherit\" border paddingX={3} paddingY={2} radius={2}>\n <Flex align=\"center\" gap={4} justify=\"space-between\">\n <Flex flex={1} align=\"center\" gap={3}>\n <Text size={1} muted><VideoIcon /></Text>\n <Text size={1} muted>Drag or paste video here</Text>\n </Flex>\n <Flex align=\"center\" gap={1}>\n <label style={{display: 'contents'}}>\n <Button\n as=\"span\"\n icon={UploadIcon}\n text=\"Upload\"\n mode=\"bleed\"\n padding={2}\n style={{cursor: 'pointer'}}\n />\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"video/*\"\n onChange={handleInputChange}\n style={{\n position: 'absolute',\n width: '1px',\n height: '1px',\n overflow: 'hidden',\n opacity: 0,\n }}\n />\n </label>\n <Button\n icon={SearchIcon}\n text=\"Select\"\n mode=\"bleed\"\n padding={2}\n onClick={() => setIsBrowserOpen(true)}\n />\n </Flex>\n </Flex>\n </Card>\n </div>\n {isBrowserOpen && (\n <BunnyBrowserModal\n config={config}\n collectionId={config.collectionId}\n onSelect={handleBrowseSelect}\n onClose={() => setIsBrowserOpen(false)}\n />\n )}\n </>\n )\n}\n","import {Box, Flex, Text} from '@sanity/ui'\n\nexport function BunnyPreview(props) {\n const {title, status, thumbnailUrl} = props\n\n const statusColors = {\n uploading: '#f59e0b',\n processing: '#3b82f6',\n ready: '#22c55e',\n error: '#ef4444',\n }\n\n const statusLabels = {\n uploading: 'Uploading',\n processing: 'Processing',\n ready: 'Ready',\n error: 'Error',\n }\n\n return (\n <Flex align=\"center\" gap={3} padding={2}>\n {thumbnailUrl ? (\n <Box\n style={{\n width: 80,\n height: 45,\n borderRadius: 4,\n overflow: 'hidden',\n backgroundColor: '#000',\n flexShrink: 0,\n }}\n >\n <img\n src={thumbnailUrl}\n alt={title || 'Video thumbnail'}\n style={{\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n }}\n />\n </Box>\n ) : (\n <Box\n style={{\n width: 80,\n height: 45,\n borderRadius: 4,\n backgroundColor: '#e5e5e5',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n }}\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{opacity: 0.4}}\n >\n <polygon points=\"5 3 19 12 5 21 5 3\" />\n </svg>\n </Box>\n )}\n <Flex direction=\"column\" gap={1} style={{minWidth: 0}}>\n <Text\n size={1}\n weight=\"semibold\"\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {title || 'Untitled video'}\n </Text>\n {status && (\n <Flex align=\"center\" gap={2}>\n <Box\n style={{\n width: 8,\n height: 8,\n borderRadius: '50%',\n backgroundColor: statusColors[status] || '#9ca3af',\n }}\n />\n <Text size={0} muted>\n {statusLabels[status] || status}\n </Text>\n </Flex>\n )}\n </Flex>\n </Flex>\n )\n}\n","import { defineType, defineField } from 'sanity'\nimport { BunnyInput } from './components/BunnyInput'\nimport { BunnyPreview } from './components/BunnyPreview'\n\nexport const createBunnyVideoSchema = (config) => {\n\treturn defineType({\n\t\ttype: 'object',\n\t\ttitle: 'Bunny Video',\n\t\tname: 'bunnyVideo',\n\t\tfields: [\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Video ID',\n\t\t\t\tname: 'videoId',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Library ID',\n\t\t\t\tname: 'libraryId',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Collection ID',\n\t\t\t\tname: 'collectionId',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Collection name',\n\t\t\t\tname: 'collectionName',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Title',\n\t\t\t\tname: 'title',\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Status',\n\t\t\t\tname: 'status',\n\t\t\t\toptions: {\n\t\t\t\t\tlist: [\n\t\t\t\t\t\t{title: 'Uploading', value: 'uploading'},\n\t\t\t\t\t\t{title: 'Processing', value: 'processing'},\n\t\t\t\t\t\t{title: 'Ready', value: 'ready'},\n\t\t\t\t\t\t{title: 'Error', value: 'error'},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'number',\n\t\t\t\ttitle: 'Video width',\n\t\t\t\tname: 'width',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'number',\n\t\t\t\ttitle: 'Video height',\n\t\t\t\tname: 'height',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'number',\n\t\t\t\ttitle: 'Video ratio',\n\t\t\t\tname: 'ratio',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Orientation',\n\t\t\t\tname: 'orientation',\n\t\t\t\toptions: {\n\t\t\t\t\tlist: [\n\t\t\t\t\t\t{title: 'Landscape', value: 'landscape'},\n\t\t\t\t\t\t{title: 'Portrait', value: 'portrait'},\n\t\t\t\t\t\t{title: 'Square', value: 'square'},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Thumbnail URL',\n\t\t\t\tname: 'thumbnailUrl',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Playback URL',\n\t\t\t\tname: 'playbackUrl',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'MP4 URL',\n\t\t\t\tname: 'mp4Url',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'number',\n\t\t\t\ttitle: 'Duration (seconds)',\n\t\t\t\tname: 'duration',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Error Message',\n\t\t\t\tname: 'errorMessage',\n\t\t\t\treadOnly: true,\n\t\t\t\thidden: true,\n\t\t\t}),\n\t\t],\n\t\tcomponents: {\n\t\t\tinput: (props) => BunnyInput({...props, config}),\n\t\t\tpreview: BunnyPreview,\n\t\t},\n\t\tpreview: {\n\t\t\tselect: {\n\t\t\t\ttitle: 'title',\n\t\t\t\tstatus: 'status',\n\t\t\t\tthumbnailUrl: 'thumbnailUrl',\n\t\t\t},\n\t\t},\n\t})\n}","import {definePlugin} from 'sanity'\nimport {createBunnyVideoSchema} from './schema'\n\nexport {getThumbnailUrl, getPlaybackUrl, getMp4Url} from './api'\n\n/**\n * Sanity plugin for Bunny Stream video uploads\n *\n * @example\n * ```js\n * // sanity.config.js\n * import { bunnyInput } from 'sanity-plugin-bunny-input'\n *\n * export default defineConfig({\n * plugins: [\n * bunnyInput({\n * libraryId: 'your-library-id',\n * cdnHostname: 'vz-abc123-xyz.b-cdn.net', // From Bunny dashboard\n * collectionName: 'my-project-videos', // Optional: auto-create/use collection by name\n * // collectionId: 'existing-collection-guid', // Optional: use existing collection directly\n * apiKey: 'your-api-key', // Or use proxyEndpoint for security\n * })\n * ]\n * })\n * ```\n *\n * Then use in your schemas:\n * ```js\n * defineField({\n * name: 'video',\n * title: 'Video',\n * type: 'bunnyVideo'\n * })\n * ```\n */\nexport const bunnyInput = definePlugin((config) => {\n if (!config.libraryId) {\n throw new Error('sanity-plugin-bunny-input: libraryId is required')\n }\n\n if (!config.cdnHostname) {\n throw new Error('sanity-plugin-bunny-input: cdnHostname is required (e.g., vz-abc123-xyz.b-cdn.net)')\n }\n\n if (!config.apiKey && !config.proxyEndpoint) {\n throw new Error('sanity-plugin-bunny-input: Either apiKey or proxyEndpoint is required')\n }\n\n const normalizedCollectionName =\n typeof config.collectionName === 'string' ? config.collectionName.trim() : undefined\n\n const pluginConfig = {\n ...config,\n ...(normalizedCollectionName ? {collectionName: normalizedCollectionName} : {}),\n }\n\n return {\n name: 'sanity-plugin-bunny-input',\n schema: {\n types: [createBunnyVideoSchema(pluginConfig)],\n },\n }\n})\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/components/icons.jsx","../src/api.js","../src/components/BunnyBrowserModal.jsx","../src/components/BunnyInput.jsx","../src/components/BunnyPreview.jsx","../src/schema.js","../src/index.js"],"sourcesContent":["import {Icon} from '@sanity/icons'\n\n// @sanity/icons has changed its per-icon import style across major versions:\n// v3.x only exports icons from the root barrel, v4.1+ adds per-icon subpaths\n// (e.g. '@sanity/icons/Upload'), and v5.0+ removes the root barrel entirely,\n// requiring subpath imports. Consuming apps can end up with any of these\n// versions hard-pinned somewhere in their dependency tree (outside our\n// control), so no single import style works everywhere.\n//\n// The one API that has stayed stable across all of these versions is the\n// dynamic `Icon` component with a `symbol` prop, exported from the root\n// entry point. These thin wrappers let the rest of the plugin use icons as\n// normal components (e.g. for @sanity/ui's `icon` prop) while staying\n// compatible with whatever @sanity/icons version ends up resolved.\nexport const UploadIcon = (props) => <Icon symbol=\"upload\" {...props} />\nexport const SearchIcon = (props) => <Icon symbol=\"search\" {...props} />\nexport const VideoIcon = (props) => <Icon symbol=\"video\" {...props} />\n","const BUNNY_API_BASE = 'https://video.bunnycdn.com'\n\n/**\n * Maps Bunny's numeric status to our string status\n * @param {number} status\n * @returns {'uploading' | 'processing' | 'ready' | 'error'}\n */\nexport function mapBunnyStatus(status) {\n switch (status) {\n case 0: // created\n case 1: // uploaded\n return 'uploading'\n case 2: // processing\n case 3: // transcoding\n return 'processing'\n case 4: // finished\n return 'ready'\n case 5: // error\n default:\n return 'error'\n }\n}\n\n/**\n * Get the thumbnail URL for a video\n * @param {string} cdnHostname - The CDN hostname (e.g., 'vz-fbd37838-a6a.b-cdn.net')\n * @param {string} videoId\n * @returns {string}\n */\nexport function getThumbnailUrl(cdnHostname, videoId) {\n return `https://${cdnHostname}/${videoId}/thumbnail.jpg`\n}\n\n/**\n * Get the HLS playback URL for a video\n * @param {string} cdnHostname - The CDN hostname (e.g., 'vz-fbd37838-a6a.b-cdn.net')\n * @param {string} videoId\n * @returns {string}\n */\nexport function getPlaybackUrl(cdnHostname, videoId) {\n return `https://${cdnHostname}/${videoId}/playlist.m3u8`\n}\n\n/**\n * Get the direct MP4 URL (if available)\n * @param {string} cdnHostname - The CDN hostname (e.g., 'vz-fbd37838-a6a.b-cdn.net')\n * @param {string} videoId\n * @param {string} availableResolutions - Comma-separated string (e.g. \"360p,480p,240p\")\n * @returns {string}\n */\nexport function getMp4Url(cdnHostname, videoId, availableResolutions = '') {\n // Parse to numbers so we can pick the highest; URL format requires \"480p\" etc.\n const parsedResolutions = (availableResolutions || '')\n .split(',')\n .map((s) => Number.parseInt(String(s.trim()).replace(/p$/i, ''), 10))\n .filter((n) => Number.isFinite(n))\n\n const bestResolution = parsedResolutions.length ? Math.max(...parsedResolutions) : 720\n return `https://${cdnHostname}/${videoId}/play_${bestResolution}p.mp4`\n}\n\nfunction createHeaders(config, includeJsonContentType = false, useDirectApi = false) {\n const headers = {\n Accept: 'application/json',\n }\n\n if (includeJsonContentType) {\n headers['Content-Type'] = 'application/json'\n }\n\n if (config.apiKey && (useDirectApi || !config.proxyEndpoint)) {\n headers.AccessKey = config.apiKey\n }\n\n return headers\n}\n\nfunction getCollectionListUrl(config, searchTerm) {\n if (config.proxyEndpoint && !config.apiKey) {\n return `${config.proxyEndpoint}/collections?search=${encodeURIComponent(searchTerm)}`\n }\n\n return `${BUNNY_API_BASE}/library/${config.libraryId}/collections?search=${encodeURIComponent(\n searchTerm\n )}&page=1&itemsPerPage=100`\n}\n\nfunction getCreateCollectionUrl(config) {\n if (config.proxyEndpoint && !config.apiKey) {\n return `${config.proxyEndpoint}/collections`\n }\n\n return `${BUNNY_API_BASE}/library/${config.libraryId}/collections`\n}\n\nasync function getCollectionList(config, searchTerm) {\n const url = getCollectionListUrl(config, searchTerm)\n\n const response = await fetch(url, {\n headers: createHeaders(config, false, !config.proxyEndpoint || Boolean(config.apiKey)),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to list collections: ${error}`)\n }\n\n const payload = await response.json()\n return payload.items || []\n}\n\n/**\n * Get or create a Bunny Stream collection by name\n * @param {Object} config\n * @param {string} collectionName\n * @returns {Promise<{guid: string, name: string}>}\n */\nexport async function getOrCreateCollection(config, collectionName) {\n const normalizedCollectionName = collectionName?.trim()\n\n if (!normalizedCollectionName) {\n throw new Error('Collection name cannot be empty')\n }\n\n const collections = await getCollectionList(config, normalizedCollectionName)\n const existingCollection = collections.find(\n (collection) => collection.name?.toLowerCase() === normalizedCollectionName.toLowerCase()\n )\n\n if (existingCollection) {\n return existingCollection\n }\n\n const response = await fetch(getCreateCollectionUrl(config), {\n method: 'POST',\n headers: createHeaders(config, true, !config.proxyEndpoint || Boolean(config.apiKey)),\n body: JSON.stringify({name: normalizedCollectionName}),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to create collection: ${error}`)\n }\n\n return response.json()\n}\n\n/**\n * Create a new video object in Bunny Stream\n * @param {Object} config\n * @param {string} title\n * @param {string} [collectionId]\n * @returns {Promise<Object>}\n */\nexport async function createVideo(config, title, collectionId) {\n const url = config.proxyEndpoint\n ? `${config.proxyEndpoint}/create`\n : `${BUNNY_API_BASE}/library/${config.libraryId}/videos`\n\n const headers = createHeaders(config, true)\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n title,\n ...(collectionId ? {collectionId} : {}),\n }),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to create video: ${error}`)\n }\n\n return response.json()\n}\n\n/**\n * Upload video file to Bunny Stream\n * @param {Object} config\n * @param {string} videoId\n * @param {File} file\n * @param {Function} onProgress\n * @returns {Promise<Object>}\n */\nexport async function uploadVideo(config, videoId, file, onProgress) {\n const url = config.proxyEndpoint\n ? `${config.proxyEndpoint}/upload/${videoId}`\n : `${BUNNY_API_BASE}/library/${config.libraryId}/videos/${videoId}`\n\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest()\n\n xhr.upload.addEventListener('progress', (event) => {\n if (event.lengthComputable && onProgress) {\n const progress = Math.round((event.loaded / event.total) * 100)\n onProgress(progress)\n }\n })\n\n xhr.addEventListener('load', () => {\n if (xhr.status >= 200 && xhr.status < 300) {\n try {\n const response = JSON.parse(xhr.responseText)\n resolve(response)\n } catch {\n resolve({success: true, message: 'OK'})\n }\n } else {\n reject(new Error(`Upload failed: ${xhr.statusText}`))\n }\n })\n\n xhr.addEventListener('error', () => {\n reject(new Error('Upload failed: Network error'))\n })\n\n xhr.open('PUT', url)\n xhr.setRequestHeader('Accept', 'application/json')\n\n if (!config.proxyEndpoint && config.apiKey) {\n xhr.setRequestHeader('AccessKey', config.apiKey)\n }\n\n xhr.send(file)\n })\n}\n\n/**\n * Get video details from Bunny Stream\n * @param {Object} config\n * @param {string} videoId\n * @returns {Promise<Object>}\n */\nexport async function getVideo(config, videoId) {\n const url = config.proxyEndpoint\n ? `${config.proxyEndpoint}/video/${videoId}`\n : `${BUNNY_API_BASE}/library/${config.libraryId}/videos/${videoId}`\n\n const headers = createHeaders(config)\n\n const response = await fetch(url, {headers})\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to get video: ${error}`)\n }\n\n return response.json()\n}\n\n/**\n * List videos in a collection (or entire library if no collectionId)\n * @param {Object} config\n * @param {Object} options\n * @param {string} [options.collectionId]\n * @param {string} [options.search]\n * @param {number} [options.page]\n * @param {number} [options.itemsPerPage]\n * @returns {Promise<{items: Array, totalItems: number, currentPage: number, itemsPerPage: number}>}\n */\nexport async function listVideos(config, {collectionId, search = '', page = 1, itemsPerPage = 50} = {}) {\n const params = new URLSearchParams({\n page: String(page),\n itemsPerPage: String(itemsPerPage),\n orderBy: 'date',\n })\n\n if (collectionId) params.set('collection', collectionId)\n if (search) params.set('search', search)\n\n const url = config.proxyEndpoint\n ? `${config.proxyEndpoint}/videos?${params}`\n : `${BUNNY_API_BASE}/library/${config.libraryId}/videos?${params}`\n\n const response = await fetch(url, {\n headers: createHeaders(config, false, !config.proxyEndpoint || Boolean(config.apiKey)),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to list videos: ${error}`)\n }\n\n const payload = await response.json()\n return {\n items: payload.items || [],\n totalItems: payload.totalItems ?? 0,\n currentPage: payload.currentPage ?? page,\n itemsPerPage: payload.itemsPerPage ?? itemsPerPage,\n }\n}\n\n/**\n * Delete a video from Bunny Stream\n * @param {Object} config\n * @param {string} videoId\n * @returns {Promise<Object>}\n */\nexport async function deleteVideo(config, videoId) {\n const url = config.proxyEndpoint\n ? `${config.proxyEndpoint}/video/${videoId}`\n : `${BUNNY_API_BASE}/library/${config.libraryId}/videos/${videoId}`\n\n const headers = createHeaders(config)\n\n const response = await fetch(url, {\n method: 'DELETE',\n headers,\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to delete video: ${error}`)\n }\n\n return response.json()\n}\n","import {useCallback, useEffect, useRef, useState} from 'react'\nimport {Box, Button, Card, Dialog, Flex, Grid, Spinner, Stack, Text, TextInput} from '@sanity/ui'\nimport {SearchIcon} from './icons'\nimport {listVideos, getThumbnailUrl, getPlaybackUrl, getMp4Url, mapBunnyStatus, getOrCreateCollection} from '../api'\n\nconst ITEMS_PER_PAGE = 48\n\nexport function BunnyBrowserModal({config, collectionId: collectionIdProp, onSelect, onClose}) {\n const [videos, setVideos] = useState([])\n const [search, setSearch] = useState('')\n const [page, setPage] = useState(1)\n const [totalItems, setTotalItems] = useState(0)\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState(null)\n // Resolved collection ID (may come from prop or be looked up from collectionName)\n const [resolvedCollectionId, setResolvedCollectionId] = useState(collectionIdProp || null)\n const searchTimeoutRef = useRef(null)\n\n const fetchVideos = useCallback(\n async (searchTerm, pageNum, collId) => {\n setIsLoading(true)\n setError(null)\n try {\n const result = await listVideos(config, {\n collectionId: collId,\n search: searchTerm,\n page: pageNum,\n itemsPerPage: ITEMS_PER_PAGE,\n })\n setVideos(result.items)\n setTotalItems(result.totalItems)\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load videos')\n } finally {\n setIsLoading(false)\n }\n },\n [config]\n )\n\n // Resolve collectionId from collectionName if needed, then fetch\n useEffect(() => {\n async function init() {\n let collId = collectionIdProp || null\n\n if (!collId && config.collectionName) {\n try {\n const collection = await getOrCreateCollection(config, config.collectionName)\n collId = collection.guid\n setResolvedCollectionId(collId)\n } catch (err) {\n // Fall back to browsing entire library if collection lookup fails\n console.warn('Could not resolve collection, browsing full library:', err)\n }\n }\n\n fetchVideos('', 1, collId)\n }\n init()\n }, []) // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleSearchChange = useCallback(\n (e) => {\n const value = e.target.value\n setSearch(value)\n setPage(1)\n if (searchTimeoutRef.current) clearTimeout(searchTimeoutRef.current)\n searchTimeoutRef.current = setTimeout(() => {\n fetchVideos(value, 1, resolvedCollectionId)\n }, 400)\n },\n [fetchVideos, resolvedCollectionId]\n )\n\n const handlePageChange = useCallback(\n (newPage) => {\n setPage(newPage)\n fetchVideos(search, newPage, resolvedCollectionId)\n },\n [fetchVideos, search, resolvedCollectionId]\n )\n\n const handleSelect = useCallback(\n (video) => {\n const videoStatus = mapBunnyStatus(video.status)\n if (videoStatus !== 'ready') return\n\n const width = Number(video.width)\n const height = Number(video.height)\n const hasDims = Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0\n const ratio = hasDims ? Number((width / height).toFixed(6)) : null\n const orientation = hasDims\n ? width > height\n ? 'landscape'\n : width < height\n ? 'portrait'\n : 'square'\n : null\n\n onSelect({\n _type: 'bunnyVideo',\n videoId: video.guid,\n libraryId: String(video.videoLibraryId),\n title: video.title,\n status: 'ready',\n duration: video.length,\n width: hasDims ? width : null,\n height: hasDims ? height : null,\n ratio,\n orientation,\n thumbnailUrl: getThumbnailUrl(config.cdnHostname, video.guid),\n playbackUrl: getPlaybackUrl(config.cdnHostname, video.guid),\n mp4Url: getMp4Url(config.cdnHostname, video.guid, video.availableResolutions),\n ...(resolvedCollectionId ? {collectionId: resolvedCollectionId} : {}),\n ...(video.collectionId ? {collectionId: video.collectionId} : {}),\n })\n },\n [config, resolvedCollectionId, onSelect]\n )\n\n const totalPages = Math.ceil(totalItems / ITEMS_PER_PAGE)\n\n return (\n <Dialog\n header=\"Browse videos\"\n id=\"bunny-browser-modal\"\n onClose={onClose}\n width={3}\n >\n <Box padding={4}>\n <Box marginBottom={4}>\n <TextInput\n icon={SearchIcon}\n placeholder=\"Search videos…\"\n value={search}\n onChange={handleSearchChange}\n />\n </Box>\n\n {error && (\n <Card padding={3} radius={2} tone=\"critical\" marginBottom={4}>\n <Text size={1}>{error}</Text>\n </Card>\n )}\n\n {isLoading ? (\n <Flex align=\"center\" justify=\"center\" padding={6}>\n <Spinner />\n </Flex>\n ) : videos.length === 0 ? (\n <Flex align=\"center\" justify=\"center\" padding={6}>\n <Text muted size={1}>\n {search ? 'No videos found matching your search' : 'No videos in this collection'}\n </Text>\n </Flex>\n ) : (\n <>\n <Grid columns={[2, 2, 3, 4]} gap={3}>\n {videos.map((video) => {\n const status = mapBunnyStatus(video.status)\n const isReady = status === 'ready'\n const thumbUrl = getThumbnailUrl(config.cdnHostname, video.guid)\n\n return (\n <Card\n key={video.guid}\n radius={2}\n shadow={1}\n style={{\n cursor: isReady ? 'pointer' : 'not-allowed',\n opacity: isReady ? 1 : 0.5,\n }}\n onClick={() => isReady && handleSelect(video)}\n >\n <Box\n style={{\n position: 'relative',\n paddingBottom: '56.25%',\n backgroundColor: '#111',\n borderRadius: '2px',\n overflow: 'hidden',\n }}\n >\n <img\n src={thumbUrl}\n alt={video.title || 'Video thumbnail'}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n }}\n />\n {!isReady && (\n <Flex\n align=\"center\"\n justify=\"center\"\n style={{\n position: 'absolute',\n inset: 0,\n backgroundColor: 'rgba(0,0,0,0.5)',\n }}\n >\n <Text size={0} style={{color: '#fff'}}>\n {status === 'processing' ? 'Processing…' : status}\n </Text>\n </Flex>\n )}\n </Box>\n <Box padding={3}>\n <Stack space={2}>\n <Text size={1} weight=\"semibold\">\n {video.title || 'Untitled'}\n </Text>\n {video.length > 0 && (\n <Text size={1} muted>\n {Math.floor(video.length / 60)}:\n {String(Math.floor(video.length % 60)).padStart(2, '0')}\n </Text>\n )}\n </Stack>\n </Box>\n </Card>\n )\n })}\n </Grid>\n\n {totalPages > 1 && (\n <Flex align=\"center\" justify=\"center\" gap={2} marginTop={4}>\n <Button\n text=\"Previous\"\n mode=\"ghost\"\n disabled={page <= 1}\n onClick={() => handlePageChange(page - 1)}\n />\n <Text size={1} muted>\n Page {page} of {totalPages}\n </Text>\n <Button\n text=\"Next\"\n mode=\"ghost\"\n disabled={page >= totalPages}\n onClick={() => handlePageChange(page + 1)}\n />\n </Flex>\n )}\n </>\n )}\n </Box>\n </Dialog>\n )\n}\n","import {useCallback, useEffect, useRef, useState} from 'react'\nimport {set, unset} from 'sanity'\nimport {Box, Button, Card, Flex, Spinner, Stack, Text} from '@sanity/ui'\nimport {UploadIcon, SearchIcon, VideoIcon} from './icons'\nimport {\n createVideo,\n uploadVideo,\n getVideo,\n deleteVideo,\n getOrCreateCollection,\n mapBunnyStatus,\n getThumbnailUrl,\n getPlaybackUrl,\n getMp4Url,\n} from '../api'\nimport {BunnyBrowserModal} from './BunnyBrowserModal'\n\nexport function BunnyInput(props) {\n const {value, onChange, config} = props\n const [uploadProgress, setUploadProgress] = useState(0)\n const [isUploading, setIsUploading] = useState(false)\n const [error, setError] = useState(null)\n const [isBrowserOpen, setIsBrowserOpen] = useState(false)\n const fileInputRef = useRef(null)\n const pollIntervalRef = useRef(null)\n\n // Poll for video status when processing\n useEffect(() => {\n if (value?.videoId && value?.status === 'processing') {\n pollIntervalRef.current = window.setInterval(async () => {\n try {\n const videoData = await getVideo(config, value.videoId)\n const status = mapBunnyStatus(videoData.status)\n\n if (status === 'ready' || status === 'error') {\n // Clear interval when done\n if (pollIntervalRef.current) {\n clearInterval(pollIntervalRef.current)\n pollIntervalRef.current = null\n }\n\n const width = Number(videoData.width)\n const height = Number(videoData.height)\n\n const hasDims = Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0\n const ratio = hasDims ? Number((width / height).toFixed(6)) : null\n const orientation = hasDims\n ? width > height\n ? 'landscape'\n : width < height\n ? 'portrait'\n : 'square'\n : null\n\n onChange(\n set({\n ...value,\n status,\n duration: videoData.length,\n height: hasDims ? height : null,\n width: hasDims ? width : null,\n ratio: ratio,\n orientation: orientation,\n thumbnailUrl: getThumbnailUrl(config.cdnHostname, value.videoId),\n playbackUrl: getPlaybackUrl(config.cdnHostname, value.videoId),\n mp4Url: getMp4Url(\n config.cdnHostname,\n value.videoId,\n videoData.availableResolutions\n ),\n })\n )\n }\n } catch (err) {\n console.error('Error polling video status:', err)\n }\n }, 5000) // Poll every 5 seconds\n }\n\n return () => {\n if (pollIntervalRef.current) {\n clearInterval(pollIntervalRef.current)\n }\n }\n }, [value?.videoId, value?.status, config, onChange, value])\n\n const handleFileSelect = useCallback(\n async (file) => {\n if (!file.type.startsWith('video/')) {\n setError('Please select a video file')\n return\n }\n\n setError(null)\n setIsUploading(true)\n setUploadProgress(0)\n\n try {\n // Step 1: Create video object in Bunny\n const title = file.name.replace(/\\.[^/.]+$/, '') // Remove extension\n let collectionId = config.collectionId\n let collectionName = config.collectionName\n\n if (!collectionId && collectionName) {\n const collection = await getOrCreateCollection(config, collectionName)\n collectionId = collection.guid\n collectionName = collection.name\n }\n\n const created = await createVideo(config, title, collectionId)\n\n // Update Sanity with initial data\n onChange(\n set({\n _type: 'bunnyVideo',\n videoId: created.guid,\n libraryId: String(created.videoLibraryId),\n title,\n status: 'uploading',\n ...(collectionId ? {collectionId} : {}),\n ...(collectionName ? {collectionName} : {}),\n })\n )\n\n // Step 2: Upload the actual file\n await uploadVideo(config, created.guid, file, setUploadProgress)\n\n // Step 3: Update status to processing\n onChange(\n set({\n _type: 'bunnyVideo',\n videoId: created.guid,\n libraryId: String(created.videoLibraryId),\n title,\n status: 'processing',\n ...(collectionId ? {collectionId} : {}),\n ...(collectionName ? {collectionName} : {}),\n })\n )\n } catch (err) {\n console.error('Upload error:', err)\n setError(err instanceof Error ? err.message : 'Upload failed')\n onChange(\n set({\n ...value,\n status: 'error',\n errorMessage: err instanceof Error ? err.message : 'Upload failed',\n })\n )\n } finally {\n setIsUploading(false)\n setUploadProgress(0)\n }\n },\n [config, onChange, value]\n )\n\n const handleInputChange = useCallback(\n (e) => {\n const file = e.target.files?.[0]\n if (file) {\n handleFileSelect(file)\n }\n },\n [handleFileSelect]\n )\n\n const handleBrowseSelect = useCallback(\n (videoData) => {\n setIsBrowserOpen(false)\n onChange(set(videoData))\n },\n [onChange]\n )\n\n const handleRemove = useCallback(async () => {\n if (value?.videoId) {\n try {\n await deleteVideo(config, value.videoId)\n } catch (err) {\n // Log but don't block removal from Sanity\n console.error('Error deleting from Bunny:', err)\n }\n }\n onChange(unset())\n }, [config, value, onChange])\n\n // Render video preview if we have one\n if (value?.videoId && value?.status === 'ready') {\n return (\n <>\n <Card padding={3} radius={2} shadow={1}>\n <Stack space={3}>\n <Box\n style={{\n position: 'relative',\n paddingBottom: '56.25%',\n backgroundColor: '#000',\n borderRadius: '4px',\n overflow: 'hidden',\n }}\n >\n {value.thumbnailUrl && (\n <img\n src={value.thumbnailUrl}\n alt={value.title || 'Video thumbnail'}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n objectFit: 'contain',\n }}\n />\n )}\n </Box>\n <Flex justify=\"space-between\" align=\"center\">\n <Stack space={2}>\n <Text size={1} weight=\"semibold\">\n {value.title}\n </Text>\n {value.duration && (\n <Text size={1} muted>\n {Math.floor(value.duration / 60)}:\n {String(Math.floor(value.duration % 60)).padStart(2, '0')}\n </Text>\n )}\n </Stack>\n <Flex gap={2}>\n <Button\n text=\"Browse\"\n mode=\"ghost\"\n onClick={() => setIsBrowserOpen(true)}\n />\n <Button text=\"Remove\" tone=\"critical\" mode=\"ghost\" onClick={handleRemove} />\n </Flex>\n </Flex>\n </Stack>\n </Card>\n {isBrowserOpen && (\n <BunnyBrowserModal\n config={config}\n collectionId={value.collectionId || config.collectionId}\n onSelect={handleBrowseSelect}\n onClose={() => setIsBrowserOpen(false)}\n />\n )}\n </>\n )\n }\n\n // Render processing state\n if (value?.status === 'processing') {\n return (\n <Card padding={4} radius={2} shadow={1}>\n <Flex direction=\"column\" align=\"center\" justify=\"center\" gap={3}>\n <Spinner />\n <Text size={1}>Processing video...</Text>\n <Text size={0} muted>\n This may take a few minutes\n </Text>\n </Flex>\n </Card>\n )\n }\n\n // Render uploading state\n if (isUploading) {\n return (\n <Card padding={4} radius={2} shadow={1}>\n <Stack space={3}>\n <Flex direction=\"column\" align=\"center\" justify=\"center\" gap={2}>\n <Spinner />\n <Text size={1}>Uploading... {uploadProgress}%</Text>\n </Flex>\n <Box\n style={{\n height: '4px',\n backgroundColor: '#e5e5e5',\n borderRadius: '2px',\n overflow: 'hidden',\n }}\n >\n <Box\n style={{\n height: '100%',\n width: `${uploadProgress}%`,\n backgroundColor: '#2563eb',\n transition: 'width 0.3s ease',\n }}\n />\n </Box>\n </Stack>\n </Card>\n )\n }\n\n // Render error state\n if (error || value?.status === 'error') {\n return (\n <Stack space={3}>\n <Card padding={3} radius={2} tone=\"critical\">\n <Text size={1}>Error: {error || value?.errorMessage}</Text>\n </Card>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"video/*\"\n onChange={handleInputChange}\n />\n </Stack>\n )\n }\n\n // Render file input + browse option\n return (\n <>\n <div style={{padding: 1}}>\n <Card tone=\"inherit\" border paddingX={3} paddingY={2} radius={2}>\n <Flex align=\"center\" gap={4} justify=\"space-between\">\n <Flex flex={1} align=\"center\" gap={3}>\n <Text size={1} muted><VideoIcon /></Text>\n <Text size={1} muted>Drag or paste video here</Text>\n </Flex>\n <Flex align=\"center\" gap={1}>\n <label style={{display: 'contents'}}>\n <Button\n as=\"span\"\n icon={UploadIcon}\n text=\"Upload\"\n mode=\"bleed\"\n padding={2}\n style={{cursor: 'pointer'}}\n />\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"video/*\"\n onChange={handleInputChange}\n style={{\n position: 'absolute',\n width: '1px',\n height: '1px',\n overflow: 'hidden',\n opacity: 0,\n }}\n />\n </label>\n <Button\n icon={SearchIcon}\n text=\"Select\"\n mode=\"bleed\"\n padding={2}\n onClick={() => setIsBrowserOpen(true)}\n />\n </Flex>\n </Flex>\n </Card>\n </div>\n {isBrowserOpen && (\n <BunnyBrowserModal\n config={config}\n collectionId={config.collectionId}\n onSelect={handleBrowseSelect}\n onClose={() => setIsBrowserOpen(false)}\n />\n )}\n </>\n )\n}\n","import {Box, Flex, Text} from '@sanity/ui'\n\nexport function BunnyPreview(props) {\n const {title, status, thumbnailUrl} = props\n\n const statusColors = {\n uploading: '#f59e0b',\n processing: '#3b82f6',\n ready: '#22c55e',\n error: '#ef4444',\n }\n\n const statusLabels = {\n uploading: 'Uploading',\n processing: 'Processing',\n ready: 'Ready',\n error: 'Error',\n }\n\n return (\n <Flex align=\"center\" gap={3} padding={2}>\n {thumbnailUrl ? (\n <Box\n style={{\n width: 80,\n height: 45,\n borderRadius: 4,\n overflow: 'hidden',\n backgroundColor: '#000',\n flexShrink: 0,\n }}\n >\n <img\n src={thumbnailUrl}\n alt={title || 'Video thumbnail'}\n style={{\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n }}\n />\n </Box>\n ) : (\n <Box\n style={{\n width: 80,\n height: 45,\n borderRadius: 4,\n backgroundColor: '#e5e5e5',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n }}\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n style={{opacity: 0.4}}\n >\n <polygon points=\"5 3 19 12 5 21 5 3\" />\n </svg>\n </Box>\n )}\n <Flex direction=\"column\" gap={1} style={{minWidth: 0}}>\n <Text\n size={1}\n weight=\"semibold\"\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {title || 'Untitled video'}\n </Text>\n {status && (\n <Flex align=\"center\" gap={2}>\n <Box\n style={{\n width: 8,\n height: 8,\n borderRadius: '50%',\n backgroundColor: statusColors[status] || '#9ca3af',\n }}\n />\n <Text size={0} muted>\n {statusLabels[status] || status}\n </Text>\n </Flex>\n )}\n </Flex>\n </Flex>\n )\n}\n","import { defineType, defineField } from 'sanity'\nimport { BunnyInput } from './components/BunnyInput'\nimport { BunnyPreview } from './components/BunnyPreview'\n\nexport const createBunnyVideoSchema = (config) => {\n\treturn defineType({\n\t\ttype: 'object',\n\t\ttitle: 'Bunny Video',\n\t\tname: 'bunnyVideo',\n\t\tfields: [\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Video ID',\n\t\t\t\tname: 'videoId',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Library ID',\n\t\t\t\tname: 'libraryId',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Collection ID',\n\t\t\t\tname: 'collectionId',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Collection name',\n\t\t\t\tname: 'collectionName',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Title',\n\t\t\t\tname: 'title',\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Status',\n\t\t\t\tname: 'status',\n\t\t\t\toptions: {\n\t\t\t\t\tlist: [\n\t\t\t\t\t\t{title: 'Uploading', value: 'uploading'},\n\t\t\t\t\t\t{title: 'Processing', value: 'processing'},\n\t\t\t\t\t\t{title: 'Ready', value: 'ready'},\n\t\t\t\t\t\t{title: 'Error', value: 'error'},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'number',\n\t\t\t\ttitle: 'Video width',\n\t\t\t\tname: 'width',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'number',\n\t\t\t\ttitle: 'Video height',\n\t\t\t\tname: 'height',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'number',\n\t\t\t\ttitle: 'Video ratio',\n\t\t\t\tname: 'ratio',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Orientation',\n\t\t\t\tname: 'orientation',\n\t\t\t\toptions: {\n\t\t\t\t\tlist: [\n\t\t\t\t\t\t{title: 'Landscape', value: 'landscape'},\n\t\t\t\t\t\t{title: 'Portrait', value: 'portrait'},\n\t\t\t\t\t\t{title: 'Square', value: 'square'},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Thumbnail URL',\n\t\t\t\tname: 'thumbnailUrl',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Playback URL',\n\t\t\t\tname: 'playbackUrl',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'MP4 URL',\n\t\t\t\tname: 'mp4Url',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'number',\n\t\t\t\ttitle: 'Duration (seconds)',\n\t\t\t\tname: 'duration',\n\t\t\t\treadOnly: true,\n\t\t\t}),\n\t\t\tdefineField({\n\t\t\t\ttype: 'string',\n\t\t\t\ttitle: 'Error Message',\n\t\t\t\tname: 'errorMessage',\n\t\t\t\treadOnly: true,\n\t\t\t\thidden: true,\n\t\t\t}),\n\t\t],\n\t\tcomponents: {\n\t\t\tinput: (props) => BunnyInput({...props, config}),\n\t\t\tpreview: BunnyPreview,\n\t\t},\n\t\tpreview: {\n\t\t\tselect: {\n\t\t\t\ttitle: 'title',\n\t\t\t\tstatus: 'status',\n\t\t\t\tthumbnailUrl: 'thumbnailUrl',\n\t\t\t},\n\t\t},\n\t})\n}","import {definePlugin} from 'sanity'\nimport {createBunnyVideoSchema} from './schema'\n\nexport {getThumbnailUrl, getPlaybackUrl, getMp4Url} from './api'\n\n/**\n * Sanity plugin for Bunny Stream video uploads\n *\n * @example\n * ```js\n * // sanity.config.js\n * import { bunnyInput } from 'sanity-plugin-bunny-input'\n *\n * export default defineConfig({\n * plugins: [\n * bunnyInput({\n * libraryId: 'your-library-id',\n * cdnHostname: 'vz-abc123-xyz.b-cdn.net', // From Bunny dashboard\n * collectionName: 'my-project-videos', // Optional: auto-create/use collection by name\n * // collectionId: 'existing-collection-guid', // Optional: use existing collection directly\n * apiKey: 'your-api-key', // Or use proxyEndpoint for security\n * })\n * ]\n * })\n * ```\n *\n * Then use in your schemas:\n * ```js\n * defineField({\n * name: 'video',\n * title: 'Video',\n * type: 'bunnyVideo'\n * })\n * ```\n */\nexport const bunnyInput = definePlugin((config) => {\n if (!config.libraryId) {\n throw new Error('sanity-plugin-bunny-input: libraryId is required')\n }\n\n if (!config.cdnHostname) {\n throw new Error('sanity-plugin-bunny-input: cdnHostname is required (e.g., vz-abc123-xyz.b-cdn.net)')\n }\n\n if (!config.apiKey && !config.proxyEndpoint) {\n throw new Error('sanity-plugin-bunny-input: Either apiKey or proxyEndpoint is required')\n }\n\n const normalizedCollectionName =\n typeof config.collectionName === 'string' ? config.collectionName.trim() : undefined\n\n const pluginConfig = {\n ...config,\n ...(normalizedCollectionName ? {collectionName: normalizedCollectionName} : {}),\n }\n\n return {\n name: 'sanity-plugin-bunny-input',\n schema: {\n types: [createBunnyVideoSchema(pluginConfig)],\n },\n }\n})\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cliff-studio/sanity-plugin-bunny-input",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "Sanity Studio plugin for uploading videos to Bunny Stream",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Cliff Studio",
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
"prepublishOnly": "npm run build"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@sanity/icons": "^3.0.0",
|
|
31
|
+
"@sanity/icons": "^3.0.0 || ^4.0.0 || ^5.0.0",
|
|
32
32
|
"@sanity/ui": "^2.0.0 || ^3.0.0",
|
|
33
33
|
"react": "^18.0.0 || ^19.0.0",
|
|
34
34
|
"sanity": "^5.0.0 || ^6.0.0",
|
|
35
35
|
"styled-components": "^5.2 || ^6"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@sanity/icons": "^
|
|
38
|
+
"@sanity/icons": "^5.2.1",
|
|
39
39
|
"@sanity/pkg-utils": "^6.0.0",
|
|
40
40
|
"@sanity/plugin-kit": "^4.0.0",
|
|
41
41
|
"@sanity/ui": "^3.3.5",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {useCallback, useEffect, useRef, useState} from 'react'
|
|
2
2
|
import {Box, Button, Card, Dialog, Flex, Grid, Spinner, Stack, Text, TextInput} from '@sanity/ui'
|
|
3
|
-
import {SearchIcon} from '
|
|
3
|
+
import {SearchIcon} from './icons'
|
|
4
4
|
import {listVideos, getThumbnailUrl, getPlaybackUrl, getMp4Url, mapBunnyStatus, getOrCreateCollection} from '../api'
|
|
5
5
|
|
|
6
6
|
const ITEMS_PER_PAGE = 48
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import {useCallback, useEffect, useRef, useState} from 'react'
|
|
2
2
|
import {set, unset} from 'sanity'
|
|
3
3
|
import {Box, Button, Card, Flex, Spinner, Stack, Text} from '@sanity/ui'
|
|
4
|
-
import {UploadIcon} from '
|
|
5
|
-
import {SearchIcon} from '@sanity/icons/Search'
|
|
6
|
-
import {VideoIcon} from '@sanity/icons/Video'
|
|
4
|
+
import {UploadIcon, SearchIcon, VideoIcon} from './icons'
|
|
7
5
|
import {
|
|
8
6
|
createVideo,
|
|
9
7
|
uploadVideo,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {Icon} from '@sanity/icons'
|
|
2
|
+
|
|
3
|
+
// @sanity/icons has changed its per-icon import style across major versions:
|
|
4
|
+
// v3.x only exports icons from the root barrel, v4.1+ adds per-icon subpaths
|
|
5
|
+
// (e.g. '@sanity/icons/Upload'), and v5.0+ removes the root barrel entirely,
|
|
6
|
+
// requiring subpath imports. Consuming apps can end up with any of these
|
|
7
|
+
// versions hard-pinned somewhere in their dependency tree (outside our
|
|
8
|
+
// control), so no single import style works everywhere.
|
|
9
|
+
//
|
|
10
|
+
// The one API that has stayed stable across all of these versions is the
|
|
11
|
+
// dynamic `Icon` component with a `symbol` prop, exported from the root
|
|
12
|
+
// entry point. These thin wrappers let the rest of the plugin use icons as
|
|
13
|
+
// normal components (e.g. for @sanity/ui's `icon` prop) while staying
|
|
14
|
+
// compatible with whatever @sanity/icons version ends up resolved.
|
|
15
|
+
export const UploadIcon = (props) => <Icon symbol="upload" {...props} />
|
|
16
|
+
export const SearchIcon = (props) => <Icon symbol="search" {...props} />
|
|
17
|
+
export const VideoIcon = (props) => <Icon symbol="video" {...props} />
|