UNPKG

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
"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