sanity
Version:
Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches
714 lines (709 loc) • 4.3 MB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: !0 });
var jsxRuntime = require("react/jsx-runtime"), reactCompilerRuntime = require("react-compiler-runtime"), PathUtils = require("@sanity/util/paths"), React = require("react"), deepEquals = require("react-fast-compare"), _singletons = require("sanity/_singletons"), ui = require("@sanity/ui"), reactVirtual = require("@tanstack/react-virtual"), throttle = require("lodash/throttle.js"), styledComponents = require("styled-components"), icons = require("@sanity/icons"), TooltipDelayGroupProvider = require("./_chunks-cjs/TooltipDelayGroupProvider.js");
require("./_singletons.js");
var resizeObserver$1 = require("@juggle/resize-observer"), createPubSub = require("nano-pubsub"), color = require("@sanity/color"), color2k = require("color2k"), reactI18next = require("react-i18next"), types = require("@sanity/types"), rxjs = require("rxjs"), operators = require("rxjs/operators"), client = require("@sanity/client"), isEqual$2 = require("lodash/isEqual.js"), memoize$1 = require("lodash/memoize.js"), version = require("./_chunks-cjs/version.js"), reactRx = require("react-rx"), observableCallback = require("observable-callback"), bifurClient = require("@sanity/bifur-client"), debug$9 = require("debug"), startCase = require("lodash/startCase.js"), reactIs = require("react-is"), uniqueId = require("lodash/uniqueId.js"), isHotkeyEsm = require("is-hotkey-esm"), FocusLock = require("react-focus-lock"), telemetry = require("@sanity/telemetry"), useEffectEvent = require("use-effect-event"), flatten$1 = require("lodash/flatten.js"), react = require("@sanity/telemetry/react"), last = require("lodash/last.js"), legacyDateFormat = require("@sanity/util/legacyDateFormat"), assetUtils = require("@sanity/asset-utils"), imageUrlBuilder = require("@sanity/image-url"), nanoid = require("nanoid"), dateFns = require("date-fns"), DataLoader = require("dataloader"), theme = require("@sanity/ui/theme"), rxjsMergemapArray = require("rxjs-mergemap-array"), router = require("sanity/router"), isString$1 = require("lodash/isString.js"), framerMotion = require("framer-motion"), sortBy = require("lodash/sortBy.js"), uniqBy = require("lodash/uniqBy.js"), debounce = require("lodash/debounce.js"), groupBy = require("lodash/groupBy.js"), orderBy = require("lodash/orderBy.js"), useDevicePixelRatio = require("use-device-pixel-ratio"), classNames = require("classnames"), _internal = require("@sanity/schema/_internal"), compact = require("lodash/compact.js"), flow = require("lodash/flow.js"), toLower = require("lodash/toLower.js"), trim = require("lodash/trim.js"), union = require("lodash/union.js"), uniq = require("lodash/uniq.js"), words = require("lodash/words.js"), content = require("@sanity/util/content"), get = require("lodash/get.js"), intersection = require("lodash/intersection.js"), isEmpty$1 = require("lodash/isEmpty.js"), isPlainObject$1 = require("lodash/isPlainObject.js"), capitalize = require("lodash/capitalize.js"), core = require("@dnd-kit/core"), modifiers = require("@dnd-kit/modifiers"), sortable = require("@dnd-kit/sortable"), utilities = require("@dnd-kit/utilities"), shallowEquals = require("shallow-equals"), react$1 = require("@portabletext/react"), editor$1 = require("@portabletext/editor"), schema$1 = require("@sanity/schema"), plugins = require("@portabletext/editor/plugins"), partition = require("lodash/partition.js"), template = require("lodash/template.js"), cloneDeep = require("lodash/cloneDeep.js"), i18next = require("i18next"), diffMatchPatch$1 = require("@sanity/diff-match-patch"), scrollIntoView$1 = require("scroll-into-view-if-needed"), difference = require("lodash/difference.js"), range = require("lodash/range.js"), cloneObject = require("date-fns/_lib/cloneObject/index.js"), dateFnsFormat = require("date-fns/format/index.js"), toInteger = require("date-fns/_lib/toInteger/index.js"), getTimezoneOffsetInMilliseconds = require("date-fns/_lib/getTimezoneOffsetInMilliseconds/index.js"), _createContext = require("sanity/_createContext"), index_js = require("use-sync-external-store/shim/index.js"), uuid = require("@sanity/uuid"), castArray = require("lodash/castArray.js"), MenuGroup = require("./_chunks-cjs/MenuGroup.js"), deburr = require("lodash/deburr.js"), blockTools = require("@portabletext/block-tools"), keyBy = require("lodash/keyBy.js"), QuickLRU = require("quick-lru"), pick = require("lodash/pick.js"), omit = require("lodash/omit.js"), mutator = require("@sanity/mutator"), sample = require("lodash/sample.js"), isFinite = require("lodash/isFinite.js"), generateHelpUrl_esm = require("./_chunks-cjs/generate-help-url.esm.js"), reactRefractor = require("react-refractor"), bash = require("refractor/bash"), javascript = require("refractor/javascript"), json = require("refractor/json"), jsx2 = require("refractor/jsx"), typescript = require("refractor/typescript"), react$2 = require("@sentry/react"), history$1 = require("history"), withSelector = require("use-sync-external-store/with-selector"), escapeRegExp$1 = require("lodash/escapeRegExp.js"), logos = require("@sanity/logos"), semver = require("semver"), useHotModuleReload = require("use-hot-module-reload"), isObject = require("lodash/isObject.js"), arrify = require("arrify"), server = require("react-dom/server"), upperFirst = require("lodash/upperFirst.js"), csm = require("@sanity/client/csm"), exif = require("exif-component"), groqJs = require("groq-js"), insertMenu = require("@sanity/insert-menu"), mendoza = require("mendoza"), noop$6 = require("lodash/noop.js"), rxjsExhaustmapWithTrailing = require("rxjs-exhaustmap-with-trailing"), findIndex$1 = require("lodash/findIndex.js"), behaviors = require("@portabletext/editor/behaviors"), find = require("lodash/find.js"), getRandomValues = require("get-random-values-esm"), clone = require("lodash/clone.js"), jsonReduce = require("json-reduce"), client$1 = require("@sanity/util/client"), concurrencyLimiter = require("@sanity/util/concurrency-limiter"), speakingurl = require("speakingurl"), sortedIndex = require("lodash/sortedIndex.js"), identity$2 = require("lodash/identity.js"), values = require("lodash/values.js"), comlink = require("@sanity/comlink"), diff = require("@sanity/diff"), raf = require("raf"), xor = require("lodash/xor.js"), diffPatch = require("@sanity/diff-patch"), client$2 = require("react-dom/client"), polished = require("polished");
function _interopDefaultCompat(e) {
return e && typeof e == "object" && "default" in e ? e : { default: e };
}
function _interopNamespaceCompat(e) {
if (e && typeof e == "object" && "default" in e) return e;
var n = /* @__PURE__ */ Object.create(null);
return e && Object.keys(e).forEach(function(k) {
if (k !== "default") {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: !0,
get: function() {
return e[k];
}
});
}
}), n.default = e, Object.freeze(n);
}
var PathUtils__namespace = /* @__PURE__ */ _interopNamespaceCompat(PathUtils), React__default = /* @__PURE__ */ _interopDefaultCompat(React), deepEquals__default = /* @__PURE__ */ _interopDefaultCompat(deepEquals), throttle__default = /* @__PURE__ */ _interopDefaultCompat(throttle), createPubSub__default = /* @__PURE__ */ _interopDefaultCompat(createPubSub), isEqual__default = /* @__PURE__ */ _interopDefaultCompat(isEqual$2), memoize__default = /* @__PURE__ */ _interopDefaultCompat(memoize$1), debug__default = /* @__PURE__ */ _interopDefaultCompat(debug$9), startCase__default = /* @__PURE__ */ _interopDefaultCompat(startCase), uniqueId__default = /* @__PURE__ */ _interopDefaultCompat(uniqueId), FocusLock__default = /* @__PURE__ */ _interopDefaultCompat(FocusLock), flatten__default = /* @__PURE__ */ _interopDefaultCompat(flatten$1), last__default = /* @__PURE__ */ _interopDefaultCompat(last), legacyDateFormat__namespace = /* @__PURE__ */ _interopNamespaceCompat(legacyDateFormat), imageUrlBuilder__default = /* @__PURE__ */ _interopDefaultCompat(imageUrlBuilder), DataLoader__default = /* @__PURE__ */ _interopDefaultCompat(DataLoader), isString__default = /* @__PURE__ */ _interopDefaultCompat(isString$1), sortBy__default = /* @__PURE__ */ _interopDefaultCompat(sortBy), uniqBy__default = /* @__PURE__ */ _interopDefaultCompat(uniqBy), debounce__default = /* @__PURE__ */ _interopDefaultCompat(debounce), groupBy__default = /* @__PURE__ */ _interopDefaultCompat(groupBy), orderBy__default = /* @__PURE__ */ _interopDefaultCompat(orderBy), classNames__default = /* @__PURE__ */ _interopDefaultCompat(classNames), compact__default = /* @__PURE__ */ _interopDefaultCompat(compact), flow__default = /* @__PURE__ */ _interopDefaultCompat(flow), toLower__default = /* @__PURE__ */ _interopDefaultCompat(toLower), trim__default = /* @__PURE__ */ _interopDefaultCompat(trim), union__default = /* @__PURE__ */ _interopDefaultCompat(union), uniq__default = /* @__PURE__ */ _interopDefaultCompat(uniq), words__default = /* @__PURE__ */ _interopDefaultCompat(words), get__default = /* @__PURE__ */ _interopDefaultCompat(get), intersection__default = /* @__PURE__ */ _interopDefaultCompat(intersection), isEmpty__default = /* @__PURE__ */ _interopDefaultCompat(isEmpty$1), isPlainObject__default = /* @__PURE__ */ _interopDefaultCompat(isPlainObject$1), capitalize__default = /* @__PURE__ */ _interopDefaultCompat(capitalize), shallowEquals__default = /* @__PURE__ */ _interopDefaultCompat(shallowEquals), partition__default = /* @__PURE__ */ _interopDefaultCompat(partition), template__default = /* @__PURE__ */ _interopDefaultCompat(template), cloneDeep__default = /* @__PURE__ */ _interopDefaultCompat(cloneDeep), scrollIntoView__default = /* @__PURE__ */ _interopDefaultCompat(scrollIntoView$1), difference__default = /* @__PURE__ */ _interopDefaultCompat(difference), range__default = /* @__PURE__ */ _interopDefaultCompat(range), cloneObject__default = /* @__PURE__ */ _interopDefaultCompat(cloneObject), dateFnsFormat__default = /* @__PURE__ */ _interopDefaultCompat(dateFnsFormat), toInteger__default = /* @__PURE__ */ _interopDefaultCompat(toInteger), getTimezoneOffsetInMilliseconds__default = /* @__PURE__ */ _interopDefaultCompat(getTimezoneOffsetInMilliseconds), castArray__default = /* @__PURE__ */ _interopDefaultCompat(castArray), deburr__default = /* @__PURE__ */ _interopDefaultCompat(deburr), keyBy__default = /* @__PURE__ */ _interopDefaultCompat(keyBy), QuickLRU__default = /* @__PURE__ */ _interopDefaultCompat(QuickLRU), pick__default = /* @__PURE__ */ _interopDefaultCompat(pick), omit__default = /* @__PURE__ */ _interopDefaultCompat(omit), sample__default = /* @__PURE__ */ _interopDefaultCompat(sample), isFinite__default = /* @__PURE__ */ _interopDefaultCompat(isFinite), bash__default = /* @__PURE__ */ _interopDefaultCompat(bash), javascript__default = /* @__PURE__ */ _interopDefaultCompat(javascript), json__default = /* @__PURE__ */ _interopDefaultCompat(json), jsx2__default = /* @__PURE__ */ _interopDefaultCompat(jsx2), typescript__default = /* @__PURE__ */ _interopDefaultCompat(typescript), escapeRegExp__default = /* @__PURE__ */ _interopDefaultCompat(escapeRegExp$1), semver__default = /* @__PURE__ */ _interopDefaultCompat(semver), isObject__default = /* @__PURE__ */ _interopDefaultCompat(isObject), arrify__default = /* @__PURE__ */ _interopDefaultCompat(arrify), upperFirst__default = /* @__PURE__ */ _interopDefaultCompat(upperFirst), exif__default = /* @__PURE__ */ _interopDefaultCompat(exif), noop__default = /* @__PURE__ */ _interopDefaultCompat(noop$6), findIndex__default = /* @__PURE__ */ _interopDefaultCompat(findIndex$1), find__default = /* @__PURE__ */ _interopDefaultCompat(find), getRandomValues__default = /* @__PURE__ */ _interopDefaultCompat(getRandomValues), clone__default = /* @__PURE__ */ _interopDefaultCompat(clone), speakingurl__default = /* @__PURE__ */ _interopDefaultCompat(speakingurl), sortedIndex__default = /* @__PURE__ */ _interopDefaultCompat(sortedIndex), identity__default = /* @__PURE__ */ _interopDefaultCompat(identity$2), values__default = /* @__PURE__ */ _interopDefaultCompat(values), raf__default = /* @__PURE__ */ _interopDefaultCompat(raf), xor__default = /* @__PURE__ */ _interopDefaultCompat(xor);
function BetaBadge(props2) {
const $ = reactCompilerRuntime.c(8);
let rest, t0, t1;
$[0] !== props2 ? ({
fontSize: t0,
children: t1,
...rest
} = props2, $[0] = props2, $[1] = rest, $[2] = t0, $[3] = t1) : (rest = $[1], t0 = $[2], t1 = $[3]);
const fontSize = t0 === void 0 ? 1 : t0, children = t1 === void 0 ? "Beta" : t1;
let t2;
return $[4] !== children || $[5] !== fontSize || $[6] !== rest ? (t2 = /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { ...rest, fontSize, radius: 2, tone: "primary", children }), $[4] = children, $[5] = fontSize, $[6] = rest, $[7] = t2) : t2 = $[7], t2;
}
function focusRingBorderStyle$3(border) {
return `inset 0 0 0 ${border.width}px ${border.color}`;
}
const AlignedBottomGrid$1 = styledComponents.styled(ui.Grid)`
align-items: flex-end;
`;
function focusRingStyle$2(opts) {
const {
base,
border,
focusRing
} = opts, focusRingOutsetWidth = focusRing.offset + focusRing.width, focusRingInsetWidth = 0 - focusRing.offset, bgColor = base ? base.bg : "var(--card-bg-color)";
return [focusRingInsetWidth > 0 && `inset 0 0 0 ${focusRingInsetWidth}px var(--card-focus-ring-color)`, border && focusRingBorderStyle$3(border), focusRingInsetWidth < 0 && `0 0 0 ${0 - focusRingInsetWidth}px ${bgColor}`, focusRingOutsetWidth > 0 && `0 0 0 ${focusRingOutsetWidth}px var(--card-focus-ring-color)`].filter(Boolean).join(",");
}
const LIST_ITEM_DATA_ATTR_ACTIVE = "data-active", LIST_ITEM_INTERACTIVE_SELECTOR = "a,button", FocusOverlayDiv = styledComponents.styled.div(({
theme: theme2,
offset
}) => styledComponents.css`
bottom: ${-offset}px;
border-radius: ${ui.rem(theme2.sanity.radius[1])};
left: ${-offset}px;
pointer-events: none;
position: absolute;
right: ${-offset}px;
top: ${-offset}px;
z-index: 2;
${VirtualListBox}:focus-visible & {
box-shadow: ${focusRingStyle$2({
base: theme2.sanity.color.base,
focusRing: theme2.sanity.focusRing
})};
}
`), PointerOverlayDiv = styledComponents.styled.div`
bottom: 0;
display: none;
left: 0;
position: absolute;
right: 0;
top: 0;
z-index: 1;
@media (hover: hover) {
&[data-enabled='true'] {
display: block;
}
}
`, VirtualListBox = styledComponents.styled(ui.Box)`
height: 100%;
outline: none;
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
width: 100%;
`, VirtualListChildBox = styledComponents.styled(ui.Box).attrs(({
$height
}) => ({
style: {
height: `${$height}px`
}
}))`
position: relative;
width: 100%;
`, CommandListComponent = React.forwardRef(function({
activeItemDataAttr = LIST_ITEM_DATA_ATTR_ACTIVE,
ariaLabel,
ariaMultiselectable = !1,
autoFocus,
canReceiveFocus,
fixedHeight,
focusRingOffset = 0,
getItemDisabled,
getItemKey: getItemKey2,
getItemSelected,
initialIndex,
initialScrollAlign = "start",
inputElement,
itemHeight,
items,
onEndReached,
onEndReachedIndexOffset = 0,
onlyShowSelectionWhenActive,
overscan,
renderItem: renderItem2,
testId,
wrapAround = !0,
...responsivePaddingProps
}, ref) {
const isMountedRef = React.useRef(!1), [commandListId] = React.useState(React.useId()), activeIndexRef = React.useRef(initialIndex ?? 0), [childContainerElement, setChildContainerElement] = React.useState(null), [hovered, setHovered] = React.useState(!1), [pointerOverlayElement, setPointerOverlayElement] = React.useState(null), [virtualListElement, setVirtualListElement] = React.useState(null), handleChange = React.useCallback((v) => {
if (!onEndReached) return;
const [lastItem] = [...v.getVirtualItems()].reverse();
lastItem && lastItem.index >= items.length - onEndReachedIndexOffset - 1 && isMountedRef.current && onEndReached();
}, [onEndReached, items.length, onEndReachedIndexOffset]), virtualizer = reactVirtual.useVirtualizer({
count: items.length,
getItemKey: getItemKey2,
getScrollElement: () => virtualListElement,
estimateSize: () => itemHeight,
onChange: handleChange,
overscan
}), itemIndices = React.useMemo(() => getItemIndicies(items, getItemDisabled, getItemSelected), [getItemDisabled, getItemSelected, items]), activeItemCount = React.useMemo(() => itemIndices.filter((v_0) => !v_0.disabled).length, [itemIndices]), enableChildContainerPointerEvents = React.useCallback((enabled) => pointerOverlayElement?.setAttribute("data-enabled", (!enabled).toString()), [pointerOverlayElement]), getChildDescendantId = React.useCallback((index) => `${commandListId}-item-${index}`, [commandListId]), getCommandListChildrenId = React.useCallback(() => `${commandListId}-children`, [commandListId]), showChildrenActiveState = React.useCallback(() => {
const hasFocus = [inputElement, virtualListElement].some((el) => document.activeElement === el);
onlyShowSelectionWhenActive && !hasFocus && !hovered || Array.from(childContainerElement?.children || [])?.forEach((child) => {
const virtualIndex = Number(child.dataset?.index), targetIndex = itemIndices[virtualIndex]?.activeIndex;
child.querySelector(LIST_ITEM_INTERACTIVE_SELECTOR)?.toggleAttribute(activeItemDataAttr, targetIndex === activeIndexRef.current);
});
}, [activeItemDataAttr, childContainerElement?.children, hovered, inputElement, itemIndices, onlyShowSelectionWhenActive, virtualListElement]), hideChildrenActiveState = React.useCallback(() => {
Array.from(childContainerElement?.children || [])?.forEach((child_0) => {
child_0.querySelector(LIST_ITEM_INTERACTIVE_SELECTOR)?.toggleAttribute(activeItemDataAttr, !1);
});
}, [activeItemDataAttr, childContainerElement?.children]), refreshChildrenActiveStateThrottled = React.useMemo(() => throttle__default.default(showChildrenActiveState, 200), [showChildrenActiveState]), handleUpdateActiveDescendant = React.useCallback(() => {
const activeIndex = activeIndexRef?.current;
items.length > 0 ? (inputElement?.setAttribute("aria-activedescendant", getChildDescendantId(activeIndex)), virtualListElement?.setAttribute("aria-activedescendant", getChildDescendantId(activeIndex))) : (inputElement?.removeAttribute("aria-activedescendant"), virtualListElement?.removeAttribute("aria-activedescendant"));
}, [getChildDescendantId, inputElement, items.length, virtualListElement]), handleGetTopIndex = React.useCallback(() => {
const childContainerParentElement = childContainerElement?.parentElement;
if (childContainerElement && childContainerParentElement) {
const offset = childContainerParentElement.getBoundingClientRect().top - childContainerElement.getBoundingClientRect().top;
return virtualizer.getVirtualItemForOffset(offset)?.index ?? -1;
}
return -1;
}, [childContainerElement, virtualizer]), setActiveIndex = React.useCallback(({
index: index_0,
scrollAlign,
scrollIntoView: scrollIntoView2 = !0
}) => {
if (activeIndexRef.current = index_0, handleUpdateActiveDescendant(), showChildrenActiveState(), scrollIntoView2) {
const virtualListIndex = itemIndices.findIndex((i) => i.activeIndex === index_0);
virtualListIndex > -1 && virtualizer.scrollToIndex(virtualListIndex, scrollAlign ? {
align: scrollAlign
} : {});
}
}, [handleUpdateActiveDescendant, itemIndices, showChildrenActiveState, virtualizer]), selectAdjacentItemIndex = React.useCallback((direction) => {
let nextIndex = -1;
const lastIndex = activeItemCount - 1;
if (direction === "next") {
const wrapAroundIndex = wrapAround ? 0 : lastIndex;
nextIndex = activeIndexRef.current < activeItemCount - 1 ? activeIndexRef.current + 1 : wrapAroundIndex;
}
if (direction === "previous") {
const wrapAroundIndex_0 = wrapAround ? lastIndex : 0;
nextIndex = activeIndexRef.current > 0 ? activeIndexRef.current - 1 : wrapAroundIndex_0;
}
setActiveIndex({
index: nextIndex,
scrollIntoView: !0
}), enableChildContainerPointerEvents(!1);
}, [activeItemCount, enableChildContainerPointerEvents, setActiveIndex, wrapAround]), focusElement = React.useCallback((type) => {
switch (type) {
case "input":
inputElement?.focus();
break;
case "list":
virtualListElement?.focus();
break;
}
}, [inputElement, virtualListElement]), focusInputElement = React.useCallback(() => {
inputElement?.focus();
}, [inputElement]), focusListElement = React.useCallback(() => {
virtualListElement?.focus();
}, [virtualListElement]), handleChildMouseEnter = React.useCallback((index_1) => () => {
setActiveIndex({
index: index_1,
scrollIntoView: !1
});
}, [setActiveIndex]), handleFocus = React.useCallback(() => {
showChildrenActiveState();
}, [showChildrenActiveState]), handleKeyDown = React.useCallback((type_0) => (event) => {
const childElements_1 = Array.from(childContainerElement?.children || []);
if (childElements_1.length && (event.key === "ArrowDown" && (event.preventDefault(), focusElement(type_0), selectAdjacentItemIndex("next")), event.key === "ArrowUp" && (event.preventDefault(), focusElement(type_0), selectAdjacentItemIndex("previous")), event.key === "Enter")) {
event.preventDefault(), focusElement(type_0);
const currentElement = childElements_1.find((el_0) => Number(el_0.dataset.index) === itemIndices.findIndex((i_0) => i_0.activeIndex === activeIndexRef.current));
currentElement && currentElement?.querySelector(LIST_ITEM_INTERACTIVE_SELECTOR)?.click();
}
}, [childContainerElement?.children, focusElement, itemIndices, selectAdjacentItemIndex]), handleKeyDownInput = React.useCallback((event_0) => handleKeyDown("input")(event_0), [handleKeyDown]), handleKeyDownList = React.useCallback((event_1) => handleKeyDown("list")(event_1), [handleKeyDown]), handleVirtualListMouseEnter = React.useCallback(() => {
onlyShowSelectionWhenActive && (showChildrenActiveState(), setHovered(!0));
}, [onlyShowSelectionWhenActive, showChildrenActiveState]), handleVirtualListMouseLeave = React.useCallback(() => {
onlyShowSelectionWhenActive && (hideChildrenActiveState(), setHovered(!1));
}, [hideChildrenActiveState, onlyShowSelectionWhenActive]);
React.useImperativeHandle(ref, () => ({
focusInputElement() {
focusInputElement();
},
focusListElement() {
focusListElement();
},
getTopIndex() {
return handleGetTopIndex();
},
scrollToIndex(index_2) {
setActiveIndex({
index: index_2
}), enableChildContainerPointerEvents(!0);
}
}), [enableChildContainerPointerEvents, focusInputElement, focusListElement, handleGetTopIndex, setActiveIndex]), React.useEffect(() => {
typeof initialIndex < "u" && !isMountedRef.current && setActiveIndex({
index: initialIndex,
scrollAlign: initialScrollAlign,
scrollIntoView: !0
}), isMountedRef.current = !0;
}, [initialIndex, initialScrollAlign, onlyShowSelectionWhenActive, setActiveIndex]), React.useEffect(() => {
function handleMouseEvent() {
enableChildContainerPointerEvents(!0);
}
return virtualListElement?.addEventListener("mousemove", handleMouseEvent), virtualListElement?.addEventListener("wheel", handleMouseEvent, {
passive: !0
}), () => {
virtualListElement?.removeEventListener("mousemove", handleMouseEvent), virtualListElement?.removeEventListener("wheel", handleMouseEvent);
};
}, [enableChildContainerPointerEvents, virtualListElement]), React.useEffect(() => (inputElement?.addEventListener("focus", handleFocus), inputElement?.addEventListener("keydown", handleKeyDownInput), virtualListElement?.addEventListener("focus", handleFocus), virtualListElement?.addEventListener("keydown", handleKeyDownList), () => {
inputElement?.removeEventListener("focus", handleFocus), inputElement?.removeEventListener("keydown", handleKeyDownInput), virtualListElement?.removeEventListener("focus", handleFocus), virtualListElement?.removeEventListener("keydown", handleKeyDownList);
}), [canReceiveFocus, handleFocus, handleKeyDown, handleKeyDownInput, handleKeyDownList, hideChildrenActiveState, inputElement, showChildrenActiveState, virtualListElement]), React.useEffect(() => {
handleUpdateActiveDescendant();
}, [handleUpdateActiveDescendant, items]), React.useEffect(() => {
const mutationObserver = new MutationObserver(refreshChildrenActiveStateThrottled);
return childContainerElement && mutationObserver.observe(childContainerElement, {
childList: !0,
subtree: !0
}), () => {
mutationObserver.disconnect();
};
}, [childContainerElement, refreshChildrenActiveStateThrottled]), React.useEffect(() => {
inputElement?.setAttribute("aria-autocomplete", "list"), inputElement?.setAttribute("aria-expanded", "true"), inputElement?.setAttribute("aria-controls", getCommandListChildrenId()), inputElement?.setAttribute("role", "combobox");
}, [getCommandListChildrenId, inputElement]), React.useEffect(() => {
autoFocus && focusElement(autoFocus);
}, [autoFocus, canReceiveFocus, focusListElement, focusInputElement, focusElement]);
const rootTabIndex = canReceiveFocus ? 0 : -1;
return /* @__PURE__ */ jsxRuntime.jsxs(VirtualListBox, { id: getCommandListChildrenId(), onMouseEnter: handleVirtualListMouseEnter, onMouseLeave: handleVirtualListMouseLeave, ref: setVirtualListElement, sizing: "border", tabIndex: rootTabIndex, "data-testid": testId, ...responsivePaddingProps, children: [
canReceiveFocus && /* @__PURE__ */ jsxRuntime.jsx(FocusOverlayDiv, { offset: focusRingOffset }),
/* @__PURE__ */ jsxRuntime.jsx(PointerOverlayDiv, { "aria-hidden": "true", "data-enabled": !0, ref: setPointerOverlayElement }),
virtualizer && /* @__PURE__ */ jsxRuntime.jsx(VirtualListChildBox, { forwardedAs: "ul", $height: virtualizer.getTotalSize(), "aria-label": ariaLabel, "aria-multiselectable": ariaMultiselectable, flex: 1, ref: setChildContainerElement, role: "listbox", children: virtualizer.getVirtualItems().map((virtualRow) => {
const virtualIndex_0 = virtualRow.index, {
activeIndex: activeIndex_0,
disabled,
selected
} = itemIndices[virtualIndex_0], itemToRender = renderItem2(items[virtualIndex_0], {
activeIndex: activeIndex_0,
disabled,
selected,
virtualIndex: virtualIndex_0
}), clonedItem = React.isValidElement(itemToRender) && itemToRender.type != React.Fragment ? React.cloneElement(itemToRender, {
// @ts-expect-error @TODO shift the responsibility of setting tabIndex to the consumer, so we can remove the need to clone
tabIndex: -1
}) : itemToRender;
return /* @__PURE__ */ jsxRuntime.jsx(CommandListItem2, { ref: fixedHeight ? void 0 : virtualizer.measureElement, activeIndex: activeIndex_0, activeItemCount, ariaMultiselectable, disabled, fixedHeight: fixedHeight ? `${virtualRow.size}px` : void 0, getChildDescendantId, handleChildMouseEnter, selected, virtualIndex: virtualIndex_0, virtualRowStart: virtualRow.start, children: clonedItem }, virtualRow.key);
}) })
] });
}), CommandList = React.memo(CommandListComponent);
CommandList.displayName = "Memo(ForwardRef(CommandList))";
const CommandListItemComponent = React.forwardRef(function(props2, forwardedRef) {
const {
children,
activeIndex,
activeItemCount,
ariaMultiselectable,
disabled,
fixedHeight,
getChildDescendantId,
handleChildMouseEnter,
selected,
virtualIndex,
virtualRowStart
} = props2, onMouseEnter = React.useMemo(() => typeof activeIndex == "number" && !disabled ? handleChildMouseEnter(activeIndex) : void 0, [activeIndex, disabled, handleChildMouseEnter]), activeAriaAttributes = React.useMemo(() => typeof activeIndex == "number" && !disabled ? {
"aria-posinset": activeIndex + 1,
...ariaMultiselectable ? {
"aria-selected": selected.toString()
} : {},
"aria-setsize": activeItemCount,
id: getChildDescendantId(activeIndex),
role: "option"
} : {}, [activeIndex, activeItemCount, ariaMultiselectable, disabled, getChildDescendantId, selected]), style = React.useMemo(() => ({
flex: 1,
height: fixedHeight,
left: 0,
position: "absolute",
top: 0,
transform: `translateY(${virtualRowStart}px)`,
width: "100%"
}), [fixedHeight, virtualRowStart]);
return /* @__PURE__ */ jsxRuntime.jsx(ui.Stack, { as: "li", "data-index": virtualIndex, ref: forwardedRef, style, tabIndex: -1, ...activeAriaAttributes, onMouseEnter, children });
}), CommandListItem2 = React.memo(CommandListItemComponent);
CommandListItem2.displayName = "Memo(ForwardRef(CommandListItem))";
function getItemIndicies(items, getItemDisabled, getItemSelected) {
let i = -1;
return items.reduce((acc, _, index) => {
const disabled = getItemDisabled?.(index) ?? !1, selected = getItemSelected?.(index) ?? !1;
return disabled || (i += 1), acc[index] = {
activeIndex: disabled ? null : i,
disabled,
selected
}, acc;
}, []);
}
const ContextMenuButton = React.forwardRef(function(props2, ref) {
const $ = reactCompilerRuntime.c(17);
let rest, t0, tone, tooltipProps;
$[0] !== props2 ? ({
mode: t0,
tooltipProps,
tone,
...rest
} = props2, $[0] = props2, $[1] = rest, $[2] = t0, $[3] = tone, $[4] = tooltipProps) : (rest = $[1], t0 = $[2], tone = $[3], tooltipProps = $[4]);
const mode = t0 === void 0 ? "bleed" : t0, {
t
} = useTranslation();
let t1;
$[5] !== t || $[6] !== tooltipProps?.content ? (t1 = tooltipProps?.content || t("common.context-menu-button.tooltip"), $[5] = t, $[6] = tooltipProps?.content, $[7] = t1) : t1 = $[7];
let t2;
$[8] !== t1 || $[9] !== tooltipProps ? (t2 = {
...tooltipProps,
content: t1
}, $[8] = t1, $[9] = tooltipProps, $[10] = t2) : t2 = $[10];
let t3;
return $[11] !== mode || $[12] !== ref || $[13] !== rest || $[14] !== t2 || $[15] !== tone ? (t3 = /* @__PURE__ */ jsxRuntime.jsx(TooltipDelayGroupProvider.Button, { ...rest, icon: icons.EllipsisHorizontalIcon, mode, ref, tone, tooltipProps: t2 }), $[11] = mode, $[12] = ref, $[13] = rest, $[14] = t2, $[15] = tone, $[16] = t3) : t3 = $[16], t3;
});
function getWorkspaceIdentifier({
name,
title
}, index) {
return typeof name == "string" && name.trim().length > 0 ? name : getNamelessWorkspaceIdentifier(title, index);
}
function getNamelessWorkspaceIdentifier(title, index) {
const withTitle = typeof title == "string" && title.trim().length > 0 ? ` (titled "${title}")` : "";
return `at index ${index}${withTitle}`;
}
function useWorkspaces() {
const workspaces = React.useContext(_singletons.WorkspacesContext);
if (!workspaces)
throw new Error("Could not find `workspaces` context");
return workspaces;
}
class WorkspaceValidationError extends Error {
constructor(message, options) {
super(message), this.name = "WorkspaceValidationError", this.index = options?.index, this.identifier = options?.workspace && getWorkspaceIdentifier(options.workspace, options.index);
}
}
function validateWorkspaces({
workspaces
}) {
if (workspaces.length === 0)
throw new WorkspaceValidationError("At least one workspace is required.");
validateNames(workspaces), validateBasePaths(workspaces);
}
function validateNames(workspaces) {
const isSingleWorkspace = workspaces.length === 1, names = /* @__PURE__ */ new Map();
workspaces.forEach((workspace, index) => {
const {
name: rawName,
title
} = workspace, thisIdentifier = getNamelessWorkspaceIdentifier(title, index);
if (!rawName && !isSingleWorkspace)
throw new WorkspaceValidationError(`All workspaces must have a \`name\`, unless only a single workspace is defined. Workspace ${thisIdentifier} did not define a \`name\`.`, {
workspace,
index
});
const name = isSingleWorkspace && typeof rawName > "u" ? "default" : rawName;
if (typeof name != "string")
throw new WorkspaceValidationError(`Workspace at index ${index} defined an invalid \`name\` - must be a string.`, {
workspace,
index
});
const normalized = name.toLowerCase(), existingWorkspace = names.get(normalized);
if (existingWorkspace) {
const prevIdentifier = getNamelessWorkspaceIdentifier(existingWorkspace.workspace.title, existingWorkspace.index);
throw new WorkspaceValidationError(`\`name\`s must be unique. Workspace ${prevIdentifier} and workspace ${thisIdentifier} both have the \`name\` \`${name}\``, {
workspace,
index
});
}
if (names.set(normalized, {
index,
workspace
}), !/^[a-z0-9][a-z0-9_-]*$/i.test(name))
throw new WorkspaceValidationError(`All workspace \`name\`s must consist of only a-z, 0-9, underscore and dashes, and cannot begin with an underscore or dash. Workspace ${thisIdentifier} has the invalid name \`${name}\``, {
workspace,
index
});
});
}
function validateBasePaths(workspaces) {
workspaces.length > 1 && workspaces.every(hasBasePath), workspaces.every(validateBasePath);
const [firstWorkspace, ...restOfWorkspaces] = workspaces, firstWorkspaceSegmentCount = (firstWorkspace.basePath || "/").slice(1).split("/").filter(Boolean).length;
restOfWorkspaces.forEach((workspace, index) => {
const workspaceSegmentCount = (workspace.basePath || "/").slice(1).split("/").length;
if (firstWorkspaceSegmentCount !== workspaceSegmentCount)
throw new WorkspaceValidationError(`All workspace \`basePath\`s must have the same amount of segments. Workspace \`${getWorkspaceIdentifier(firstWorkspace, index)}\` had ${firstWorkspaceSegmentCount} segment${firstWorkspaceSegmentCount === 1 ? "" : "s"} \`${firstWorkspace.basePath}\` but workspace \`${getWorkspaceIdentifier(workspace, index)}\` had ${workspaceSegmentCount} segment${workspaceSegmentCount === 1 ? "" : "s"} \`${workspace.basePath}\``, {
workspace,
index
});
});
const basePaths = /* @__PURE__ */ new Map();
workspaces.forEach((workspace, index) => {
const basePath = (workspace.basePath || "").toLowerCase(), existingWorkspace = basePaths.get(basePath);
if (existingWorkspace)
throw new WorkspaceValidationError(`\`basePath\`s must be unique. Workspaces \`${existingWorkspace}\` and \`${getWorkspaceIdentifier(workspace, index)}\` both have the \`basePath\` \`${basePath}\``, {
workspace,
index
});
basePaths.set(basePath, getWorkspaceIdentifier(workspace, index));
});
}
function hasBasePath(workspace, index) {
const {
name,
basePath
} = workspace;
if (basePath && typeof basePath == "string")
return !0;
throw typeof basePath > "u" ? new WorkspaceValidationError(`If more than one workspace is defined, every workspace must have a \`basePath\` defined. Workspace \`${name}\` is missing a \`basePath\``, {
workspace,
index
}) : new WorkspaceValidationError(`If more than one workspace is defined, every workspace must have a \`basePath\` defined. Workspace \`${name}\` has an invalid \`basePath\` (must be a non-empty string)`, {
workspace,
index
});
}
function validateBasePath(workspace, index) {
const {
name,
basePath
} = workspace;
if (!(!basePath || basePath === "/") && !/^\/[a-z0-9/_-]*[a-z0-9_-]+$/i.test(basePath))
throw new WorkspaceValidationError(`All workspace \`basePath\`s must start with a leading \`/\`, consist of only URL safe characters, and cannot end with a trailing \`/\`. Workspace \`${name}\`'s basePath is \`${basePath}\``, {
workspace,
index
});
}
const DEBUG_MODE$2 = !1, SPINNER_DELAY = 750, TEXT_DELAY = 2e3, StyledCard$5 = styledComponents.styled(ui.Card)(({
$fill
}) => styledComponents.css`
align-items: center;
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: center;
${$fill ? styledComponents.css`
bottom: 0;
height: 100%;
left: 0;
position: absolute;
right: 0;
top: 0;
width: 100%;
` : styledComponents.css`
min-height: 75px;
height: stretch;
height: -webkit-fill-available;
width: stretch;
width: -webkit-fill-available;
`}
${DEBUG_MODE$2}
> * {
position: absolute;
}
`), StyledSpinner = styledComponents.styled(ui.Spinner)(({
$animatePosition = !0
}) => styledComponents.css`
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideUp {
from {
transform: translateY(0);
}
to {
transform: translateY(-15px);
}
}
animation: ${$animatePosition ? `500ms ease-out ${SPINNER_DELAY}ms 1 normal both running fadeIn, 750ms ease-out ${TEXT_DELAY}ms 1 normal both running slideUp` : `500ms ease-out ${SPINNER_DELAY}ms 1 normal both running fadeIn`};
`), StyledText$7 = styledComponents.styled(ui.Text)`
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideDown {
from {
transform: translateY(0);
}
to {
transform: translateY(15px);
}
}
animation:
1500ms ease-out ${TEXT_DELAY}ms 1 normal both running fadeIn,
750ms ease-out ${TEXT_DELAY}ms 1 normal both running slideDown;
`;
function LoadingBlock(t0) {
const $ = reactCompilerRuntime.c(10), {
fill,
showText,
title
} = t0, t1 = fill ? ui.Layer : "div", t2 = !!showText;
let t3;
$[0] !== t2 ? (t3 = /* @__PURE__ */ jsxRuntime.jsx(StyledSpinner, { $animatePosition: t2, muted: !0 }), $[0] = t2, $[1] = t3) : t3 = $[1];
let t4;
$[2] !== showText || $[3] !== title ? (t4 = showText && /* @__PURE__ */ jsxRuntime.jsx(LoadingText, { title }), $[2] = showText, $[3] = title, $[4] = t4) : t4 = $[4];
let t5;
return $[5] !== fill || $[6] !== t1 || $[7] !== t3 || $[8] !== t4 ? (t5 = /* @__PURE__ */ jsxRuntime.jsxs(StyledCard$5, { $fill: fill, as: t1, "data-testid": "loading-block", children: [
t3,
t4
] }), $[5] = fill, $[6] = t1, $[7] = t3, $[8] = t4, $[9] = t5) : t5 = $[9], t5;
}
function LoadingText(t0) {
const $ = reactCompilerRuntime.c(5), {
title
} = t0, {
t
} = useTranslation();
let t1;
$[0] !== t || $[1] !== title ? (t1 = title || t("common.loading"), $[0] = t, $[1] = title, $[2] = t1) : t1 = $[2];
let t2;
return $[3] !== t1 ? (t2 = /* @__PURE__ */ jsxRuntime.jsx(StyledText$7, { muted: !0, size: 1, children: t1 }), $[3] = t1, $[4] = t2) : t2 = $[4], t2;
}
function defineLocaleResourceBundle(bundle) {
return bundle;
}
function defineLocale(locale) {
return locale;
}
function isStaticResourceBundle(bundle) {
return !("then" in bundle.resources && typeof bundle.resources.then == "function");
}
function defineLocalesResources(namespace, resources) {
return resources;
}
function removeUndefinedLocaleResources(resources) {
const result = {};
for (const key in resources)
typeof resources[key] < "u" && (result[key] = resources[key]);
return result;
}
const studioLocaleNamespace = "studio", validationLocaleNamespace = "validation", copyPasteLocalNamespace = "copy-paste", copyPasteLocaleStrings = defineLocalesResources("copy-paste", {
/** Text on the field action button to copy a document */
"copy-paste.field-action-copy-button.document.title": "Copy document",
/** Text on the field action button to copy a field */
"copy-paste.field-action-copy-button.field.title": "Copy field",
/** Text on the field action button to paste a document */
"copy-paste.field-action-paste-button.document.title": "Paste document",
/** Text on the field action button to paste a field */
"copy-paste.field-action-paste-button.field.title": "Paste field",
/** --- On paste --- */
/** The validation message that is shown when pasting a value into a read-only target */
"copy-paste.on-paste.validation.read-only-target.description": "The target is read-only",
/** The validation message that is shown when the source and target schema types are incompatible */
"copy-paste.on-paste.validation.schema-type-incompatible.description": "Source and target schema types are not compatible",
/** The validation message that is shown when reference types are incompatible */
"copy-paste.on-paste.validation.reference-type-incompatible.description": 'References of type "{{sourceReferenceType}}" is not allowed in reference field that accepts types "{{targetReferenceTypes}}"',
/** The validation message that is shown when reference is incompatible with filter */
"copy-paste.on-paste.validation.reference-filter-incompatible.description": "Reference is not allowed in reference field according to filter",
/** The validation message that is shown when reference does not exist */
"copy-paste.on-paste.validation.reference-validation-failed.description": 'The referenced document "{{ref}}" does not exist',
/** The validation message that is shown when image files are incompatible */
"copy-paste.on-paste.validation.image-file-incompatible.description": 'A "{{sourceSchemaType}}" is not allowed in a "{{targetSchemaType}}"',
/** The validation message that is shown when array types are incompatible */
"copy-paste.on-paste.validation.array-type-incompatible.description": 'Value of type "{{type}}" is not allowed in this array field',
/** The validation message that is shown when array values are incompatible */
"copy-paste.on-paste.validation.array-value-incompatible.description": 'Value of type "{{type}}" is not allowed in this array field',
/** The validation message that is shown when string values are incompatible */
"copy-paste.on-paste.validation.string-value-incompatible.description": 'Value "{{value}}" is not allowed in "{{allowedStrings}}"',
/** The validation message that is shown when primitive types are incompatible */
"copy-paste.on-paste.validation.primitive-type-incompatible.description": 'Value of type "{{type}}" is not allowed in this field',
/** The validation message that is shown when the clipboard is empty */
"copy-paste.on-paste.validation.clipboard-empty.title": "Nothing to paste",
/** The validation message that is shown when the clipboard item is invalid */
"copy-paste.on-paste.validation.clipboard-invalid.title": "Invalid clipboard item",
/** The validation message that is shown when schema types are incompatible */
"copy-paste.on-paste.validation.schema-type-incompatible.title": "Could not resolve schema type for path: {{path}}",
/** The warning message that is shown when not all values can be pasted */
"copy-paste.on-paste.validation.partial-warning.title": "Could not paste all values",
/** The error message that is shown when the MIME type is not accepted */
"copy-paste.on-paste.validation.mime-type-incompatible.description": 'MIME type "{{mimeType}}" is not accepted for this field',
/** The error message that is shown when the MIME type validation fails */
"copy-paste.on-paste.validation.mime-type-validation-failed.description": "MIME type validation failed",
/** --- On copy --- */
/** The error message that is shown when schema types are incompatible */
"copy-paste.on-copy.validation.schema-type-incompatible.title": "Could not resolve schema type for path: {{path}}",
/** The error message that is shown when there is no value to copy */
"copy-paste.on-copy.validation.no-value.title": "Empty value, nothing to copy",
/** The error message that is shown when the clipboard is not supported */
"copy-paste.on-copy.validation.clipboard-not-supported.description": "Clipboard access required to copy this content. Allow clipboard permissions in your browser settings, then try copying again.",
/** The error message that is shown when the clipboard is not supported */
"copy-paste.on-copy.validation.clipboard-not-supported.title": "Clipboard access blocked"
}), copyPasteLocaleResources = {
locale: "en-US",
namespace: copyPasteLocalNamespace,
resources: copyPasteLocaleStrings
}, studioLocaleStrings = defineLocalesResources("studio", {
/** "Disabled" status for auto-updates in About-dialog */
"about-dialog.version-info.auto-updates.disabled": "Auto Updates not enabled",
/** "Enabled" status for auto-updates in About-dialog */
"about-dialog.version-info.auto-updates.enabled": "Auto Updates Enabled",
/** @deprecated "Auto Updates" status header in About-dialog */
"about-dialog.version-info.auto-updates.header": "Auto Updates",
/** "How to enable" next to Disabled state for Auto updates in version info dialog */
"about-dialog.version-info.auto-updates.how-to-enable": "Enable",
/** "Manage version" link text */
"about-dialog.version-info.auto-updates.manage-version": "Manage version",
/** Text displayed on the "Copy to clipboard"-button after clicked */
"about-dialog.version-info.copy-to-clipboard-button.copied-text": "Copied to Clipboard. Happy pasting!",
/** "Copy to Clipboard" button text for copying version details from About-dialog */
"about-dialog.version-info.copy-to-clipboard-button.text": "Copy to Clipboard",
/** "Current version" header in version info dialog */
"about-dialog.version-info.current-version.header": "Current version",
/** @deprecated "How to upgrade" link text */
"about-dialog.version-info.how-to-upgrade": "Update now",
/** "Latest version" header in version info dialog */
"about-dialog.version-info.latest-version.header": "Latest version",
/** Info text when auto updates is enabled and a new version is available */
"about-dialog.version-info.new-auto-update-version-available": "New version available",
/** "New version" header in version info dialog - Note that this is not necessary a *higher* version compared to current:
* It's a new version configured for auto updates which in some cases could even be a version below current */
"about-dialog.version-info.new-version.text": "New version",
/** "Reload"-button when auto updates is enabled and a new version is available */
"about-dialog.version-info.reload": "Reload",
/** "Reload to update"-tooltip when auto updates is enabled and a new version is available */
"about-dialog.version-info.reload-to-update": "Reload Studio to update",
/** "New version available" tooltip in About-dialog */
"about-dialog.version-info.tooltip.new-version-available": "New version available",
/** "Prerelease" tooltip in About-dialog */
"about-dialog.version-info.tooltip.prerelease": "Prerelease",
/** "Up to date" tooltip in About-dialog */
"about-dialog.version-info.tooltip.up-to-date": "Up to date",
/** @deprecated "Up to date" status in About-dialog */
"about-dialog.version-info.up-to-date": "Up to date",
/** "Upgrade"-button text */
"about-dialog.version-info.update-button.text": "Update",
/** "Upgrade"-button tooltip text */
"about-dialog.version-info.update-button.tooltip": "Learn how to update Sanity Studio",
/** "User agent" header in About-dialog */
"about-dialog.version-info.user-agent.header": "User agent",
/** "View on GitHub" link from version info dialog */
"about-dialog.version-info.view-on-github": "View on GitHub",
/** The text used in the tooltip shown in the dialog close button */
"announcement.dialog.close": "Close",
/** Aria label to be used in the dialog close button */
"announcement.dialog.close-label": "Close dialog",
/**Text to be used in the tooltip in the button in the studio announcement card */
"announcement.floating-button.dismiss": "Close",
/**Aria label to be used in the floating button in the studio announcement card, to dismiss the card */
"announcement.floating-button.dismiss-label": "Dismiss announcements",
/**Aria label to be used in the floating button in the studio announcement card */
"announcement.floating-button.open-label": "Open announcements",
/** Menu item for deleting the asset */
"asset-source.asset-list.menu.delete": "Delete",
/** Menu item for showing where a particular asset is used */
"asset-source.asset-list.menu.show-usage": "Show usage",
/** Header in usage dialog for file assets */
"asset-source.asset-usage-dialog.header_file": "Documents using file",
/** Header in usage dialog for image assets */
"asset-source.asset-usage-dialog.header_image": "Documents using image",
/** Text shown in usage dialog when loading documents using the selected asset */
"asset-source.asset-usage-dialog.loading": "Loading\u2026",
/** Text for cancel action in delete-asset dialog */
"asset-source.delete-dialog.action.cancel": "Cancel",
/** Text for "confirm delete" action in delete-asset dialog */
"asset-source.delete-dialog.action.delete": "Delete",
/** Dialog header for delete-asset dialog when deleting a file */
"asset-source.delete-dialog.header_file": "Delete file",
/** Dialog header for delete-asset dialog when deleting an image */
"asset-source.delete-dialog.header_image": "Delete image",
/** Text shown in delete dialog when loading documents using the selected asset */
"asset-source.delete-dialog.loading": "Loading\u2026",
/** Message confirming to delete *named* file */
"asset-source.delete-dialog.usage-list.confirm-delete-file_named": "You are about to delete the file <strong>{{filename}}</strong> and its metadata. Are you sure?",
/** Message confirming to delete *unnamed* file */
"asset-source.delete-dialog.usage-list.confirm-delete-file_unnamed": "You are about to delete the file and its metadata. Are you sure?",
/** Message confirming to delete *named* image */
"asset-source.delete-dialog.usage-list.confirm-delete-image_named": "You are about to delete the