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

1,321 lines (1,291 loc) • 167 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }); var jsxRuntime = require("react/jsx-runtime"), PathUtils = require("@sanity/util/paths"), React = require("react"), deepCompare = require("react-fast-compare"), TransformPatches = require("./_chunks-cjs/TransformPatches.js"), sortBy = require("lodash/sortBy.js"), reactRx = require("react-rx"), rxjs = require("rxjs"), operators = require("rxjs/operators"), isEqual$1 = require("lodash/isEqual.js"), throttle = require("lodash/throttle.js"), types = require("@sanity/types"), ui = require("@sanity/ui"), router = require("sanity/router"), getJsonStream = require("./_chunks-cjs/getJsonStream.js"), isString = require("lodash/isString.js"); require("dataloader"); require("history"); var withSelector = require("use-sync-external-store/with-selector"); require("lodash/escapeRegExp.js"); require("lodash/isEqual"); require("lodash/startCase"); require("react-dom/server"); require("@sanity/schema/_internal"); require("lodash/compact.js"); require("lodash/intersection.js"); require("lodash/keyBy.js"); require("lodash/partition.js"); require("lodash/toLower.js"); require("lodash/union.js"); require("lodash/uniq.js"); require("lodash/words.js"); require("lodash/isFinite.js"); require("lodash/intersection"); require("lodash/isEmpty"); require("date-fns"); require("react-i18next"); require("@sanity/portable-text-editor"); require("@sanity/icons"); require("lodash/omit.js"); require("@sanity/diff-match-patch"); var flatten = require("lodash/flatten.js"); require("lodash/orderBy.js"); require("lodash/xor.js"); require("sanity-diff-patch"); require("lodash/startCase.js"); require("lodash/debounce.js"); require("nano-pubsub"); require("shallow-equals"); require("scroll-into-view-if-needed"); require("lodash/get.js"); require("get-random-values-esm"); var content = require("@sanity/util/content"); require("lodash/isPlainObject.js"); require("@tanstack/react-virtual"); require("@sanity/util/legacyDateFormat"); require("speakingurl"); require("@sanity/telemetry/react"); require("lodash/find.js"); var castArray = require("lodash/castArray.js"), pick = require("lodash/pick.js"), mutator = require("@sanity/mutator"); require("@sanity/schema"); require("@sanity/asset-utils"); require("@sanity/image-url"); require("@sanity/uuid"); require("exif-component"); require("react-is"); require("lodash/difference.js"); require("lodash/memoize.js"); require("lodash/identity.js"); require("lodash/values.js"); require("lodash/assignWith.js"); require("lodash/capitalize.js"); var client = require("react-dom/client"); require("lodash/groupBy.js"); require("json-reduce"); require("rxjs-exhaustmap-with-trailing"); require("groq-js"); require("rxjs-etc/operators"); require("mendoza"); require("@sanity/diff"); require("raf"); require("@sanity/bifur-client"); require("@sanity/client"); require("i18next"); var color = require("@sanity/color"), theme = require("@sanity/ui/theme"), 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), deepCompare__default = /* @__PURE__ */ _interopDefaultCompat(deepCompare), sortBy__default = /* @__PURE__ */ _interopDefaultCompat(sortBy), isEqual__default = /* @__PURE__ */ _interopDefaultCompat(isEqual$1), throttle__default = /* @__PURE__ */ _interopDefaultCompat(throttle), isString__default = /* @__PURE__ */ _interopDefaultCompat(isString), flatten__default = /* @__PURE__ */ _interopDefaultCompat(flatten), castArray__default = /* @__PURE__ */ _interopDefaultCompat(castArray), pick__default = /* @__PURE__ */ _interopDefaultCompat(pick); function noop() { } function NoopTracker({ children }) { return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }); } function createNoopTrackerScope() { return { useReportedValues: noop, Tracker: NoopTracker, useReporter: noop }; } const ChangeFieldWrapper = (props) => { const ref = React.useRef(null), { onSetFocus } = React.useContext(TransformPatches.ConnectorContext), [isHover, setHover] = React.useState(!1), onMouseEnter = React.useCallback(() => { setHover(!0); }, []), onMouseLeave = React.useCallback(() => { setHover(!1); }, []); TransformPatches.useReporter( `change-${PathUtils__namespace.toString(props.path)}`, () => ({ element: ref.current, path: props.path, isChanged: !0, hasFocus: !1, hasHover: isHover, hasRevertHover: props.hasHover }), // note: deepCompare should be ok here since we're not comparing deep values deepCompare__default.default ); const handleClick = React.useCallback( (event) => { setFocusWithStopPropagation(event, onSetFocus, props.path); }, [onSetFocus, props.path] ); return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, onClick: handleClick, onMouseLeave, onMouseEnter, children: props.children }); }; function setFocusWithStopPropagation(event, onSetFocus, path) { event.stopPropagation(), onSetFocus(path); } function isArray(value) { return Array.isArray(value); } function isTruthy(value) { return !!value; } const BUNDLED_DOC_TYPES = ["sanity.imageAsset", "sanity.fileAsset"]; function _isSanityDocumentTypeDefinition(def) { return def.type === "document" && BUNDLED_DOC_TYPES.includes(def.name); } function _isCustomDocumentTypeDefinition(def) { return def.type === "document" && !_isSanityDocumentTypeDefinition(def); } const FONT_SANS_SERIF = "-apple-system, BlinkMacSystemFont, \\'Segoe UI\\', Roboto, \\'Helvetica Neue\\', Helvetica, Arial, system-ui, sans-serif", FONT_MONOSPACE = "-apple-system-ui-monospace, \\'SF Mono\\', Menlo, Monaco, Consolas, monospace", uncaughtErrorHandler = () => ( // prettier-ignore [ "window.onerror = function(m,u,l,c,e) {", "var p=window.location.port;", "var h=window.location.protocol+'//'+window.location.hostname+(p?':'+p:'');", "var r=document.getElementById('sanity');", "while(r.firstChild){r.removeChild(r.firstChild);}", "var s=document.createElement('style');", "s.appendChild(document.createTextNode('", "html,body,#sanityBody,#sanity,#sanityError{height:100%;}", "body{-webkit-font-smoothing:antialiased;margin:0;}", `#sanityError{position:fixed;top:0;left:0;width:100%;height:100%;overflow:auto;background-color:#fff;color:#121923;font-family:${FONT_SANS_SERIF};font-size:16px;line-height:21px;min-height:100%;}`, "#sanityError>div{background-color:#fff;max-width:960px;margin:0 auto;padding:47px 32px 52px;}", "@media(min-width:512px){", "#sanityError>div{", "padding:47px 84px;", "}", "}", "#sanityError button{-webkit-font-smoothing:inherit;font:inherit;font-weight:500;background-color:#2276FC;color:#fff;padding:7px 12px;border-radius:3px;border:0;}", "#sanityError button:hover{background-color:#1E63D0;}", "#sanityError button:active{background-color:#1B50A5;}", "'));", "document.head.appendChild(s);", "var f=document.createElement('div');", "f.id='sanityError';", "f.innerHTML='", "<div>", '<h1 style="font-size:21px;line-height:27px;margin: 0 0 10px;">Unhandled error</h1>', '<p style="color:#66758D;margin:10px 0 14px;">Encountered an unhandled error in this Studio.</p>', '<button class="sanity-error-handler__reload-btn" type="button">Reload page</button>', '<pre style="background-color:#FDEBEA;color:#C3362C;font-size:13px;line-height:17px;padding:8px 12px;border-radius:3px;margin:32px 0 0;overflow:auto;">', `<code style="font-family:${FONT_MONOSPACE};">`, "'+e.stack.replaceAll(h,'')+'", "</code>", "</pre>", "</div>", "';", "var b=f.querySelector('.sanity-error-handler__reload-btn');", "if(b){", "b.onclick=function() {", "window.location.reload();", "}", "};", "r.appendChild(f);", "};" ].join("") ); function useThrottledCallback(callback, wait, options) { return React.useMemo( () => throttle__default.default(callback, wait, options), [callback, options, wait] ); } function useOnScroll(callback) { const parentContext = React.useContext(TransformPatches.ScrollContext); React.useEffect(() => parentContext == null ? void 0 : parentContext.subscribe(callback), [callback, parentContext]); } function ScrollMonitor({ onScroll, children }) { return useOnScroll(onScroll), /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }); } function findMostSpecificTarget(targetType, id, values) { const pathString = id.slice(id.indexOf("-") + 1) || "[]", path = PathUtils__namespace.fromString(pathString), exactId = `${targetType}-${PathUtils__namespace.toString(path)}`; if (values.has(exactId)) return values.get(exactId); let mostSpecific; for (const [targetId, target] of values) { if (!("path" in target) || !targetId.startsWith(targetType)) continue; const numEqual = PathUtils__namespace.numEqualSegments(path, target.path), lastPathSegment = target.path[target.path.length - 1], pathOnlyDiffersByKey = numEqual === target.path.length - 1 && types.isKeyedObject(lastPathSegment); if (numEqual !== 0 && !(numEqual !== target.path.length && !pathOnlyDiffersByKey) && (mostSpecific = target, numEqual === path.length)) break; } return mostSpecific; } function hasOverflowScroll(el) { const overflow = getComputedStyle(el).overflow; return overflow.includes("auto") || overflow.includes("scroll"); } function isScrollable(el) { return (el.scrollHeight !== el.offsetHeight || el.scrollWidth !== el.offsetWidth) && hasOverflowScroll(el); } const getOffsetsTo = (source, target) => { const bounds = { top: 0, left: 0, height: target.offsetHeight, width: target.offsetWidth }, rect = { top: 0, left: 0, height: source.offsetHeight, width: source.offsetWidth }; let foundScrollContainer = !1, el = source; for (; el && el !== target && target.contains(el); ) foundScrollContainer && (bounds.top += el.offsetTop, bounds.left += el.offsetLeft), hasOverflowScroll(el) && (bounds.top = el.offsetTop, bounds.height = el.offsetHeight, bounds.left = el.offsetLeft, bounds.width = el.offsetWidth, foundScrollContainer = !0), rect.top += el.offsetTop - el.scrollTop, rect.left += el.offsetLeft - el.scrollLeft, el = el.offsetParent; return { rect, bounds }; }; function isChangeBar(v) { return v[0] !== "changePanel"; } const SCROLL_INTO_VIEW_TOP_PADDING = -15; function scrollIntoView(field) { let parentElementWithScroll = field.element; for (; !isScrollable(parentElementWithScroll); ) if (parentElementWithScroll = parentElementWithScroll.parentElement, !parentElementWithScroll) return; parentElementWithScroll.scroll({ top: parentElementWithScroll.scrollTop + field.rect.top - field.bounds.top + SCROLL_INTO_VIEW_TOP_PADDING, left: 0, behavior: "smooth" }); } function useResizeObserver(element, onResize) { React.useEffect(() => TransformPatches.resizeObserver.observe(element, onResize), [element, onResize]); } function getState(allReportedValues, hovered, byId, rootElement) { const changeBarsWithHover = [], changeBarsWithFocus = []; for (const value of allReportedValues) { if (!isChangeBar(value) || !value[1].isChanged) continue; const [id, reportedChangeBar] = value; if (id === hovered) { changeBarsWithHover.push(value); continue; } if (reportedChangeBar.hasHover) { changeBarsWithHover.push(value); continue; } if (reportedChangeBar.hasFocus) { changeBarsWithFocus.push(value); continue; } } const isHoverConnector = changeBarsWithHover.length > 0; return { connectors: (isHoverConnector ? changeBarsWithHover : changeBarsWithFocus).map(([id]) => { const field = findMostSpecificTarget("field", id, byId), change = findMostSpecificTarget("change", id, byId); return !field || !change ? null : { field: { id, ...field }, change: { id, ...change } }; }).filter(TransformPatches.isNonNullable).map(({ field, change }) => ({ hasHover: field.hasHover || change.hasHover, hasFocus: field.hasFocus, hasRevertHover: change.hasRevertHover, field: { ...field, ...getOffsetsTo(field.element, rootElement) }, change: { ...change, ...getOffsetsTo(change.element, rootElement) } })), isHoverConnector }; } function ConnectorsOverlay(props) { const { rootElement, onSetFocus } = props, [hovered, setHovered] = React.useState(null), allReportedValues = TransformPatches.useReportedValues(), byId = React.useMemo( () => new Map(allReportedValues), [allReportedValues] ), [{ connectors }, setState] = React.useState( () => getState(allReportedValues, hovered, byId, rootElement) ), visibleConnectors = React.useMemo( () => sortBy__default.default(connectors, (c) => 0 - c.field.path.length).slice(0, 1), [connectors] ), handleScrollOrResize = React.useCallback(() => { setState(getState(allReportedValues, hovered, byId, rootElement)); }, [byId, allReportedValues, hovered, rootElement]); return useResizeObserver(rootElement, handleScrollOrResize), /* @__PURE__ */ jsxRuntime.jsx(ScrollMonitor, { onScroll: handleScrollOrResize, children: /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.SvgWrapper, { style: { zIndex: visibleConnectors[0] && visibleConnectors[0].field.zIndex }, children: visibleConnectors.map(({ field, change }) => change ? /* @__PURE__ */ jsxRuntime.jsx( ConnectorGroup, { field, change, onSetFocus, setHovered }, field.id ) : null) }) }); } function ConnectorGroup(props) { const { change, field, onSetFocus, setHovered } = props, onConnectorClick = React.useCallback(() => { scrollIntoView(field), scrollIntoView(change), onSetFocus(field.path); }, [field, change, onSetFocus]), handleMouseEnter = React.useCallback(() => setHovered(field.id), [field, setHovered]), handleMouseLeave = React.useCallback(() => setHovered(null), [setHovered]), from = React.useMemo( () => ({ rect: { ...field.rect, left: field.rect.left + 3 }, bounds: field.bounds }), [field.bounds, field.rect] ), to = React.useMemo( () => ({ rect: { ...change.rect, left: change.rect.left + 1 }, bounds: change.bounds }), [change.bounds, change.rect] ); return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ /* @__PURE__ */ jsxRuntime.jsx("g", { onClick: onConnectorClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.Connector, { from, to }) }), TransformPatches.DEBUG_LAYER_BOUNDS ] }); } function EnabledChangeConnectorRoot({ children, className, isReviewChangesOpen, onOpenReviewChanges, onSetFocus, ...restProps }) { const [rootElement, setRootElement] = React.useState(), contextValue = React.useMemo( () => ({ isReviewChangesOpen, onOpenReviewChanges, onSetFocus }), [isReviewChangesOpen, onOpenReviewChanges, onSetFocus] ); return /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.ConnectorContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.Tracker, { children: /* @__PURE__ */ jsxRuntime.jsxs(TransformPatches.ScrollContainer, { ...restProps, ref: setRootElement, className, children: [ children, rootElement && /* @__PURE__ */ jsxRuntime.jsx(ConnectorsOverlay, { rootElement, onSetFocus }) ] }) }) }); } function DisabledChangeConnectorRoot({ children, className }) { return /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.ScrollContainer, { className, children }); } const ChangeConnectorRoot = EnabledChangeConnectorRoot; function BetaBadge(props) { const { fontSize = 1, children = "Beta", ...rest } = props; return /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { ...rest, fontSize, radius: 2, tone: "primary", children }); } function Favicons({ basePath }) { const base = `${basePath.replace(/\/+$/, "")}/static`; return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "icon", href: `${base}/favicon.ico`, sizes: "any" }), /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "icon", href: `${base}/favicon.svg`, type: "image/svg+xml" }), /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "apple-touch-icon", href: `${base}/apple-touch-icon.png` }), /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "manifest", href: `${base}/manifest.webmanifest` }) ] }); } const errorHandlerScript = ` ;(function () { var _caughtErrors = [] var errorChannel = (function () { var subscribers = [] function publish(msg) { for (var i = 0; i < subscribers.length; i += 1) { subscribers[i](msg) } } function subscribe(subscriber) { subscribers.push(subscriber) return function () { var idx = subscribers.indexOf(subscriber) if (idx > -1) { subscribers.splice(idx, 1) } } } return {publish, subscribe, subscribers} })() // NOTE: Store the error channel instance in the global scope so that the Studio application can // access it and subscribe to errors. window.__sanityErrorChannel = { subscribe: errorChannel.subscribe, } function _nextTick(callback) { setTimeout(callback, 0) } function _handleError(error, params) { _nextTick(function () { // - If there are error channel subscribers, then we notify them (no console error). // - If there are no subscribers, then we log the error to the console and render the error overlay. if (errorChannel.subscribers.length) { errorChannel.publish({error, params}) } else { console.error(error) _renderErrorOverlay(error, params) } }) } var ERROR_BOX_STYLE = [ 'background: #fff', 'border-radius: 6px', 'box-sizing: border-box', 'color: #121923', 'flex: 1', "font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue','Liberation Sans',Helvetica,Arial,system-ui,sans-serif", 'font-size: 16px', 'line-height: 21px', 'margin: 0 auto', 'max-width: 960px', 'overflow: auto', 'padding: 20px', 'width: 100%', ].join(';') var ERROR_CODE_STYLE = [ 'color: #972E2A', "font-family: -apple-system-ui-monospace, 'SF Mono', Menlo, Monaco, Consolas, monospace", 'font-size: 13px', 'line-height: 17px', 'margin: 0', ].join(';') function _renderErrorOverlay(error, params) { var errorElement = document.querySelector('#__sanityError') || document.createElement('div') var colno = params.event.colno var lineno = params.event.lineno var filename = params.event.filename errorElement.id = '__sanityError' errorElement.innerHTML = [ '<div style="' + ERROR_BOX_STYLE + '">', '<div style="font-weight: 700;">Uncaught error: ' + error.message + '</div>', '<div style="color: #515E72; font-size: 13px; line-height: 17px; margin: 10px 0;">' + filename + ':' + lineno + ':' + colno + '</div>', '<pre style="' + ERROR_CODE_STYLE + '">' + error.stack + '</pre>', '</div>', ].join('') errorElement.style.position = 'fixed' errorElement.style.zIndex = 1000000 errorElement.style.top = 0 errorElement.style.left = 0 errorElement.style.right = 0 errorElement.style.bottom = 0 errorElement.style.padding = '20px' errorElement.style.background = 'rgba(16,17,18,0.66)' errorElement.style.display = 'flex' errorElement.style.alignItems = 'center' errorElement.style.justifyContent = 'center' document.body.appendChild(errorElement) } // NOTE: // Yes \u2013 we're attaching 2 error listeners below \u{1F440} // This is because React makes the same error throw twice (in development mode). // See: https://github.com/facebook/react/issues/10384 // Error listener #1 window.onerror = function (event, source, lineno, colno, error) { _nextTick(function () { if (_caughtErrors.indexOf(error) !== -1) return _caughtErrors.push(error) _handleError(error, { event, lineno, colno, source, }) _nextTick(function () { var idx = _caughtErrors.indexOf(error) if (idx > -1) _caughtErrors.splice(idx, 1) }) }) // IMPORTANT: this callback must return \`true\` to prevent the error from being rendered in // the browser\u2019s console. return true } // Error listener #2 window.addEventListener('error', function (event) { if (_caughtErrors.indexOf(event.error) !== -1) return true _caughtErrors.push(event.error) _handleError(event.error, { event, lineno: event.lineno, colno: event.colno, }) _nextTick(function () { _nextTick(function () { var idx = _caughtErrors.indexOf(event.error) if (idx > -1) _caughtErrors.splice(idx, 1) }) }) return true }) })() `; function GlobalErrorHandler() { return /* @__PURE__ */ jsxRuntime.jsx("script", { dangerouslySetInnerHTML: { __html: errorHandlerScript } }); } const NoJsStyles = ` .sanity-app-no-js__root { position: absolute; top: 0; right: 0; left: 0; bottom: 0; background: #fff; } .sanity-app-no-js__content { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; font-family: helvetica, arial, sans-serif; } `; function NoJavascript() { return /* @__PURE__ */ jsxRuntime.jsx("noscript", { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sanity-app-no-js__root", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sanity-app-no-js__content", children: [ /* @__PURE__ */ jsxRuntime.jsx("style", { type: "text/css", children: NoJsStyles }), /* @__PURE__ */ jsxRuntime.jsx("h1", { children: "JavaScript disabled" }), /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [ "Please ", /* @__PURE__ */ jsxRuntime.jsx("a", { href: "https://www.enable-javascript.com/", children: "enable JavaScript" }), " in your browser and reload the page to proceed." ] }) ] }) }) }); } const globalStyles = ` @font-face { font-family: Inter; font-style: normal; font-weight: 400; font-display: swap; src: url("https://studio-static.sanity.io/Inter-Regular.woff2") format("woff2"); } @font-face { font-family: Inter; font-style: italic; font-weight: 400; font-display: swap; src: url("https://studio-static.sanity.io/Inter-Italic.woff2") format("woff2"); } @font-face { font-family: Inter; font-style: normal; font-weight: 500; font-display: swap; src: url("https://studio-static.sanity.io/Inter-Medium.woff2") format("woff2"); } @font-face { font-family: Inter; font-style: italic; font-weight: 500; font-display: swap; src: url("https://studio-static.sanity.io/Inter-MediumItalic.woff2") format("woff2"); } @font-face { font-family: Inter; font-style: normal; font-weight: 600; font-display: swap; src: url("https://studio-static.sanity.io/Inter-SemiBold.woff2") format("woff2"); } @font-face { font-family: Inter; font-style: italic; font-weight: 600; font-display: swap; src: url("https://studio-static.sanity.io/Inter-SemiBoldItalic.woff2") format("woff2"); } @font-face { font-family: Inter; font-style: normal; font-weight: 700; font-display: swap; src: url("https://studio-static.sanity.io/Inter-Bold.woff2") format("woff2"); } @font-face { font-family: Inter; font-style: italic; font-weight: 700; font-display: swap; src: url("https://studio-static.sanity.io/Inter-BoldItalic.woff2") format("woff2"); } @font-face { font-family: Inter; font-style: normal; font-weight: 800; font-display: swap; src: url("https://studio-static.sanity.io/Inter-ExtraBold.woff2") format("woff2"); } @font-face { font-family: Inter; font-style: italic; font-weight: 800; font-display: swap; src: url("https://studio-static.sanity.io/Inter-ExtraBoldItalic.woff2") format("woff2"); } @font-face { font-family: Inter; font-style: normal; font-weight: 900; font-display: swap; src: url("https://studio-static.sanity.io/Inter-Black.woff2") format("woff2"); } @font-face { font-family: Inter; font-style: italic; font-weight: 900; font-display: swap; src: url("https://studio-static.sanity.io/Inter-BlackItalic.woff2") format("woff2"); } html { background-color: #f1f3f6; } html, body, #sanity { height: 100%; } body { margin: 0; -webkit-font-smoothing: antialiased; } `, EMPTY_ARRAY$1 = []; function DefaultDocument(props) { const { entryPath, css = EMPTY_ARRAY$1, basePath = "/" } = props; return /* @__PURE__ */ jsxRuntime.jsxs("html", { lang: "en", children: [ /* @__PURE__ */ jsxRuntime.jsxs("head", { children: [ /* @__PURE__ */ jsxRuntime.jsx("meta", { charSet: "utf-8" }), /* @__PURE__ */ jsxRuntime.jsx( "meta", { name: "viewport", content: "width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" } ), /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "robots", content: "noindex" }), /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "referrer", content: "same-origin" }), /* @__PURE__ */ jsxRuntime.jsx(Favicons, { basePath }), /* @__PURE__ */ jsxRuntime.jsx("title", { children: "Sanity Studio" }), /* @__PURE__ */ jsxRuntime.jsx(GlobalErrorHandler, {}), css.map((href) => /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "stylesheet", href }, href)), /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: globalStyles } }) ] }), /* @__PURE__ */ jsxRuntime.jsxs("body", { children: [ /* @__PURE__ */ jsxRuntime.jsx("div", { id: "sanity" }), /* @__PURE__ */ jsxRuntime.jsx("script", { type: "module", src: entryPath }), /* @__PURE__ */ jsxRuntime.jsx(NoJavascript, {}) ] }) ] }); } function defineConfig(config) { return config; } function createConfig(config) { return config; } function validatePlugin(pluginResult) { const messages = [ "projectId" in pluginResult && "`projectId` not allowed in plugin configuration", "dataset" in pluginResult && "`dataset` not allowed in plugin configuration" ].filter(isString__default.default); if (messages.length) throw new Error( `Invalid plugin configuration: ${messages.map((message) => ` ${message}`).join(` `)}` ); } function definePlugin(arg) { if (typeof arg == "function") { const pluginFactory = arg; return (options) => { const result = pluginFactory(options); return validatePlugin(result), result; }; } return validatePlugin(arg), () => arg; } function createPlugin(arg) { return definePlugin(arg); } function defineDocumentFieldAction(fieldAction) { return fieldAction; } function defineDocumentInspector(inspector) { return inspector; } function createMockAuthStore({ client: client2, currentUser = null }) { return { state: rxjs.of({ authenticated: !0, client: client2, currentUser }) }; } function isEqual(item, otherItem) { if (item === otherItem) return !0; if (typeof item != typeof otherItem) return !1; if (typeof item != "object" && !Array.isArray(item)) return item === otherItem; if (types.isKeyedObject(item) && types.isKeyedObject(otherItem) && item._key === otherItem._key) return !0; if (Array.isArray(item) && Array.isArray(otherItem)) return item.length !== otherItem.length ? !1 : item.every((child, i) => isEqual(child, otherItem[i])); if (item === null || otherItem === null) return item === otherItem; const obj = item, otherObj = otherItem, keys = Object.keys(obj), otherKeys = Object.keys(otherObj); return keys.length !== otherKeys.length ? !1 : keys.every((keyName) => isEqual(obj[keyName], otherObj[keyName])); } const ArrayOfOptionsFieldDiff = ({ diff, schemaType }) => { var _a; const options = (_a = schemaType.options) == null ? void 0 : _a.list, colorManager = TransformPatches.useUserColorManager(), { t } = TransformPatches.useTranslation(); return Array.isArray(options) ? /* @__PURE__ */ jsxRuntime.jsx("div", { children: diff.items.map((item) => normalizeItems(item, diff, schemaType)).filter((item) => item !== null).sort(sortItems).map((item, index) => { const { annotation, isPresent, value, memberType, title } = item, color2 = TransformPatches.getAnnotationColor(colorManager, annotation), action = t(isPresent ? "changes.added-label" : "changes.removed-label"); return /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", children: [ /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.DiffTooltip, { annotations: annotation ? [annotation] : [], description: action, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Flex, { align: "center", children: [ /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.Checkbox, { checked: !isPresent, color: color2 }), /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { margin: 2, children: /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.FromToArrow, {}) }), /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.Checkbox, { checked: isPresent, color: color2 }) ] }) }), /* @__PURE__ */ jsxRuntime.jsx(ui.Flex, { align: "center", children: /* @__PURE__ */ jsxRuntime.jsx(ItemPreview, { value: title || value, memberType }) }) ] }, getItemKey(diff, index)); }) }) : null; }; function normalizeItems(item, parentDiff, schemaType) { if (item.diff.action === "unchanged") return null; const { fromValue, toValue } = parentDiff, value = getValue(item.diff), wasPresent = isInArray(value, fromValue), isPresent = isInArray(value, toValue); return wasPresent === isPresent ? null : { title: getItemTitle(value, schemaType), memberType: resolveMemberType(getValue(item.diff), schemaType), itemIndex: getOptionIndex(value, schemaType), annotation: item.annotation, isPresent, value }; } function sortItems(itemA, itemB) { return itemA.itemIndex - itemB.itemIndex; } function ItemPreview({ value, memberType }) { return /* @__PURE__ */ jsxRuntime.jsx(ui.Box, { marginX: 2, marginY: 1, children: typeof value == "string" || typeof value == "number" ? value : /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.Preview, { schemaType: memberType, value, layout: "default" }) }); } function isInArray(value, parent) { const array = parent || []; return typeof value == "object" && value !== null ? array.some((item) => isEqual(item, value)) : array.includes(value); } function getItemKey(diff, index) { const value = diff.toValue || diff.fromValue; return types.isKeyedObject(value) ? value._key : index; } function getValue(diff) { return typeof diff.toValue > "u" ? diff.fromValue : diff.toValue; } function resolveMemberType(item, schemaType) { const itemTypeName = resolveTypeName(item); return schemaType.of.find((memberType) => memberType.name === itemTypeName); } function resolveTypeName(value) { const jsType = resolveJSType(value); if (jsType !== "object") return jsType; const obj = value; return "_type" in obj && obj._type || jsType; } function resolveJSType(val) { return val === null ? "null" : Array.isArray(val) ? "array" : typeof val; } function isNamedOption(item) { return typeof item == "object" && item !== null && "title" in item; } function getOptionIndex(item, schemaType) { var _a; return (((_a = schemaType.options) == null ? void 0 : _a.list) || []).findIndex((opt) => isEqual(isNamedOption(opt) ? opt.value : opt, item)); } function getItemTitle(item, schemaType) { var _a; const list = ((_a = schemaType.options) == null ? void 0 : _a.list) || [], index = getOptionIndex(item, schemaType); return index === -1 ? void 0 : list[index].title || void 0; } const SlugFieldDiff = ({ diff, schemaType }) => /* @__PURE__ */ jsxRuntime.jsx( TransformPatches.DiffFromTo, { layout: "inline", diff, schemaType, previewComponent: TransformPatches.SlugPreview } ), UrlFieldDiff = ({ diff, schemaType }) => /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.DiffFromTo, { diff, schemaType, previewComponent: TransformPatches.StringPreview }), diffResolver = ({ schemaType }) => { var _a; if (["datetime", "date"].includes(schemaType.name)) return TransformPatches.DatetimeFieldDiff; if (schemaType.name === "url") return UrlFieldDiff; if (schemaType.name === "slug") return SlugFieldDiff; if (schemaType.jsonType === "array" && Array.isArray((_a = schemaType.options) == null ? void 0 : _a.list)) return ArrayOfOptionsFieldDiff; }; function HoveredFieldProvider(props) { const { children } = props, [hoveredStack, setHoveredStack] = React.useState([]), handleMouseEnter = React.useCallback((path) => { const pathString = TransformPatches.pathToString(path); setHoveredStack((prev) => prev.includes(pathString) ? prev : [pathString, ...prev]); }, []), handleMouseLeave = React.useCallback((path) => { const pathString = TransformPatches.pathToString(path); setHoveredStack((prev) => prev.includes(pathString) ? prev.filter((item) => item !== pathString) : prev); }, []), context = React.useMemo( () => ({ hoveredStack, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave }), [handleMouseEnter, handleMouseLeave, hoveredStack] ); return /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.HoveredFieldContext.Provider, { value: context, children }); } const EMPTY_ARRAY = []; function trimChildPath(path, childPath) { return PathUtils__namespace.startsWith(path, childPath) ? PathUtils__namespace.trimLeft(path, childPath) : EMPTY_ARRAY; } function PresenceScope(props) { const { readOnly, path, children } = props, contextPresence = React.useContext(TransformPatches.FormFieldPresenceContext), childPresence = React.useMemo(() => readOnly ? EMPTY_ARRAY : (contextPresence || EMPTY_ARRAY).filter((presence) => PathUtils__namespace.startsWith(path, presence.path)).map((presence) => ({ ...presence, path: trimChildPath(path, presence.path) })), [contextPresence, path, readOnly]); return /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.FormFieldPresenceContext.Provider, { value: childPresence, children }); } function createPatchChannel() { const _subscribers = []; return { publish(msg) { for (const subscriber of _subscribers) subscriber(msg); }, subscribe(subscriber) { return _subscribers.push(subscriber), () => { const idx = _subscribers.indexOf(subscriber); idx > -1 && _subscribers.splice(idx, 1); }; } }; } function ArrayOfObjectsInputMember(props) { const { member, renderAnnotation, renderBlock, renderField, renderInlineBlock, renderInput, renderItem, renderPreview } = props; return member.kind === "item" ? /* @__PURE__ */ jsxRuntime.jsx( TransformPatches.ArrayOfObjectsItem, { member, renderAnnotation, renderBlock, renderField, renderInlineBlock, renderInput, renderItem, renderPreview }, member.key ) : member.kind === "error" ? /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.MemberItemError, { member }, member.key) : (console.warn(new Error(`Unhandled member kind ${member.kind}`)), null); } function ArrayOfObjectsInputMembers(props) { const { members, ...rest } = props; return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: members.map((member) => /* @__PURE__ */ jsxRuntime.jsx(ArrayOfObjectsInputMember, { member, ...rest }, member.key)) }); } function useReviewChanges() { const reviewChanges = React.useContext(TransformPatches.ReviewChangesContext); if (!reviewChanges) throw new Error("Review changes: missing context value"); return reviewChanges; } const defaultRenderAnnotation = (props) => React.createElement(TransformPatches.defaultResolveAnnotationComponent(props.schemaType), props), defaultRenderBlock = (props) => React.createElement(TransformPatches.defaultResolveBlockComponent(props.schemaType), props), defaultRenderInlineBlock = (props) => React.createElement(TransformPatches.defaultResolveInlineBlockComponent(props.schemaType), props), defaultRenderField = (props) => React.createElement(TransformPatches.defaultResolveFieldComponent(props.schemaType), props), defaultRenderInput = (props) => React.createElement(TransformPatches.defaultResolveInputComponent(props.schemaType), props), defaultRenderItem = (props) => React.createElement(TransformPatches.defaultResolveItemComponent(props.schemaType), props), defaultRenderPreview = (props) => React.createElement(TransformPatches.Preview, props); function DefaultCustomMarkers() { return /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: 1, children: [ "This is a example custom marker, please implement ", /* @__PURE__ */ jsxRuntime.jsx("code", { children: "renderCustomMarkers" }), " function." ] }); } const missingPatchChannel = { publish: () => { }, subscribe: () => (console.warn( "No patch channel provided to form-builder. If you need input based patch updates, please provide one" ), () => { }) }; function FormBuilderProvider(props) { const { __internal_fieldActions: fieldActions = TransformPatches.EMPTY_ARRAY, __internal_patchChannel: patchChannel = missingPatchChannel, autoFocus, changesOpen, children, collapsedFieldSets, collapsedPaths, file, filterField, focusPath, focused, groups, id, image, onChange, onFieldGroupSelect, onPathBlur, onPathFocus, onPathOpen, onSetFieldSetCollapsed, onSetPathCollapsed, presence, readOnly, renderAnnotation, renderBlock, renderField, renderInlineBlock, renderInput, renderItem, renderPreview, schemaType, unstable, validation } = props, __internal = React.useMemo( () => ({ patchChannel, // eslint-disable-line camelcase components: { ArrayFunctions: TransformPatches.ArrayOfObjectsFunctions, CustomMarkers: (unstable == null ? void 0 : unstable.CustomMarkers) || DefaultCustomMarkers, Markers: (unstable == null ? void 0 : unstable.Markers) || TransformPatches.DefaultMarkers }, field: { actions: fieldActions }, file: { assetSources: file.assetSources, directUploads: (file == null ? void 0 : file.directUploads) !== !1 }, filterField: filterField || (() => !0), image: { assetSources: image.assetSources, directUploads: (image == null ? void 0 : image.directUploads) !== !1 }, onChange }), [ fieldActions, file.assetSources, file == null ? void 0 : file.directUploads, filterField, image.assetSources, image == null ? void 0 : image.directUploads, onChange, patchChannel, unstable == null ? void 0 : unstable.CustomMarkers, unstable == null ? void 0 : unstable.Markers ] ), formBuilder = React.useMemo( () => ({ __internal, autoFocus, changesOpen, collapsedFieldSets, collapsedPaths, focusPath, focused, groups, id, readOnly, renderAnnotation, renderBlock, renderField, renderInlineBlock, renderInput, renderItem, renderPreview, schemaType }), [ __internal, autoFocus, changesOpen, collapsedFieldSets, collapsedPaths, focusPath, focused, groups, id, readOnly, renderAnnotation, renderBlock, renderField, renderInlineBlock, renderInput, renderItem, renderPreview, schemaType ] ); return /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.FormBuilderContext.Provider, { value: formBuilder, children: /* @__PURE__ */ jsxRuntime.jsx( TransformPatches.FormCallbacksProvider, { onChange, onFieldGroupSelect, onPathBlur, onPathFocus, onPathOpen, onSetPathCollapsed, onSetFieldSetCollapsed, children: /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.DocumentIdProvider, { id, children: /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.PresenceProvider, { presence, children: /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.ValidationProvider, { validation, children: /* @__PURE__ */ jsxRuntime.jsx(HoveredFieldProvider, { children }) }) }) }) } ) }); } function FormProvider(props) { const { __internal_fieldActions: fieldActions, __internal_patchChannel: patchChannel, autoFocus, changesOpen, children, collapsedFieldSets, collapsedPaths, focusPath, focused, groups, id, onChange, onPathBlur, onPathFocus, onPathOpen, onFieldGroupSelect, onSetPathCollapsed, onSetFieldSetCollapsed, presence, readOnly, schemaType, validation } = props, { file, image } = TransformPatches.useSource().form, Input = TransformPatches.useInputComponent(), Field = TransformPatches.useFieldComponent(), Preview = TransformPatches.usePreviewComponent(), Item = TransformPatches.useItemComponent(), Block = TransformPatches.useBlockComponent(), InlineBlock = TransformPatches.useInlineBlockComponent(), Annotation = TransformPatches.useAnnotationComponent(), renderInput = React.useCallback( (inputProps) => /* @__PURE__ */ jsxRuntime.jsx(Input, { ...inputProps }), [Input] ), renderField = React.useCallback( (fieldProps) => /* @__PURE__ */ jsxRuntime.jsx(Field, { ...fieldProps }), [Field] ), renderItem = React.useCallback( (itemProps) => /* @__PURE__ */ jsxRuntime.jsx(Item, { ...itemProps }), [Item] ), renderPreview = React.useCallback( (previewProps) => /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.PreviewLoader, { component: Preview, ...previewProps }), [Preview] ), renderBlock = React.useCallback( (blockProps) => /* @__PURE__ */ jsxRuntime.jsx(Block, { ...blockProps }), [Block] ), renderInlineBlock = React.useCallback( (blockProps) => /* @__PURE__ */ jsxRuntime.jsx(InlineBlock, { ...blockProps }), [InlineBlock] ), renderAnnotation = React.useCallback( (annotationProps) => /* @__PURE__ */ jsxRuntime.jsx(Annotation, { ...annotationProps }), [Annotation] ); return /* @__PURE__ */ jsxRuntime.jsx( FormBuilderProvider, { __internal_fieldActions: fieldActions, __internal_patchChannel: patchChannel, autoFocus, changesOpen, collapsedFieldSets, collapsedPaths, file, focusPath, focused, groups, id, image, onChange, onPathBlur, onPathFocus, onPathOpen, onFieldGroupSelect, onSetPathCollapsed, onSetFieldSetCollapsed, presence, readOnly, renderAnnotation, renderBlock, renderField, renderInlineBlock, renderInput, renderItem, renderPreview, schemaType, validation, children } ); } function FormBuilder(props) { const { __internal_fieldActions: fieldActions, __internal_patchChannel: patchChannel, autoFocus, changesOpen, collapsedFieldSets, collapsedPaths, focusPath, focused, groups, id, members, onChange, onPathBlur, onPathFocus, onPathOpen, onFieldGroupSelect, onSetFieldSetCollapsed, onSetPathCollapsed, presence, readOnly, schemaType, validation, value } = props, handleCollapseField = React.useCallback( (fieldName) => onSetPathCollapsed([fieldName], !0), [onSetPathCollapsed] ), handleExpandField = React.useCallback( (fieldName) => onSetPathCollapsed([fieldName], !1), [onSetPathCollapsed] ), handleBlur = React.useCallback(() => onPathBlur(TransformPatches.EMPTY_ARRAY), [onPathBlur]), handleFocus = React.useCallback(() => onPathFocus(TransformPatches.EMPTY_ARRAY), [onPathFocus]), handleChange = React.useCallback( (patch) => onChange(TransformPatches.PatchEvent.from(patch)), [onChange] ), focusRef = React.useRef(null), handleSelectFieldGroup = React.useCallback( (groupName) => onFieldGroupSelect(TransformPatches.EMPTY_ARRAY, groupName), [onFieldGroupSelect] ), handleOpenField = React.useCallback((fieldName) => onPathOpen([fieldName]), [onPathOpen]), handleCloseField = React.useCallback(() => onPathOpen([]), [onPathOpen]), handleCollapseFieldSet = React.useCallback( (fieldSetName) => onSetFieldSetCollapsed([fieldSetName], !0), [onSetFieldSetCollapsed] ), handleExpandFieldSet = React.useCallback( (fieldSetName) => onSetFieldSetCollapsed([fieldSetName], !1), [onSetFieldSetCollapsed] ), Input = TransformPatches.useInputComponent(), Field = TransformPatches.useFieldComponent(), Preview = TransformPatches.usePreviewComponent(), Item = TransformPatches.useItemComponent(), Block = TransformPatches.useBlockComponent(), InlineBlock = TransformPatches.useInlineBlockComponent(), Annotation = TransformPatches.useAnnotationComponent(), renderInput = React.useCallback( (inputProps) => /* @__PURE__ */ jsxRuntime.jsx(Input, { ...inputProps }), [Input] ), renderField = React.useCallback( (fieldProps) => /* @__PURE__ */ jsxRuntime.jsx(Field, { ...fieldProps }), [Field] ), renderItem = React.useCallback( (itemProps) => /* @__PURE__ */ jsxRuntime.jsx(Item, { ...itemProps }), [Item] ), renderPreview = React.useCallback( (previewProps) => /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.PreviewLoader, { component: Preview, ...previewProps }), [Preview] ), renderBlock = React.useCallback( (blockProps) => /* @__PURE__ */ jsxRuntime.jsx(Block, { ...blockProps }), [Block] ), renderInlineBlock = React.useCallback( (blockProps) => /* @__PURE__ */ jsxRuntime.jsx(InlineBlock, { ...blockProps }), [InlineBlock] ), renderAnnotation = React.useCallback( (annotationProps) => /* @__PURE__ */ jsxRuntime.jsx(Annotation, { ...annotationProps }), [Annotation] ), rootInputProps = { focusPath, elementProps: { ref: focusRef, id, onBlur: handleBlur, onFocus: handleFocus, "aria-describedby": void 0 // Root input should not have any aria-describedby }, changed: members.some((m) => m.kind === "field" && m.field.changed), focused, groups, id, level: 0, members, onChange: handleChange, onFieldClose: handleCloseField, onFieldCollapse: handleCollapseField, onFieldSetCollapse: handleCollapseFieldSet, onFieldExpand: handleExpandField, onFieldSetExpand: handleExpandFieldSet, onPathFocus, onFieldOpen: handleOpenField, onFieldGroupSelect: handleSelectFieldGroup, path: TransformPatches.EMPTY_ARRAY, presence: TransformPatches.EMPTY_ARRAY, readOnly, renderAnnotation, renderBlock, renderField, renderInlineBlock, renderInput, renderItem, renderPreview, schemaType, validation: TransformPatches.EMPTY_ARRAY, value }; return /* @__PURE__ */ jsxRuntime.jsx( FormProvider, { __internal_fieldActions: fieldActions, __internal_patchChannel: patchChannel, autoFocus, changesOpen, collapsedFieldSets, collapsedPaths, focusPath, focused, groups, id, onChange, onPathBlur, onPathFocus, onPathOpen, onFieldGroupSelect, onSetPathCollapsed, onSetFieldSetCollapsed, presence, validation, readOnly, schemaType, children: /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.GetFormValueProvider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.FormValueProvider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(TransformPatches.DocumentFieldActionsProvider, { actions: fieldActions, children: renderInput(rootInputProps) }) }) }) } ); } const remoteSnapshots = TransformPatches.memoize( (client2, idPair, typeName) => TransformPatches.memoizedPair(client2, idPair, typeName).pipe( operators.switchMap(({ published, draft }) => rxjs.merge(published.remoteSnapshot$, draft.remoteSnapshot$)) ), TransformPatches.memoizeKeyGen ); function maybeSerialize(template) { return TransformPatches.isBuilder(template) ? template.serialize() : template; } function isNonNullable(t) { return !!t; } function prepareTemplates(schema, initialValueTemplates) { const serialized = initialValueTemplates.map(maybeSerialize); return TransformPatches.validateTemplates(schema, serialized); } function defaultTemplateForType(schemaType) { return { id: schemaType.name, schemaType: schemaType.name, title: schemaType.title || schemaType.name, icon: schemaType.icon, value: schemaType.initialValue || { _type: schemaType.name } }; } function defaultTemplatesForSchema(schema) { const schemaTypes = schema.getTypeNames().filter((typeName) => !/^sanity\./.test(typeName)).map((typeName) => schema.get(typeName)).filter(