@sanity/visual-editing
Version:
[](https://npm-stat.com/charts.html?package=@sanity/visual-editing) [](https://
326 lines (325 loc) • 11.9 kB
JavaScript
var reactCompilerRuntime = require("react-compiler-runtime"), csm = require("@sanity/client/csm"), mutate = require("@sanity/mutate"), presentationComlink = require("@sanity/presentation-comlink"), context = require("./context.cjs"), react = require("react"), getRandomValues = require("get-random-values-esm");
function _interopDefaultCompat(e) {
return e && typeof e == "object" && "default" in e ? e : { default: e };
}
var getRandomValues__default = /* @__PURE__ */ _interopDefaultCompat(getRandomValues);
const reKeySegment$1 = /_key\s*==\s*['"](.*)['"]/, reIndexTuple = /^\d*:\d*$/;
function isIndexSegment(segment) {
return typeof segment == "number" || typeof segment == "string" && /^\[\d+\]$/.test(segment);
}
function isKeySegment(segment) {
return typeof segment == "string" ? reKeySegment$1.test(segment.trim()) : typeof segment == "object" && "_key" in segment;
}
function isIndexTuple(segment) {
if (typeof segment == "string" && reIndexTuple.test(segment))
return !0;
if (!Array.isArray(segment) || segment.length !== 2)
return !1;
const [from, to] = segment;
return (typeof from == "number" || from === "") && (typeof to == "number" || to === "");
}
const rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g, reKeySegment = /_key\s*==\s*['"](.*)['"]/;
function get(obj, path, defaultVal) {
const select = typeof path == "string" ? fromString(path) : path;
if (!Array.isArray(select))
throw new Error("Path must be an array or a string");
let acc = obj;
for (let i = 0; i < select.length; i++) {
const segment = select[i];
if (isIndexSegment(segment)) {
if (!Array.isArray(acc))
return defaultVal;
acc = acc[segment];
}
if (isKeySegment(segment)) {
if (!Array.isArray(acc))
return defaultVal;
acc = acc.find((item) => item._key === segment._key);
}
if (typeof segment == "string" && (acc = typeof acc == "object" && acc !== null ? acc[segment] : void 0), typeof acc > "u")
return defaultVal;
}
return acc;
}
function fromString(path) {
if (typeof path != "string")
throw new Error("Path is not a string");
const segments = path.match(rePropName);
if (!segments)
throw new Error("Invalid path string");
return segments.map(normalizePathSegment);
}
function normalizePathSegment(segment) {
return isIndexSegment(segment) ? normalizeIndexSegment(segment) : isKeySegment(segment) ? normalizeKeySegment(segment) : isIndexTuple(segment) ? normalizeIndexTupleSegment(segment) : segment;
}
function normalizeIndexSegment(segment) {
return Number(segment.replace(/[^\d]/g, ""));
}
function normalizeKeySegment(segment) {
return { _key: segment.match(reKeySegment)[1] };
}
function normalizeIndexTupleSegment(segment) {
const [from, to] = segment.split(":").map((seg) => seg === "" ? seg : Number(seg));
return [from, to];
}
function useOptimisticActor() {
return react.useSyncExternalStore(_temp, _temp2, _temp3);
}
function _temp3() {
return context.emptyActor;
}
function _temp2() {
return context.actor;
}
function _temp(listener) {
return context.listeners.add(listener), () => context.listeners.delete(listener);
}
function useOptimisticActorReady() {
const actor2 = useOptimisticActor();
let t0;
return t0 = !context.isEmptyActor(actor2), t0;
}
function debounce(fn, timeout) {
let timer;
return (...args) => {
clearTimeout(timer), timer = setTimeout(() => {
fn.apply(fn, args);
}, timeout);
};
}
function getDocumentsAndSnapshot(id, actor) {
const inFrame = presentationComlink.isMaybePreviewIframe(), inPopUp = presentationComlink.isMaybePreviewWindow();
if (context.isEmptyActor(actor) || !inFrame && !inPopUp)
throw new Error("The `useDocuments` hook cannot be used in this context");
const draftId = csm.getDraftId(id), publishedId = csm.getPublishedId(id), documents = actor.getSnapshot().context?.documents, draftDoc = documents?.[draftId], publishedDoc = documents?.[publishedId], doc = draftDoc || publishedDoc;
if (!doc)
throw new Error(`Document "${id}" not found`);
const snapshot = draftDoc.getSnapshot().context?.local || publishedDoc.getSnapshot().context?.local, snapshotPromise = new Promise((resolve) => {
if (snapshot)
resolve(snapshot);
else {
const subscriber = doc.on("ready", (event) => {
const {
snapshot: snapshot2
} = event;
resolve(snapshot2 || null), subscriber.unsubscribe();
});
}
});
return {
draftDoc,
draftId,
getSnapshot: () => snapshotPromise,
publishedDoc,
publishedId,
/**
* @deprecated - use `getSnapshot` instead
*/
get snapshot() {
if (!snapshot)
throw new Error(`Snapshot for document "${id}" not found`);
return snapshot;
}
};
}
function createDocumentCommit(id, actor) {
return () => {
const {
draftDoc
} = getDocumentsAndSnapshot(id, actor);
draftDoc.send({
type: "submit"
});
};
}
function createDocumentGet(id, actor) {
return (path) => {
const {
snapshot
} = getDocumentsAndSnapshot(id, actor);
return path ? get(snapshot, path) : snapshot;
};
}
function createDocumentGetSnapshot(id, actor) {
const {
getSnapshot
} = getDocumentsAndSnapshot(id, actor);
return getSnapshot;
}
function createDocumentPatch(id, actor) {
return async (patches, options) => {
const result = getDocumentsAndSnapshot(id, actor), {
draftDoc,
draftId,
getSnapshot,
publishedId
} = result, {
commit = !0
} = options || {}, resolvedPatches = await (typeof patches == "function" ? patches({
draftId,
publishedId,
/**
* @deprecated - use `getSnapshot` instead
*/
get snapshot() {
return result.snapshot;
},
getSnapshot
}) : patches), _snapshot = await getSnapshot();
if (!_snapshot)
throw new Error(`Snapshot for document "${id}" not found`);
draftDoc.send({
type: "mutate",
mutations: [
// Attempt to create the draft document, it might not exist if the
// snapshot was from the published document
mutate.createIfNotExists({
..._snapshot,
_id: draftId
}),
// Patch the draft document with the resolved patches
mutate.patch(draftId, resolvedPatches)
]
}), commit && (typeof commit == "object" && "debounce" in commit ? debounce(() => draftDoc.send({
type: "submit"
}), commit.debounce)() : draftDoc.send({
type: "submit"
}));
};
}
function useDocuments() {
const $ = reactCompilerRuntime.c(7), actor = useOptimisticActor();
let t0;
$[0] !== actor ? (t0 = (documentId) => ({
id: documentId,
commit: createDocumentCommit(documentId, actor),
get: createDocumentGet(documentId, actor),
getSnapshot: createDocumentGetSnapshot(documentId, actor),
patch: createDocumentPatch(documentId, actor)
}), $[0] = actor, $[1] = t0) : t0 = $[1];
const getDocument = t0;
let t1;
$[2] !== actor ? (t1 = (id, mutations, options) => {
const {
draftDoc
} = getDocumentsAndSnapshot(id, actor), {
commit: t22
} = options || {}, commit = t22 === void 0 ? !0 : t22;
draftDoc.send({
type: "mutate",
mutations
}), commit && (typeof commit == "object" && "debounce" in commit ? debounce(() => draftDoc.send({
type: "submit"
}), commit.debounce)() : draftDoc.send({
type: "submit"
}));
}, $[2] = actor, $[3] = t1) : t1 = $[3];
const mutateDocument = t1;
let t2;
return $[4] !== getDocument || $[5] !== mutateDocument ? (t2 = {
getDocument,
mutateDocument
}, $[4] = getDocument, $[5] = mutateDocument, $[6] = t2) : t2 = $[6], t2;
}
function whatwgRNG(length = 16) {
const rnds8 = new Uint8Array(length);
return getRandomValues__default.default(rnds8), rnds8;
}
const getByteHexTable = /* @__PURE__ */ (() => {
let table;
return () => {
if (table)
return table;
table = [];
for (let i = 0; i < 256; ++i)
table[i] = (i + 256).toString(16).slice(1);
return table;
};
})();
function randomKey(length) {
const table = getByteHexTable();
return whatwgRNG(length).reduce((str, n) => str + table[n], "").slice(0, length);
}
function getArrayItemKeyAndParentPath(pathOrNode) {
const elementPath = typeof pathOrNode == "string" ? pathOrNode : pathOrNode.path, lastDotIndex = elementPath.lastIndexOf("."), lastPathItem = elementPath.substring(lastDotIndex + 1, elementPath.length);
if (!lastPathItem.indexOf("[")) throw new Error("Invalid path: not an array");
const lastArrayIndex = elementPath.lastIndexOf("["), path = elementPath.substring(0, lastArrayIndex);
let key, hasExplicitKey;
if (lastPathItem.includes("_key")) {
const startIndex = lastPathItem.indexOf('"') + 1, endIndex = lastPathItem.indexOf('"', startIndex);
key = lastPathItem.substring(startIndex, endIndex), hasExplicitKey = !0;
} else {
const startIndex = lastPathItem.indexOf("[") + 1, endIndex = lastPathItem.indexOf("]", startIndex);
key = lastPathItem.substring(startIndex, endIndex), hasExplicitKey = !1;
}
if (!path || !key) throw new Error("Invalid path");
return {
path,
key,
hasExplicitKey
};
}
function getArrayDuplicatePatches(node, snapshot, position = "after") {
const {
path: arrayPath,
key: itemKey
} = getArrayItemKeyAndParentPath(node), duplicate = {
...get(snapshot, node.path),
_key: randomKey()
};
return [mutate.at(arrayPath, mutate.insert(duplicate, position, {
_key: itemKey
}))];
}
function getArrayRemovePatches(node, snapshot) {
const {
path: arrayPath,
key: itemKey
} = getArrayItemKeyAndParentPath(node), currentIndex = get(snapshot, arrayPath).findIndex((item) => item._key === itemKey);
return [mutate.at(arrayPath, mutate.truncate(currentIndex, currentIndex + 1))];
}
function getArrayInsertPatches(node, insertType, position) {
const {
path: arrayPath,
key: itemKey
} = getArrayItemKeyAndParentPath(node), insertKey = randomKey();
return [mutate.at(arrayPath, mutate.insert([{
_type: insertType,
_key: insertKey
}], position, {
_key: itemKey
}))];
}
async function getArrayMovePatches(node, doc, moveTo) {
if (!node.type) throw new Error("Node type is missing");
const {
path: arrayPath,
key: itemKey
} = getArrayItemKeyAndParentPath(node), snapshot = await doc.getSnapshot(), array = get(snapshot, arrayPath), item = get(snapshot, node.path), currentIndex = array.findIndex((item2) => item2._key === itemKey);
let nextIndex = -1, position = "before";
if (moveTo === "first") {
if (currentIndex === 0) return [];
nextIndex = 0, position = "before";
} else if (moveTo === "last") {
if (currentIndex === array.length - 1) return [];
nextIndex = -1, position = "after";
} else if (moveTo === "next") {
if (currentIndex === array.length - 1) return [];
nextIndex = currentIndex, position = "after";
} else if (moveTo === "previous") {
if (currentIndex === 0) return [];
nextIndex = currentIndex - 1, position = "before";
}
return [mutate.at(arrayPath, mutate.truncate(currentIndex, currentIndex + 1)), mutate.at(arrayPath, mutate.insert(item, position, nextIndex))];
}
exports.get = get;
exports.getArrayDuplicatePatches = getArrayDuplicatePatches;
exports.getArrayInsertPatches = getArrayInsertPatches;
exports.getArrayItemKeyAndParentPath = getArrayItemKeyAndParentPath;
exports.getArrayMovePatches = getArrayMovePatches;
exports.getArrayRemovePatches = getArrayRemovePatches;
exports.useDocuments = useDocuments;
exports.useOptimisticActor = useOptimisticActor;
exports.useOptimisticActorReady = useOptimisticActorReady;
//# sourceMappingURL=mutations.cjs.map
;