sanity-plugin-utils
Version:
Handy hooks and clever components for Sanity Studio v3
1 lines • 61.4 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/components/Feedback.tsx","../src/components/Table.tsx","../src/components/UserSelectMenu/index.tsx","../node_modules/@sanity/image-url/lib/node/parseAssetId.js","../node_modules/@sanity/image-url/lib/node/parseSource.js","../node_modules/@sanity/image-url/lib/node/urlForImage.js","../node_modules/@sanity/image-url/lib/node/builder.js","../node_modules/@sanity/image-url/lib/node/index.js","../src/hooks/useImageUrlBuilder.tsx","../src/hooks/useImageUrlBuilderImage.tsx","../src/hooks/useListeningQuery.tsx","../src/hooks/useOpenInNewPane.tsx","../src/hooks/useProjectUsers.tsx"],"sourcesContent":["import {Box, Card, CardTone, Flex, Stack, Text} from '@sanity/ui'\nimport type {ReactNode} from 'react'\n\ntype FeedbackChildren = {\n children?: ReactNode\n title?: never\n description?: never\n}\n\ntype FeedbackTextProps = {\n title?: string\n description?: ReactNode\n children?: never\n}\n\ntype FeedbackProps = (FeedbackChildren | FeedbackTextProps) & {\n tone?: CardTone\n icon?: ReactNode\n}\n\nconst DEFAULT_PROPS: FeedbackProps = {\n tone: 'primary',\n}\n\nexport function Feedback(props: FeedbackProps) {\n const {title, description, icon, tone, children} = {\n ...DEFAULT_PROPS,\n ...props,\n }\n\n return (\n <Card tone={tone} padding={4} radius={3} border>\n <Flex>\n {icon ? `display icon` : null}\n {children ? (\n children\n ) : (\n <Box flex={1}>\n <Stack space={4}>\n {title ? <Text weight=\"semibold\">{title}</Text> : null}\n {description ? <Text size={2}>{description}</Text> : null}\n </Stack>\n </Box>\n )}\n </Flex>\n </Card>\n )\n}\n","import {Card, type CardProps} from '@sanity/ui'\nimport type {PropsWithChildren} from 'react'\nimport {css, styled} from 'styled-components'\n\n// Wrappers required because of bug with passing down \"as\" prop\n// https://github.com/styled-components/styled-components/issues/2449\n\n// Table\nconst TableWrapper = (props: CardProps = {}) => {\n return <Card as=\"table\" {...props} />\n}\n\nconst StyledTable = styled(TableWrapper)(\n () => css`\n display: table;\n width: 100%;\n border-collapse: collapse;\n\n &:not([hidden]) {\n display: table;\n border-collapse: collapse;\n }\n `\n)\n\ntype TableProps = PropsWithChildren<CardProps>\n\nexport function Table(props: TableProps) {\n const {children, ...rest} = props\n\n return <StyledTable {...rest}>{children}</StyledTable>\n}\n\n// Row\nconst RowWrapper = (props: CardProps = {}) => {\n return <Card as=\"tr\" {...props} />\n}\n\nconst StyledRow = styled(RowWrapper)(\n () => css`\n display: table-row;\n\n &:not([hidden]) {\n display: table-row;\n }\n `\n)\n\ntype TableRowProps = PropsWithChildren<CardProps>\n\nexport function Row(props: TableRowProps) {\n const {children, ...rest} = props\n\n return <StyledRow {...rest}>{children}</StyledRow>\n}\n\n// Cell\nconst CellWrapper = (props = {}) => {\n return <Card as=\"td\" {...props} />\n}\n\nconst StyledCell = styled(CellWrapper)(\n () => css`\n display: table-cell;\n\n &:not([hidden]) {\n display: table-cell;\n }\n `\n)\n\ntype TableCellProps = PropsWithChildren<\n CardProps & {\n colSpan?: number\n rowSpan?: number\n }\n>\n\nexport function Cell(props: TableCellProps) {\n const {children, ...rest} = props\n\n return <StyledCell {...rest}>{children}</StyledCell>\n}\n","import {AddCircleIcon, RemoveCircleIcon, RestoreIcon} from '@sanity/icons'\nimport {Badge, Box, Flex, Menu, MenuItem, Text, TextInput} from '@sanity/ui'\nimport {type ChangeEvent, useRef, useState} from 'react'\nimport {UserAvatar} from 'sanity'\n\nimport {UserExtended} from '../../hooks/useProjectUsers'\n\nfunction searchUsers(\n users: UserExtended[],\n searchString: string\n): UserExtended[] {\n return users.filter((user) => {\n const displayName = (user.displayName || '').toLowerCase()\n if (displayName.startsWith(searchString)) return true\n const givenName = (user.givenName || '').toLowerCase()\n if (givenName.startsWith(searchString)) return true\n const middleName = (user.middleName || '').toLowerCase()\n if (middleName.startsWith(searchString)) return true\n const familyName = (user.familyName || '').toLowerCase()\n if (familyName.startsWith(searchString)) return true\n\n return false\n })\n}\n\ntype Labels = {\n addMe?: string\n removeMe?: string\n clear?: string\n searchPlaceholder?: string\n notFound?: string\n}\n\ntype UserSelectMenuProps = {\n value: string[]\n userList: UserExtended[]\n onAdd: (userId: string) => void\n onRemove: (userId: string) => void\n onClear: () => void\n labels?: Labels\n style?: React.CSSProperties\n}\n\nconst LABELS: Labels = {\n addMe: 'Assign myself',\n removeMe: 'Unassign myself',\n clear: 'Clear assignees',\n searchPlaceholder: 'Search users',\n notFound: 'No users found',\n}\n\nexport function UserSelectMenu(props: UserSelectMenuProps) {\n const {\n value = [],\n userList = [],\n onAdd,\n onRemove,\n onClear,\n style = {},\n } = props\n const labels = props?.labels ? {...LABELS, ...props.labels} : LABELS\n\n const [searchString, setSearchString] = useState('')\n const searchResults = searchUsers(userList || [], searchString)\n\n const me = userList.find((u) => u.isCurrentUser)\n const meAssigned = me && value.includes(me.id)\n\n // Focus input on open\n // TODO: Fix focus, it gets immediately taken away\n const input = useRef<HTMLInputElement>(null)\n // useEffect(() => {\n // if (open && input?.current) {\n // input.current.focus()\n // }\n // }, [open])\n\n const handleSearchChange = (event: ChangeEvent<HTMLInputElement>) => {\n setSearchString(event.target.value)\n }\n\n const handleSelect = (isChecked: boolean, user: UserExtended) => {\n if (!isChecked) {\n if (onAdd) onAdd(user.id)\n } else if (onRemove) onRemove(user.id)\n }\n\n const handleAssignMyself = () => {\n if (me && onAdd) onAdd(me.id)\n }\n\n const handleUnassignMyself = () => {\n if (me && onRemove) onRemove(me.id)\n }\n\n const handleClearAssigneesClick = () => {\n if (onClear) onClear()\n }\n\n return (\n <Menu style={style}>\n {meAssigned ? (\n <MenuItem\n tone=\"caution\"\n disabled={!me}\n onClick={handleUnassignMyself}\n icon={RemoveCircleIcon}\n text={labels.removeMe}\n />\n ) : (\n <MenuItem\n tone=\"positive\"\n onClick={handleAssignMyself}\n icon={AddCircleIcon}\n text={labels.addMe}\n />\n )}\n\n <MenuItem\n tone=\"critical\"\n disabled={value.length === 0}\n onClick={handleClearAssigneesClick}\n icon={RestoreIcon}\n text={labels.clear}\n />\n\n <Box padding={1}>\n <TextInput\n ref={input}\n onChange={handleSearchChange}\n placeholder={labels.searchPlaceholder}\n value={searchString}\n />\n </Box>\n\n {searchString && searchResults?.length === 0 && (\n <MenuItem disabled text={labels.notFound} />\n )}\n\n {searchResults &&\n searchResults.map((user) => (\n <MenuItem\n key={user.id}\n pressed={value.includes(user.id)}\n onClick={() => handleSelect(value.indexOf(user.id) > -1, user)}\n >\n <Flex align=\"center\">\n <UserAvatar user={user} size={1} />\n <Box paddingX={2} flex={1}>\n <Text>{user.displayName}</Text>\n </Box>\n {user.isCurrentUser && (\n <Badge fontSize={1} tone=\"positive\" mode=\"outline\">\n Me\n </Badge>\n )}\n </Flex>\n </MenuItem>\n ))}\n </Menu>\n )\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar example = 'image-Tb9Ew8CXIwaY6R1kjMvI0uRR-2000x3000-jpg';\nfunction parseAssetId(ref) {\n var _a = ref.split('-'), id = _a[1], dimensionString = _a[2], format = _a[3];\n if (!id || !dimensionString || !format) {\n throw new Error(\"Malformed asset _ref '\".concat(ref, \"'. Expected an id like \\\"\").concat(example, \"\\\".\"));\n }\n var _b = dimensionString.split('x'), imgWidthStr = _b[0], imgHeightStr = _b[1];\n var width = +imgWidthStr;\n var height = +imgHeightStr;\n var isValidAssetId = isFinite(width) && isFinite(height);\n if (!isValidAssetId) {\n throw new Error(\"Malformed asset _ref '\".concat(ref, \"'. Expected an id like \\\"\").concat(example, \"\\\".\"));\n }\n return { id: id, width: width, height: height, format: format };\n}\nexports.default = parseAssetId;\n//# sourceMappingURL=parseAssetId.js.map","\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.isInProgressUpload = void 0;\nvar isRef = function (src) {\n var source = src;\n return source ? typeof source._ref === 'string' : false;\n};\nvar isAsset = function (src) {\n var source = src;\n return source ? typeof source._id === 'string' : false;\n};\nvar isAssetStub = function (src) {\n var source = src;\n return source && source.asset ? typeof source.asset.url === 'string' : false;\n};\n// Detect in-progress uploads (has upload key but no complete asset reference)\nvar isInProgressUpload = function (src) {\n if (typeof src === 'object' && src !== null) {\n var obj = src;\n // Check if it has an upload key (indicating in-progress upload)\n return obj._upload && (!obj.asset || !obj.asset._ref);\n }\n return false;\n};\nexports.isInProgressUpload = isInProgressUpload;\n// Convert an asset-id, asset or image to an image record suitable for processing\n// eslint-disable-next-line complexity\nfunction parseSource(source) {\n if (!source) {\n return null;\n }\n var image;\n if (typeof source === 'string' && isUrl(source)) {\n // Someone passed an existing image url?\n image = {\n asset: { _ref: urlToId(source) },\n };\n }\n else if (typeof source === 'string') {\n // Just an asset id\n image = {\n asset: { _ref: source },\n };\n }\n else if (isRef(source)) {\n // We just got passed an asset directly\n image = {\n asset: source,\n };\n }\n else if (isAsset(source)) {\n // If we were passed an image asset document\n image = {\n asset: {\n _ref: source._id || '',\n },\n };\n }\n else if (isAssetStub(source)) {\n // If we were passed a partial asset (`url`, but no `_id`)\n image = {\n asset: {\n _ref: urlToId(source.asset.url),\n },\n };\n }\n else if (typeof source.asset === 'object') {\n // Probably an actual image with materialized asset\n image = __assign({}, source);\n }\n else {\n // We got something that does not look like an image, or it is an image\n // that currently isn't sporting an asset.\n return null;\n }\n var img = source;\n if (img.crop) {\n image.crop = img.crop;\n }\n if (img.hotspot) {\n image.hotspot = img.hotspot;\n }\n return applyDefaults(image);\n}\nexports.default = parseSource;\nfunction isUrl(url) {\n return /^https?:\\/\\//.test(\"\".concat(url));\n}\nfunction urlToId(url) {\n var parts = url.split('/').slice(-1);\n return \"image-\".concat(parts[0]).replace(/\\.([a-z]+)$/, '-$1');\n}\n// Mock crop and hotspot if image lacks it\nfunction applyDefaults(image) {\n if (image.crop && image.hotspot) {\n return image;\n }\n // We need to pad in default values for crop or hotspot\n var result = __assign({}, image);\n if (!result.crop) {\n result.crop = {\n left: 0,\n top: 0,\n bottom: 0,\n right: 0,\n };\n }\n if (!result.hotspot) {\n result.hotspot = {\n x: 0.5,\n y: 0.5,\n height: 1.0,\n width: 1.0,\n };\n }\n return result;\n}\n//# sourceMappingURL=parseSource.js.map","\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.parseSource = exports.SPEC_NAME_TO_URL_NAME_MAPPINGS = void 0;\nvar parseAssetId_1 = __importDefault(require(\"./parseAssetId\"));\nvar parseSource_1 = __importStar(require(\"./parseSource\"));\nexports.parseSource = parseSource_1.default;\nexports.SPEC_NAME_TO_URL_NAME_MAPPINGS = [\n ['width', 'w'],\n ['height', 'h'],\n ['format', 'fm'],\n ['download', 'dl'],\n ['blur', 'blur'],\n ['sharpen', 'sharp'],\n ['invert', 'invert'],\n ['orientation', 'or'],\n ['minHeight', 'min-h'],\n ['maxHeight', 'max-h'],\n ['minWidth', 'min-w'],\n ['maxWidth', 'max-w'],\n ['quality', 'q'],\n ['fit', 'fit'],\n ['crop', 'crop'],\n ['saturation', 'sat'],\n ['auto', 'auto'],\n ['dpr', 'dpr'],\n ['pad', 'pad'],\n ['frame', 'frame'],\n];\nfunction urlForImage(options) {\n var spec = __assign({}, (options || {}));\n var source = spec.source;\n delete spec.source;\n var image = (0, parseSource_1.default)(source);\n if (!image) {\n if (source && (0, parseSource_1.isInProgressUpload)(source)) {\n // This is a placeholder image that will be replaced with the actual image when the upload is complete\n // This is a 0x0 transparent PNG image\n return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8HwQACfsD/QNViZkAAAAASUVORK5CYII=';\n }\n throw new Error(\"Unable to resolve image URL from source (\".concat(JSON.stringify(source), \")\"));\n }\n var id = image.asset._ref || image.asset._id || '';\n var asset = (0, parseAssetId_1.default)(id);\n // Compute crop rect in terms of pixel coordinates in the raw source image\n var cropLeft = Math.round(image.crop.left * asset.width);\n var cropTop = Math.round(image.crop.top * asset.height);\n var crop = {\n left: cropLeft,\n top: cropTop,\n width: Math.round(asset.width - image.crop.right * asset.width - cropLeft),\n height: Math.round(asset.height - image.crop.bottom * asset.height - cropTop),\n };\n // Compute hot spot rect in terms of pixel coordinates\n var hotSpotVerticalRadius = (image.hotspot.height * asset.height) / 2;\n var hotSpotHorizontalRadius = (image.hotspot.width * asset.width) / 2;\n var hotSpotCenterX = image.hotspot.x * asset.width;\n var hotSpotCenterY = image.hotspot.y * asset.height;\n var hotspot = {\n left: hotSpotCenterX - hotSpotHorizontalRadius,\n top: hotSpotCenterY - hotSpotVerticalRadius,\n right: hotSpotCenterX + hotSpotHorizontalRadius,\n bottom: hotSpotCenterY + hotSpotVerticalRadius,\n };\n // If irrelevant, or if we are requested to: don't perform crop/fit based on\n // the crop/hotspot.\n if (!(spec.rect || spec.focalPoint || spec.ignoreImageParams || spec.crop)) {\n spec = __assign(__assign({}, spec), fit({ crop: crop, hotspot: hotspot }, spec));\n }\n return specToImageUrl(__assign(__assign({}, spec), { asset: asset }));\n}\nexports.default = urlForImage;\n// eslint-disable-next-line complexity\nfunction specToImageUrl(spec) {\n var cdnUrl = (spec.baseUrl || 'https://cdn.sanity.io').replace(/\\/+$/, '');\n var vanityStub = spec.vanityName ? \"/\".concat(spec.vanityName) : '';\n var filename = \"\".concat(spec.asset.id, \"-\").concat(spec.asset.width, \"x\").concat(spec.asset.height, \".\").concat(spec.asset.format).concat(vanityStub);\n var baseUrl = \"\".concat(cdnUrl, \"/images/\").concat(spec.projectId, \"/\").concat(spec.dataset, \"/\").concat(filename);\n var params = [];\n if (spec.rect) {\n // Only bother url with a crop if it actually crops anything\n var _a = spec.rect, left = _a.left, top_1 = _a.top, width = _a.width, height = _a.height;\n var isEffectiveCrop = left !== 0 || top_1 !== 0 || height !== spec.asset.height || width !== spec.asset.width;\n if (isEffectiveCrop) {\n params.push(\"rect=\".concat(left, \",\").concat(top_1, \",\").concat(width, \",\").concat(height));\n }\n }\n if (spec.bg) {\n params.push(\"bg=\".concat(spec.bg));\n }\n if (spec.focalPoint) {\n params.push(\"fp-x=\".concat(spec.focalPoint.x));\n params.push(\"fp-y=\".concat(spec.focalPoint.y));\n }\n var flip = [spec.flipHorizontal && 'h', spec.flipVertical && 'v'].filter(Boolean).join('');\n if (flip) {\n params.push(\"flip=\".concat(flip));\n }\n // Map from spec name to url param name, and allow using the actual param name as an alternative\n exports.SPEC_NAME_TO_URL_NAME_MAPPINGS.forEach(function (mapping) {\n var specName = mapping[0], param = mapping[1];\n if (typeof spec[specName] !== 'undefined') {\n params.push(\"\".concat(param, \"=\").concat(encodeURIComponent(spec[specName])));\n }\n else if (typeof spec[param] !== 'undefined') {\n params.push(\"\".concat(param, \"=\").concat(encodeURIComponent(spec[param])));\n }\n });\n if (params.length === 0) {\n return baseUrl;\n }\n return \"\".concat(baseUrl, \"?\").concat(params.join('&'));\n}\nfunction fit(source, spec) {\n var cropRect;\n var imgWidth = spec.width;\n var imgHeight = spec.height;\n // If we are not constraining the aspect ratio, we'll just use the whole crop\n if (!(imgWidth && imgHeight)) {\n return { width: imgWidth, height: imgHeight, rect: source.crop };\n }\n var crop = source.crop;\n var hotspot = source.hotspot;\n // If we are here, that means aspect ratio is locked and fitting will be a bit harder\n var desiredAspectRatio = imgWidth / imgHeight;\n var cropAspectRatio = crop.width / crop.height;\n if (cropAspectRatio > desiredAspectRatio) {\n // The crop is wider than the desired aspect ratio. That means we are cutting from the sides\n var height = Math.round(crop.height);\n var width = Math.round(height * desiredAspectRatio);\n var top_2 = Math.max(0, Math.round(crop.top));\n // Center output horizontally over hotspot\n var hotspotXCenter = Math.round((hotspot.right - hotspot.left) / 2 + hotspot.left);\n var left = Math.max(0, Math.round(hotspotXCenter - width / 2));\n // Keep output within crop\n if (left < crop.left) {\n left = crop.left;\n }\n else if (left + width > crop.left + crop.width) {\n left = crop.left + crop.width - width;\n }\n cropRect = { left: left, top: top_2, width: width, height: height };\n }\n else {\n // The crop is taller than the desired ratio, we are cutting from top and bottom\n var width = crop.width;\n var height = Math.round(width / desiredAspectRatio);\n var left = Math.max(0, Math.round(crop.left));\n // Center output vertically over hotspot\n var hotspotYCenter = Math.round((hotspot.bottom - hotspot.top) / 2 + hotspot.top);\n var top_3 = Math.max(0, Math.round(hotspotYCenter - height / 2));\n // Keep output rect within crop\n if (top_3 < crop.top) {\n top_3 = crop.top;\n }\n else if (top_3 + height > crop.top + crop.height) {\n top_3 = crop.top + crop.height - height;\n }\n cropRect = { left: left, top: top_3, width: width, height: height };\n }\n return {\n width: imgWidth,\n height: imgHeight,\n rect: cropRect,\n };\n}\n//# sourceMappingURL=urlForImage.js.map","\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.ImageUrlBuilder = void 0;\nvar urlForImage_1 = __importStar(require(\"./urlForImage\"));\nvar validFits = ['clip', 'crop', 'fill', 'fillmax', 'max', 'scale', 'min'];\nvar validCrops = ['top', 'bottom', 'left', 'right', 'center', 'focalpoint', 'entropy'];\nvar validAutoModes = ['format'];\nfunction isSanityModernClientLike(client) {\n return client && 'config' in client ? typeof client.config === 'function' : false;\n}\nfunction isSanityClientLike(client) {\n return client && 'clientConfig' in client ? typeof client.clientConfig === 'object' : false;\n}\nfunction rewriteSpecName(key) {\n var specs = urlForImage_1.SPEC_NAME_TO_URL_NAME_MAPPINGS;\n for (var _i = 0, specs_1 = specs; _i < specs_1.length; _i++) {\n var entry = specs_1[_i];\n var specName = entry[0], param = entry[1];\n if (key === specName || key === param) {\n return specName;\n }\n }\n return key;\n}\nfunction urlBuilder(options) {\n // Did we get a modernish client?\n if (isSanityModernClientLike(options)) {\n // Inherit config from client\n var _a = options.config(), apiUrl = _a.apiHost, projectId = _a.projectId, dataset = _a.dataset;\n var apiHost = apiUrl || 'https://api.sanity.io';\n return new ImageUrlBuilder(null, {\n baseUrl: apiHost.replace(/^https:\\/\\/api\\./, 'https://cdn.'),\n projectId: projectId,\n dataset: dataset,\n });\n }\n // Did we get a SanityClient?\n if (isSanityClientLike(options)) {\n // Inherit config from client\n var _b = options.clientConfig, apiUrl = _b.apiHost, projectId = _b.projectId, dataset = _b.dataset;\n var apiHost = apiUrl || 'https://api.sanity.io';\n return new ImageUrlBuilder(null, {\n baseUrl: apiHost.replace(/^https:\\/\\/api\\./, 'https://cdn.'),\n projectId: projectId,\n dataset: dataset,\n });\n }\n // Or just accept the options as given\n return new ImageUrlBuilder(null, options || {});\n}\nexports.default = urlBuilder;\nvar ImageUrlBuilder = /** @class */ (function () {\n function ImageUrlBuilder(parent, options) {\n this.options = parent\n ? __assign(__assign({}, (parent.options || {})), (options || {})) : __assign({}, (options || {})); // Copy options\n }\n ImageUrlBuilder.prototype.withOptions = function (options) {\n var baseUrl = options.baseUrl || this.options.baseUrl;\n var newOptions = { baseUrl: baseUrl };\n for (var key in options) {\n if (options.hasOwnProperty(key)) {\n var specKey = rewriteSpecName(key);\n newOptions[specKey] = options[key];\n }\n }\n return new ImageUrlBuilder(this, __assign({ baseUrl: baseUrl }, newOptions));\n };\n // The image to be represented. Accepts a Sanity 'image'-document, 'asset'-document or\n // _id of asset. To get the benefit of automatic hot-spot/crop integration with the content\n // studio, the 'image'-document must be provided.\n ImageUrlBuilder.prototype.image = function (source) {\n return this.withOptions({ source: source });\n };\n // Specify the dataset\n ImageUrlBuilder.prototype.dataset = function (dataset) {\n return this.withOptions({ dataset: dataset });\n };\n // Specify the projectId\n ImageUrlBuilder.prototype.projectId = function (projectId) {\n return this.withOptions({ projectId: projectId });\n };\n // Specify background color\n ImageUrlBuilder.prototype.bg = function (bg) {\n return this.withOptions({ bg: bg });\n };\n // Set DPR scaling factor\n ImageUrlBuilder.prototype.dpr = function (dpr) {\n // A DPR of 1 is the default - so only include it if we have a different value\n return this.withOptions(dpr && dpr !== 1 ? { dpr: dpr } : {});\n };\n // Specify the width of the image in pixels\n ImageUrlBuilder.prototype.width = function (width) {\n return this.withOptions({ width: width });\n };\n // Specify the height of the image in pixels\n ImageUrlBuilder.prototype.height = function (height) {\n return this.withOptions({ height: height });\n };\n // Specify focal point in fraction of image dimensions. Each component 0.0-1.0\n ImageUrlBuilder.prototype.focalPoint = function (x, y) {\n return this.withOptions({ focalPoint: { x: x, y: y } });\n };\n ImageUrlBuilder.prototype.maxWidth = function (maxWidth) {\n return this.withOptions({ maxWidth: maxWidth });\n };\n ImageUrlBuilder.prototype.minWidth = function (minWidth) {\n return this.withOptions({ minWidth: minWidth });\n };\n ImageUrlBuilder.prototype.maxHeight = function (maxHeight) {\n return this.withOptions({ maxHeight: maxHeight });\n };\n ImageUrlBuilder.prototype.minHeight = function (minHeight) {\n return this.withOptions({ minHeight: minHeight });\n };\n // Specify width and height in pixels\n ImageUrlBuilder.prototype.size = function (width, height) {\n return this.withOptions({ width: width, height: height });\n };\n // Specify blur between 0 and 100\n ImageUrlBuilder.prototype.blur = function (blur) {\n return this.withOptions({ blur: blur });\n };\n ImageUrlBuilder.prototype.sharpen = function (sharpen) {\n return this.withOptions({ sharpen: sharpen });\n };\n // Specify the desired rectangle of the image\n ImageUrlBuilder.prototype.rect = function (left, top, width, height) {\n return this.withOptions({ rect: { left: left, top: top, width: width, height: height } });\n };\n // Specify the image format of the image. 'jpg', 'pjpg', 'png', 'webp'\n ImageUrlBuilder.prototype.format = function (format) {\n return this.withOptions({ format: format });\n };\n ImageUrlBuilder.prototype.invert = function (invert) {\n return this.withOptions({ invert: invert });\n };\n // Rotation in degrees 0, 90, 180, 270\n ImageUrlBuilder.prototype.orientation = function (orientation) {\n return this.withOptions({ orientation: orientation });\n };\n // Compression quality 0-100\n ImageUrlBuilder.prototype.quality = function (quality) {\n return this.withOptions({ quality: quality });\n };\n // Make it a download link. Parameter is default filename.\n ImageUrlBuilder.prototype.forceDownload = function (download) {\n return this.withOptions({ download: download });\n };\n // Flip image horizontally\n ImageUrlBuilder.prototype.flipHorizontal = function () {\n return this.withOptions({ flipHorizontal: true });\n };\n // Flip image vertically\n ImageUrlBuilder.prototype.flipVertical = function () {\n return this.withOptions({ flipVertical: true });\n };\n // Ignore crop/hotspot from image record, even when present\n ImageUrlBuilder.prototype.ignoreImageParams = function () {\n return this.withOptions({ ignoreImageParams: true });\n };\n ImageUrlBuilder.prototype.fit = function (value) {\n if (validFits.indexOf(value) === -1) {\n throw new Error(\"Invalid fit mode \\\"\".concat(value, \"\\\"\"));\n }\n return this.withOptions({ fit: value });\n };\n ImageUrlBuilder.prototype.crop = function (value) {\n if (validCrops.indexOf(value) === -1) {\n throw new Error(\"Invalid crop mode \\\"\".concat(value, \"\\\"\"));\n }\n return this.withOptions({ crop: value });\n };\n // Saturation\n ImageUrlBuilder.prototype.saturation = function (saturation) {\n return this.withOptions({ saturation: saturation });\n };\n ImageUrlBuilder.prototype.auto = function (value) {\n if (validAutoModes.indexOf(value) === -1) {\n throw new Error(\"Invalid auto mode \\\"\".concat(value, \"\\\"\"));\n }\n return this.withOptions({ auto: value });\n };\n // Specify the number of pixels to pad the image\n ImageUrlBuilder.prototype.pad = function (pad) {\n return this.withOptions({ pad: pad });\n };\n // Vanity URL for more SEO friendly URLs\n ImageUrlBuilder.prototype.vanityName = function (value) {\n return this.withOptions({ vanityName: value });\n };\n ImageUrlBuilder.prototype.frame = function (frame) {\n if (frame !== 1) {\n throw new Error(\"Invalid frame value \\\"\".concat(frame, \"\\\"\"));\n }\n return this.withOptions({ frame: frame });\n };\n // Gets the url based on the submitted parameters\n ImageUrlBuilder.prototype.url = function () {\n return (0, urlForImage_1.default)(this.options);\n };\n // Alias for url()\n ImageUrlBuilder.prototype.toString = function () {\n return this.url();\n };\n return ImageUrlBuilder;\n}());\nexports.ImageUrlBuilder = ImageUrlBuilder;\n//# sourceMappingURL=builder.js.map","\"use strict\";\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nvar builder_1 = __importDefault(require(\"./builder\"));\nmodule.exports = builder_1.default;\n//# sourceMappingURL=index.js.map","import createImageUrlBuilder from '@sanity/image-url'\nimport {useMemo} from 'react'\nimport type {ImageUrlBuilder, SourceClientOptions} from 'sanity'\nimport {useClient} from 'sanity'\n\nexport function useImageUrlBuilder(\n clientOptions: SourceClientOptions\n): ImageUrlBuilder | null {\n const client = useClient(clientOptions)\n const builder = useMemo(() => createImageUrlBuilder(client), [client])\n\n return builder\n}\n","import type {SanityImageSource} from '@sanity/asset-utils'\nimport {useMemo} from 'react'\nimport type {ImageUrlBuilder, SourceClientOptions} from 'sanity'\n\nimport {useImageUrlBuilder} from './useImageUrlBuilder'\n\nexport function useImageUrlBuilderImage(\n source: SanityImageSource,\n clientOptions: SourceClientOptions\n): ImageUrlBuilder | null {\n const builder = useImageUrlBuilder(clientOptions)\n const image = useMemo(\n () => (source && builder ? builder.image(source) : null),\n [builder, source]\n )\n\n return image\n}\n","import {useEffect, useMemo, useRef, useState} from 'react'\nimport isEqual from 'react-fast-compare'\nimport {Subscription} from 'rxjs'\nimport {catchError, distinctUntilChanged} from 'rxjs/operators'\nimport {ListenQueryOptions, ListenQueryParams, useDocumentStore} from 'sanity'\n\ntype Value = unknown\n\ninterface Config<V> {\n params?: ListenQueryParams\n options?: ListenQueryOptions\n initialValue?: null | V\n}\n\n// make generic optional\ninterface Return<V = Value> {\n loading: boolean\n error: boolean | unknown | ProgressEvent\n data: unknown | V\n initialValue?: Value\n}\n\nconst DEFAULT_PARAMS = {}\nconst DEFAULT_OPTIONS = {apiVersion: `v2023-05-01`}\nconst DEFAULT_INITIAL_VALUE = null\n\nfunction useParams(\n params?: undefined | null | ListenQueryParams | ListenQueryOptions\n): ListenQueryParams {\n const stringifiedParams = useMemo(\n () => JSON.stringify(params || {}),\n [params]\n )\n return useMemo(() => JSON.parse(stringifiedParams), [stringifiedParams])\n}\n\nexport function useListeningQuery<V>(\n query: string | {fetch: string; listen: string},\n {\n params = DEFAULT_PARAMS,\n options = DEFAULT_OPTIONS,\n initialValue = DEFAULT_INITIAL_VALUE,\n }: Config<V>\n): Return<V> {\n const [loading, setLoading] = useState<Return['loading']>(true)\n const [error, setError] = useState<Return['error']>(false)\n const [data, setData] = useState<Return['data']>(initialValue)\n const memoParams = useParams(params)\n const memoOptions = useParams(options)\n\n const subscription = useRef<null | Subscription>(null)\n const documentStore = useDocumentStore()\n\n useEffect(() => {\n if (query && !error && !subscription.current) {\n try {\n subscription.current = documentStore\n .listenQuery(query, memoParams, memoOptions)\n .pipe(\n distinctUntilChanged(isEqual),\n catchError((err) => {\n console.error(err)\n setError(err)\n setLoading(false)\n setData(null)\n\n return err\n })\n )\n .subscribe((documents) => {\n setData((current: Value) =>\n isEqual(current, documents) ? current : documents\n )\n setLoading(false)\n setError(false)\n })\n } catch (err) {\n console.error(err)\n setLoading(false)\n setError(err)\n }\n }\n\n // Unsubscribe when an error occurs\n if (error && subscription.current) {\n subscription.current.unsubscribe()\n }\n\n return () => {\n if (subscription.current) {\n subscription?.current?.unsubscribe()\n subscription.current = null\n }\n }\n }, [query, error, memoParams, memoOptions, documentStore])\n\n return {data, loading, error}\n}\n","import {useCallback, useContext} from 'react'\nimport {RouterContext} from 'sanity/router'\nimport {usePaneRouter} from 'sanity/structure'\n\nexport function useOpenInNewPane(id?: string, type?: string) {\n const routerContext = useContext(RouterContext)\n const {routerPanesState, groupIndex} = usePaneRouter()\n\n const openInNewPane = useCallback(() => {\n if (!routerContext || !id || !type) {\n return\n }\n\n const panes = [...routerPanesState]\n panes.splice(groupIndex + 1, 0, [\n {\n id: id,\n params: {type},\n },\n ])\n\n const href = routerContext.resolvePathFromState({panes})\n routerContext.navigateUrl({path: href})\n }, [id, type, routerContext, routerPanesState, groupIndex])\n\n return openInNewPane\n}\n","import {useEffect, useState} from 'react'\nimport {useClient, useWorkspace} from 'sanity'\n\nexport type UserExtended = {\n createdAt: string\n displayName: string\n email: string\n familyName: string\n givenName: string\n id: string\n imageUrl: string\n isCurrentUser: boolean\n middleName: string\n projectId: string\n provider: string\n sanityUserId: string\n updatedAt: string\n}\n\ntype UserRole = {\n name: string\n title: string\n}\n\ntype UserResponse = {\n isRobot: boolean\n projectUserId: string\n roles: UserRole[]\n}\n\ntype HookConfig = {\n apiVersion?: string\n}\n\nfunction chunkArray<T>(array: T[], size: number): T[][] {\n const chunks: T[][] = []\n for (let i = 0; i < array.length; i += size) {\n chunks.push(array.slice(i, i + size))\n }\n return chunks\n}\n\n// Custom hook to fetch user details and roles in batches\nexport function useProjectUsers({apiVersion}: HookConfig): UserExtended[] {\n const {currentUser} = useWorkspace()\n const client = useClient({apiVersion: apiVersion ?? '2023-01-01'})\n const [users, setUsers] = useState<UserExtended[]>([])\n\n useEffect(() => {\n const {projectId} = client.config()\n\n async function getUsersWithRoles() {\n try {\n const aclData = await client.request({\n url: `/projects/${projectId}/acl`,\n })\n\n const userIds = aclData.map((user: UserResponse) => user.projectUserId)\n\n const userIdChunks = chunkArray(userIds, 200)\n\n let usersData: UserExtended[] = []\n\n // Fetch users in batches of 200\n for (const chunk of userIdChunks) {\n const chunkedUserIds = chunk.join(',')\n const response = await client.request({\n url: `/projects/${projectId}/users/${chunkedUserIds}`,\n })\n usersData = [...usersData, ...response]\n }\n\n // Combine user details with roles\n const usersWithRoles = usersData.map((user: UserExtended) => {\n const userRoles =\n aclData.find(\n (aclUser: UserResponse) => aclUser.projectUserId === user.id\n )?.roles || []\n\n return {\n ...user,\n isCurrentUser: user.id === currentUser?.id,\n roles: userRoles,\n }\n })\n\n setUsers(usersWithRoles)\n } catch (err) {\n console.error('Failed to fetch users:', err)\n }\n }\n\n if (!users.length) {\n getUsersWithRoles()\n }\n }, [client, currentUser?.id, users.length])\n\n return users\n}\n"],"names":["jsx","Card","jsxs","Flex","Box","Stack","Text","styled","css","useState","useRef","Menu","MenuItem","RemoveCircleIcon","AddCircleIcon","RestoreIcon","TextInput","UserAvatar","Badge","parseAssetId_1","parseAssetId","this","parseSource_1","parseSource","exports","require$$0","require$$1","urlForImage","ImageUrlBuilder","useClient","useMemo","builder","useDocumentStore","useEffect","distinctUntilChanged","isEqual","catchError","useContext","RouterContext","usePaneRouter","useCallback","useWorkspace"],"mappings":"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