const require_SuperConverter = require("./SuperConverter-C5uCLySV.cjs");
const require_create_headless_toolbar = require("./create-headless-toolbar-BUr9TmNG.cjs");
const DEFAULT_TEXT_ALIGN_OPTIONS = [
	{
		label: "Left",
		value: "left"
	},
	{
		label: "Center",
		value: "center"
	},
	{
		label: "Right",
		value: "right"
	},
	{
		label: "Justify",
		value: "justify"
	}
];
const DEFAULT_LINE_HEIGHT_OPTIONS = [
	{
		label: "1.00",
		value: 1
	},
	{
		label: "1.15",
		value: 1.15
	},
	{
		label: "1.50",
		value: 1.5
	},
	{
		label: "2.00",
		value: 2
	},
	{
		label: "2.50",
		value: 2.5
	},
	{
		label: "3.00",
		value: 3
	}
];
const DEFAULT_ZOOM_OPTIONS = [
	{
		label: "50%",
		value: 50
	},
	{
		label: "75%",
		value: 75
	},
	{
		label: "90%",
		value: 90
	},
	{
		label: "100%",
		value: 100
	},
	{
		label: "125%",
		value: 125
	},
	{
		label: "150%",
		value: 150
	},
	{
		label: "200%",
		value: 200
	}
];
const DEFAULT_DOCUMENT_MODE_OPTIONS = [
	{
		label: "Editing",
		value: "editing",
		description: "Edit document directly"
	},
	{
		label: "Suggesting",
		value: "suggesting",
		description: "Edits become suggestions"
	},
	{
		label: "Viewing",
		value: "viewing",
		description: "View clean version of document only"
	}
];
const DEFAULT_FONT_SIZE_OPTIONS = [
	{
		label: "8",
		value: "8pt"
	},
	{
		label: "9",
		value: "9pt"
	},
	{
		label: "10",
		value: "10pt"
	},
	{
		label: "11",
		value: "11pt"
	},
	{
		label: "12",
		value: "12pt"
	},
	{
		label: "14",
		value: "14pt"
	},
	{
		label: "18",
		value: "18pt"
	},
	{
		label: "24",
		value: "24pt"
	},
	{
		label: "30",
		value: "30pt"
	},
	{
		label: "36",
		value: "36pt"
	},
	{
		label: "48",
		value: "48pt"
	},
	{
		label: "60",
		value: "60pt"
	},
	{
		label: "72",
		value: "72pt"
	},
	{
		label: "96",
		value: "96pt"
	}
];
const DEFAULT_FONT_FAMILY_OPTIONS = [
	{
		label: "Aptos",
		value: "Aptos, Arial, sans-serif"
	},
	{
		label: "Georgia",
		value: "Georgia, serif"
	},
	{
		label: "Arial",
		value: "Arial, sans-serif"
	},
	{
		label: "Courier New",
		value: "Courier New, monospace"
	},
	{
		label: "Times New Roman",
		value: "Times New Roman, serif"
	}
];
const DEFAULT_TEXT_COLOR_OPTIONS = [
	{
		label: "Black",
		value: "#000000"
	},
	{
		label: "Dark Gray",
		value: "#434343"
	},
	{
		label: "Gray",
		value: "#666666"
	},
	{
		label: "Light Gray",
		value: "#999999"
	},
	{
		label: "Red",
		value: "#ff0000"
	},
	{
		label: "Orange",
		value: "#ff9900"
	},
	{
		label: "Yellow",
		value: "#ffff00"
	},
	{
		label: "Green",
		value: "#00ff00"
	},
	{
		label: "Cyan",
		value: "#00ffff"
	},
	{
		label: "Blue",
		value: "#0000ff"
	},
	{
		label: "Purple",
		value: "#9900ff"
	},
	{
		label: "Magenta",
		value: "#ff00ff"
	},
	{
		label: "None",
		value: "none"
	}
];
const DEFAULT_HIGHLIGHT_COLOR_OPTIONS = [
	{
		label: "Yellow",
		value: "#ffff00"
	},
	{
		label: "Green",
		value: "#00ff00"
	},
	{
		label: "Cyan",
		value: "#00ffff"
	},
	{
		label: "Pink",
		value: "#ff00ff"
	},
	{
		label: "Blue",
		value: "#0000ff"
	},
	{
		label: "Red",
		value: "#ff0000"
	},
	{
		label: "Orange",
		value: "#ff9900"
	},
	{
		label: "None",
		value: "none"
	}
];
const headlessToolbarConstants = {
	DEFAULT_TEXT_ALIGN_OPTIONS,
	DEFAULT_LINE_HEIGHT_OPTIONS,
	DEFAULT_ZOOM_OPTIONS,
	DEFAULT_DOCUMENT_MODE_OPTIONS,
	DEFAULT_FONT_SIZE_OPTIONS,
	DEFAULT_FONT_FAMILY_OPTIONS,
	DEFAULT_TEXT_COLOR_OPTIONS,
	DEFAULT_HIGHLIGHT_COLOR_OPTIONS
};
const BUILT_IN_COMMAND_IDS = [
	"bold",
	"italic",
	"underline",
	"strikethrough",
	"font-size",
	"font-family",
	"text-color",
	"highlight-color",
	"link",
	"text-align",
	"line-height",
	"linked-style",
	"bullet-list",
	"numbered-list",
	"indent-increase",
	"indent-decrease",
	"direction-ltr",
	"direction-rtl",
	"undo",
	"redo",
	"ruler",
	"formatting-marks",
	"zoom",
	"document-mode",
	"clear-formatting",
	"copy-format",
	"track-changes-accept-selection",
	"track-changes-reject-selection",
	"image",
	"table-of-contents-insert",
	"table-insert",
	"table-add-row-before",
	"table-add-row-after",
	"table-delete-row",
	"table-add-column-before",
	"table-add-column-after",
	"table-delete-column",
	"table-delete",
	"table-merge-cells",
	"table-split-cell",
	"table-remove-borders",
	"table-fix"
];
const headlessToolbarHelpers = {
	getQuickFormatList: require_create_headless_toolbar.getQuickFormatList,
	generateLinkedStyleString: require_create_headless_toolbar.generateLinkedStyleString,
	getFileOpener: require_create_headless_toolbar.getFileOpener,
	processAndInsertImageFile: require_create_headless_toolbar.processAndInsertImageFile
};
function parseCommaSeparatedIds(value) {
	return value.split(",").map((id) => id.trim()).filter(Boolean);
}
function getTrackChangeIds(node) {
	const trackChangeIds = node.getAttribute("data-track-change-ids");
	if (trackChangeIds !== null) {
		const ids = parseCommaSeparatedIds(trackChangeIds);
		if (ids.length > 0) return ids;
	}
	const trackChangeId = node.getAttribute("data-track-change-id");
	return trackChangeId ? [trackChangeId] : [];
}
function orderTrackChangeIds(ids, preferredTargetId) {
	if (!preferredTargetId || !ids.includes(preferredTargetId)) return ids;
	return [preferredTargetId, ...ids.filter((id) => id !== preferredTargetId)];
}
function collectEntityHitsFromChain(start) {
	if (!start || typeof start.getAttribute !== "function") return [];
	const hits = [];
	const seen = /* @__PURE__ */ new Set();
	let el = start;
	while (el) {
		const node = el;
		const trackChangeIds = orderTrackChangeIds(getTrackChangeIds(node), node.getAttribute("data-track-change-preferred-target-id"));
		for (const trackChangeId of trackChangeIds) {
			const key = `trackedChange:${trackChangeId}`;
			if (!seen.has(key)) {
				seen.add(key);
				hits.push({
					type: "trackedChange",
					id: trackChangeId
				});
			}
		}
		const commentIds = node.getAttribute("data-comment-ids");
		if (commentIds) for (const id of commentIds.split(",")) {
			if (!id) continue;
			const key = `comment:${id}`;
			if (!seen.has(key)) {
				seen.add(key);
				hits.push({
					type: "comment",
					id
				});
			}
		}
		const sdtType = node.getAttribute("data-sdt-type");
		const sdtId = node.getAttribute("data-sdt-id");
		if (sdtId && sdtType === "structuredContent") {
			const key = `contentControl:${sdtId}`;
			if (!seen.has(key)) {
				seen.add(key);
				const scopeAttr = node.getAttribute("data-sdt-scope");
				const tag = node.getAttribute("data-sdt-tag");
				const hit = {
					type: "contentControl",
					id: sdtId
				};
				if (scopeAttr === "block" || scopeAttr === "inline") hit.scope = scopeAttr;
				if (tag) hit.tag = tag;
				hits.push(hit);
			}
		}
		el = el.parentElement;
	}
	return hits;
}
function shallowEqual(a, b) {
	if (Object.is(a, b)) return true;
	if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
	if (Array.isArray(a)) {
		if (!Array.isArray(b) || a.length !== b.length) return false;
		for (let i = 0; i < a.length; i += 1) if (!Object.is(a[i], b[i])) return false;
		return true;
	}
	if (Array.isArray(b)) return false;
	const keysA = Object.keys(a);
	const keysB = Object.keys(b);
	if (keysA.length !== keysB.length) return false;
	for (const key of keysA) {
		if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
		if (!Object.is(a[key], b[key])) return false;
	}
	return true;
}
function resolvePositionAt(hostEditor, routedEditor, x, y) {
	if (!hostEditor || !routedEditor) return null;
	const presentation = hostEditor.presentationEditor;
	if (!presentation || typeof presentation.posAtCoords !== "function") return null;
	const host = presentation.visibleHost;
	if (host && typeof document !== "undefined") {
		const elAtPoint = document.elementFromPoint?.(x, y);
		if (elAtPoint && !host.contains(elAtPoint)) return null;
	}
	let result = null;
	try {
		result = presentation.posAtCoords({
			clientX: x,
			clientY: y
		});
	} catch {
		return null;
	}
	if (!result) return null;
	const block = findContainingTextBlock(routedEditor.state?.doc, result.pos);
	if (!block) return null;
	const offset = require_SuperConverter.pmPositionToTextOffset(block.node, block.pos, result.pos);
	const story = readActiveStoryLocator$1(hostEditor);
	const point = story ? {
		kind: "text",
		blockId: block.blockId,
		offset,
		story
	} : {
		kind: "text",
		blockId: block.blockId,
		offset
	};
	return {
		point,
		target: story ? {
			kind: "selection",
			start: point,
			end: point,
			story
		} : {
			kind: "selection",
			start: point,
			end: point
		}
	};
}
function readActiveStoryLocator$1(hostEditor) {
	const presentation = hostEditor.presentationEditor;
	if (!presentation || typeof presentation.getActiveStoryLocator !== "function") return null;
	try {
		return presentation.getActiveStoryLocator() ?? null;
	} catch {
		return null;
	}
}
function findContainingTextBlock(doc, pmPos) {
	if (!doc) return null;
	let match = null;
	doc.descendants((node, pos) => {
		if (match) return false;
		if (!node.isTextblock) return true;
		const blockStart = pos;
		const blockEnd = pos + node.nodeSize;
		if (pmPos < blockStart || pmPos > blockEnd) return false;
		const blockId = readBlockId(node);
		if (!blockId) return false;
		match = {
			node,
			pos,
			blockId
		};
		return false;
	});
	return match;
}
function readBlockId(node) {
	const attrs = node.attrs ?? {};
	const id = attrs.sdBlockId ?? attrs.id ?? attrs.blockId;
	return typeof id === "string" && id.length > 0 ? id : null;
}
function pointInsideRects(x, y, rects) {
	for (const rect of rects) if (x >= rect.left && x <= rect.left + rect.width && y >= rect.top && y <= rect.top + rect.height) return true;
	return false;
}
function buildViewportContext(args) {
	return {
		point: {
			x: args.x,
			y: args.y
		},
		entities: args.entities,
		position: args.position,
		selection: args.selection,
		insideSelection: pointInsideRects(args.x, args.y, args.selectionRects)
	};
}
function isViewportContextBundle(input) {
	if (input == null || typeof input !== "object") return false;
	const candidate = input;
	if (candidate.point == null || typeof candidate.point !== "object") return false;
	const p = candidate.point;
	return typeof p.x === "number" && typeof p.y === "number";
}
function canonicalKey(key) {
	return key.length === 1 ? key.toUpperCase() : key;
}
var MOD_ALIASES = new Set([
	"Mod",
	"Meta",
	"Cmd",
	"Command"
]);
var ALT_ALIASES = new Set(["Alt", "Option"]);
var CTRL_ALIASES = new Set(["Control", "Ctrl"]);
var SHIFT_ALIASES = new Set(["Shift"]);
function normalizeShortcut(input) {
	if (typeof input !== "string" || input.length === 0) return null;
	const parts = input.split("-").filter((p) => p.length > 0);
	if (parts.length === 0) return null;
	const key = parts[parts.length - 1];
	const modParts = parts.slice(0, -1);
	if (new Set([
		...MOD_ALIASES,
		...ALT_ALIASES,
		...CTRL_ALIASES,
		...SHIFT_ALIASES
	]).has(key)) return null;
	let hasMod = false;
	let hasAlt = false;
	let hasShift = false;
	for (const part of modParts) if (MOD_ALIASES.has(part) || CTRL_ALIASES.has(part)) hasMod = true;
	else if (ALT_ALIASES.has(part)) hasAlt = true;
	else if (SHIFT_ALIASES.has(part)) hasShift = true;
	else return null;
	const out = [];
	if (hasMod) out.push("Mod");
	if (hasAlt) out.push("Alt");
	if (hasShift) out.push("Shift");
	out.push(canonicalKey(key));
	return out.join("-");
}
function unshiftedPrintableFromCode(code) {
	if (!code) return null;
	if (code.startsWith("Digit") && code.length === 6) return code.slice(5);
	return null;
}
function shortcutFromEvent(event) {
	const rawKey = event.key;
	if (!rawKey || rawKey === "Control" || rawKey === "Meta" || rawKey === "Alt" || rawKey === "Shift") return null;
	let key = rawKey;
	if (event.shiftKey && rawKey.length === 1) {
		const unshifted = unshiftedPrintableFromCode(event.code);
		if (unshifted) key = unshifted;
	}
	const out = [];
	if (event.metaKey || event.ctrlKey) out.push("Mod");
	if (event.altKey) out.push("Alt");
	if (event.shiftKey) out.push("Shift");
	out.push(canonicalKey(key));
	return out.join("-");
}
async function scrollRangeIntoView(editor, input) {
	const presentation = editor.presentationEditor;
	if (!presentation) return { success: false };
	const target = input.target;
	if (target.kind === "entity") {
		if (typeof presentation.navigateTo !== "function") return { success: false };
		try {
			const ok = await presentation.navigateTo(target, {
				behavior: input.behavior ?? "smooth",
				block: input.block ?? "center"
			});
			return { success: Boolean(ok) };
		} catch {
			return { success: false };
		}
	}
	if (typeof presentation.scrollToPositionAsync !== "function") return { success: false };
	try {
		const firstSegment = Array.isArray(target.segments) && (target.segments.length ?? 0) > 0 ? target.segments[0] : {
			blockId: target.blockId,
			range: target.range
		};
		if (!firstSegment) return { success: false };
		const resolved = require_SuperConverter.resolveTextTarget(editor, {
			kind: "text",
			blockId: firstSegment.blockId,
			range: firstSegment.range
		});
		if (!resolved) return { success: false };
		const ok = await presentation.scrollToPositionAsync(resolved.from, {
			block: input.block ?? "center",
			behavior: input.behavior ?? "smooth"
		});
		return { success: Boolean(ok) };
	} catch {
		return { success: false };
	}
}
function getSelectionRects(hostEditor, routedEditor, capture) {
	const presentation = hostEditor?.presentationEditor;
	if (!presentation) return [];
	if (capture) return getCapturedSelectionRects(hostEditor, routedEditor ?? hostEditor, capture);
	if (typeof presentation.getSelectionRects !== "function") return [];
	try {
		return presentation.getSelectionRects().map(toViewportRect);
	} catch {
		return [];
	}
}
function getSelectionAnchorRect(hostEditor, routedEditor, options, capture) {
	const rects = getSelectionRects(hostEditor, routedEditor, capture);
	if (rects.length === 0) return null;
	const placement = options?.placement ?? "start";
	if (placement === "end") return rects[rects.length - 1];
	if (placement === "union") return computeUnionRect(rects);
	return rects[0];
}
function getCapturedSelectionRects(hostEditor, routedEditor, capture) {
	const presentation = hostEditor.presentationEditor;
	if (!presentation || typeof presentation.getRangeRects !== "function") return [];
	const segments = capture.target?.segments;
	if (!segments || segments.length === 0) return [];
	const first = segments[0];
	const last = segments[segments.length - 1];
	let fromResolved = null;
	let toResolved = null;
	try {
		fromResolved = require_SuperConverter.resolveTextTarget(routedEditor, {
			kind: "text",
			blockId: first.blockId,
			range: first.range
		});
		toResolved = require_SuperConverter.resolveTextTarget(routedEditor, {
			kind: "text",
			blockId: last.blockId,
			range: last.range
		});
	} catch (err) {
		if (err instanceof require_SuperConverter.DocumentApiAdapterError) console.warn(`[superdoc/ui] ui.selection.getRects: ${err.code}: ${err.message}`);
		return [];
	}
	if (!fromResolved || !toResolved) return [];
	try {
		return presentation.getRangeRects(fromResolved.from, toResolved.to).map(toViewportRect);
	} catch {
		return [];
	}
}
function toViewportRect(rect) {
	return {
		top: rect.top,
		left: rect.left,
		width: rect.width,
		height: rect.height,
		pageIndex: rect.pageIndex
	};
}
function computeUnionRect(rects) {
	let top = Infinity;
	let left = Infinity;
	let bottom = -Infinity;
	let right = -Infinity;
	const pageIndex = rects[0].pageIndex;
	for (const rect of rects) {
		if (rect.top < top) top = rect.top;
		if (rect.left < left) left = rect.left;
		if (rect.top + rect.height > bottom) bottom = rect.top + rect.height;
		if (rect.left + rect.width > right) right = rect.left + rect.width;
	}
	return {
		top,
		left,
		width: right - left,
		height: bottom - top,
		pageIndex
	};
}
var SUCCESS = { success: true };
function restoreSelection(editor, capture, options = {}) {
	if (!editor) return {
		success: false,
		reason: "not-ready"
	};
	if (editor.isEditable === false) return {
		success: false,
		reason: "read-only"
	};
	const setTextSelection = editor.commands?.setTextSelection;
	if (typeof setTextSelection !== "function") return {
		success: false,
		reason: "not-ready"
	};
	const capturedStory = capture.target?.story ?? null;
	if (capturedStory) {
		if (!storyMatches(options.activeStory ?? null, capturedStory)) return {
			success: false,
			reason: "stale"
		};
	}
	const segments = capture.target?.segments;
	if (!segments || segments.length === 0) return {
		success: false,
		reason: "missing-target"
	};
	const first = segments[0];
	const last = segments[segments.length - 1];
	let fromResolved = null;
	let toResolved = null;
	try {
		fromResolved = require_SuperConverter.resolveTextTarget(editor, {
			kind: "text",
			blockId: first.blockId,
			range: first.range
		});
		toResolved = require_SuperConverter.resolveTextTarget(editor, {
			kind: "text",
			blockId: last.blockId,
			range: last.range
		});
	} catch {
		return {
			success: false,
			reason: "stale"
		};
	}
	if (!fromResolved || !toResolved) return {
		success: false,
		reason: "stale"
	};
	if (capture.quotedText !== "") {
		const liveText = editor.state?.doc?.textBetween?.(fromResolved.from, toResolved.to, " ");
		if (typeof liveText === "string" && liveText !== capture.quotedText) return {
			success: false,
			reason: "stale"
		};
	}
	if (!setTextSelection({
		from: fromResolved.from,
		to: toResolved.to
	})) return {
		success: false,
		reason: "stale"
	};
	return SUCCESS;
}
function storyMatches(a, b) {
	if (!a || !b) return false;
	if (a.storyType !== b.storyType) return false;
	const ax = a;
	const bx = b;
	if (ax.refId !== bx.refId) return false;
	if (ax.noteId !== bx.noteId) return false;
	if (ax.headerFooterKind !== bx.headerFooterKind) return false;
	if (ax.variant !== bx.variant) return false;
	return JSON.stringify(ax.section ?? null) === JSON.stringify(bx.section ?? null);
}
var DEFAULT_SHORTCUT_COLLISION_MESSAGE = (shortcut, oldId, newId) => `[superdoc/ui] ui.commands.register(): shortcut '${shortcut}' was already bound to '${oldId}'. Replacing with '${newId}'.`;
var DEFAULT_INVALID_SHORTCUT_MESSAGE = (id, raw) => `[superdoc/ui] ui.commands.register(): id '${id}' carries an invalid shortcut '${raw}' — ignored. Use a string like 'Mod-Shift-K'.`;
var BUILTIN_CONTEXT_MENU_GROUPS = [
	"format",
	"clipboard",
	"review",
	"comment",
	"link"
];
var BUILTIN_GROUP_ORDER = new Map(BUILTIN_CONTEXT_MENU_GROUPS.map((g, i) => [g, i]));
var DEFAULT_CONTEXT_MENU_GROUP = "custom";
var DEFAULT_BUILTIN_COLLISION_MESSAGE = (id) => `[superdoc/ui] ui.commands.register(): id '${id}' collides with a built-in command. Pass { override: true } to replace deliberately. Registration refused.`;
var DEFAULT_REPLACEMENT_MESSAGE = (id) => `[superdoc/ui] ui.commands.register(): id '${id}' was already registered. Replacing prior registration.`;
var RESERVED_PROXY_PROPERTY_NAMES = new Set([
	"register",
	"get",
	"has",
	"require",
	"getContextMenuItems"
]);
var DEFAULT_RESERVED_NAME_MESSAGE = (id) => `[superdoc/ui] ui.commands.register(): id '${id}' shadows a Proxy method on ui.commands and would be unreachable through index access. Use a namespaced id (e.g. 'company.${id}') instead. Registration refused.`;
var STATIC_CUSTOM_STATE = {
	active: false,
	disabled: false,
	value: void 0
};
function createCustomCommandsRegistry(deps) {
	const entries = /* @__PURE__ */ new Map();
	const handleCache = /* @__PURE__ */ new Map();
	const subscribableCache = /* @__PURE__ */ new Map();
	let nextRegistrationSeq = 0;
	const shortcutIndex = /* @__PURE__ */ new Map();
	const releaseShortcuts = (entry) => {
		for (const sc of entry.shortcuts) if (shortcutIndex.get(sc) === entry.id) shortcutIndex.delete(sc);
	};
	const claimShortcuts = (id, raw) => {
		if (raw === void 0) return [];
		const list = Array.isArray(raw) ? raw : [raw];
		const claimed = [];
		for (const item of list) {
			const normalized = normalizeShortcut(item);
			if (!normalized) {
				console.warn(DEFAULT_INVALID_SHORTCUT_MESSAGE(id, item));
				continue;
			}
			const prior = shortcutIndex.get(normalized);
			if (prior && prior !== id) console.warn(DEFAULT_SHORTCUT_COLLISION_MESSAGE(normalized, prior, id));
			shortcutIndex.set(normalized, id);
			claimed.push(normalized);
		}
		return claimed;
	};
	const observerDisposers = /* @__PURE__ */ new Map();
	const getOrCreateSubscribable = (id) => {
		let sub = subscribableCache.get(id);
		if (sub) return sub;
		sub = deps.buildSubscribable(id);
		subscribableCache.set(id, sub);
		return sub;
	};
	const disposeAllObservers = (id) => {
		const set = observerDisposers.get(id);
		if (!set) return;
		const disposers = [...set];
		observerDisposers.delete(id);
		for (const dispose of disposers) try {
			dispose();
		} catch {}
	};
	const buildHandle = (id, ownEntry) => ({
		observe(listener) {
			let innerOff = null;
			let stopped = false;
			const dispose = () => {
				if (stopped) return;
				stopped = true;
				innerOff?.();
				innerOff = null;
				observerDisposers.get(id)?.delete(dispose);
			};
			let set = observerDisposers.get(id);
			if (!set) {
				set = /* @__PURE__ */ new Set();
				observerDisposers.set(id, set);
			}
			set.add(dispose);
			innerOff = getOrCreateSubscribable(id).subscribe((state) => {
				if (stopped) return;
				if (entries.get(id) !== ownEntry) {
					dispose();
					return;
				}
				const next = state ? {
					active: state.active,
					disabled: state.disabled,
					value: state.value,
					source: "custom"
				} : {
					...STATIC_CUSTOM_STATE,
					source: "custom",
					value: void 0
				};
				try {
					listener(next);
				} catch {}
			});
			return dispose;
		},
		execute: ((payload) => {
			if (entries.get(id) !== ownEntry) return false;
			return registry.execute(id, payload);
		})
	});
	const getHandle = (id) => {
		const entry = entries.get(id);
		if (!entry) return void 0;
		let cached = handleCache.get(id);
		if (cached) return cached;
		cached = buildHandle(id, entry);
		handleCache.set(id, cached);
		return cached;
	};
	const registry = {
		register(registration) {
			const { id, execute, getState, override = false } = registration;
			if (RESERVED_PROXY_PROPERTY_NAMES.has(id)) {
				console.warn(DEFAULT_RESERVED_NAME_MESSAGE(id));
				return {
					handle: buildNoOpHandle(id),
					invalidate() {},
					unregister() {}
				};
			}
			if (deps.isBuiltIn(id) && !override) {
				console.warn(DEFAULT_BUILTIN_COLLISION_MESSAGE(id));
				return {
					handle: buildNoOpHandle(id),
					invalidate() {},
					unregister() {}
				};
			}
			const priorEntry = entries.get(id);
			if (priorEntry) {
				console.warn(DEFAULT_REPLACEMENT_MESSAGE(id));
				disposeAllObservers(id);
				releaseShortcuts(priorEntry);
			}
			const ownEntry = {
				id,
				execute,
				getState,
				override,
				shortcuts: claimShortcuts(id, registration.shortcut),
				contextMenu: registration.contextMenu ?? null,
				registrationSeq: nextRegistrationSeq++,
				lastErrorMessage: null,
				lastContextMenuErrorMessage: null
			};
			entries.set(id, ownEntry);
			handleCache.delete(id);
			deps.scheduleNotify();
			let unregistered = false;
			return {
				handle: getHandle(id),
				invalidate() {
					if (unregistered) return;
					if (entries.get(id) !== ownEntry) return;
					deps.scheduleNotify();
				},
				unregister() {
					if (unregistered) return;
					unregistered = true;
					if (entries.get(id) !== ownEntry) return;
					entries.delete(id);
					handleCache.delete(id);
					subscribableCache.delete(id);
					releaseShortcuts(ownEntry);
					disposeAllObservers(id);
					deps.scheduleNotify();
				}
			};
		},
		has(id) {
			return entries.has(id);
		},
		computeStates(state) {
			const out = {};
			for (const entry of entries.values()) {
				let derived;
				if (entry.getState) try {
					const result = entry.getState({ state });
					derived = result == null ? void 0 : result;
				} catch (err) {
					derived = void 0;
					const message = err instanceof Error ? err.message : String(err);
					if (entry.lastErrorMessage !== message) {
						entry.lastErrorMessage = message;
						console.error(`[superdoc/ui] custom command '${entry.id}' getState threw: ${message}`);
					}
				}
				out[entry.id] = {
					active: derived?.active ?? STATIC_CUSTOM_STATE.active,
					disabled: derived?.disabled ?? STATIC_CUSTOM_STATE.disabled,
					value: derived ? derived.value : STATIC_CUSTOM_STATE.value,
					source: "custom"
				};
			}
			return out;
		},
		getHandle,
		execute(id, payload, context) {
			const entry = entries.get(id);
			if (!entry) return false;
			try {
				const result = entry.execute({
					payload,
					superdoc: deps.superdoc,
					editor: deps.getEditor(),
					context
				});
				if (result instanceof Promise) return result.then((value) => value !== false, (err) => {
					console.error(`[superdoc/ui] custom command '${id}' execute rejected:`, err);
					return false;
				});
				return result !== false;
			} catch (err) {
				console.error(`[superdoc/ui] custom command '${id}' execute threw:`, err);
				return false;
			}
		},
		getContextMenuItems(state, input) {
			const context = isViewportContextBundle(input) ? input : null;
			const entities = context ? context.entities : Array.isArray(input) ? input : [];
			const items = [];
			for (const entry of entries.values()) {
				const contribution = entry.contextMenu;
				if (!contribution) continue;
				if (contribution.when) {
					let applies = true;
					try {
						const whenInput = context ? {
							entities,
							selection: state.selection,
							point: context.point,
							position: context.position,
							insideSelection: context.insideSelection
						} : {
							entities,
							selection: state.selection
						};
						applies = contribution.when(whenInput) === true;
					} catch (err) {
						const message = err instanceof Error ? err.message : String(err);
						if (entry.lastContextMenuErrorMessage !== message) {
							entry.lastContextMenuErrorMessage = message;
							console.error(`[superdoc/ui] custom command '${entry.id}' contextMenu.when threw:`, err);
						}
						applies = false;
					}
					if (!applies) continue;
				} else entry.lastContextMenuErrorMessage = null;
				const ownEntry = entry;
				const itemId = entry.id;
				const invoke = context ? () => {
					if (entries.get(itemId) !== ownEntry) return false;
					return registry.execute(itemId, void 0, context);
				} : void 0;
				items.push({
					id: entry.id,
					label: contribution.label,
					group: contribution.group ?? DEFAULT_CONTEXT_MENU_GROUP,
					order: contribution.order ?? 0,
					...invoke ? { invoke } : {}
				});
			}
			const customGroupSeq = /* @__PURE__ */ new Map();
			for (const entry of entries.values()) {
				if (!entry.contextMenu) continue;
				const group = entry.contextMenu.group ?? DEFAULT_CONTEXT_MENU_GROUP;
				if (BUILTIN_GROUP_ORDER.has(group)) continue;
				const existing = customGroupSeq.get(group);
				if (existing === void 0 || entry.registrationSeq < existing) customGroupSeq.set(group, entry.registrationSeq);
			}
			const groupRank = (group) => {
				const builtin = BUILTIN_GROUP_ORDER.get(group);
				if (builtin !== void 0) return builtin;
				return BUILTIN_CONTEXT_MENU_GROUPS.length + (customGroupSeq.get(group) ?? 0);
			};
			const seqById = /* @__PURE__ */ new Map();
			for (const entry of entries.values()) seqById.set(entry.id, entry.registrationSeq);
			items.sort((a, b) => {
				const ga = groupRank(a.group);
				const gb = groupRank(b.group);
				if (ga !== gb) return ga - gb;
				if (a.order !== b.order) return a.order - b.order;
				return (seqById.get(a.id) ?? 0) - (seqById.get(b.id) ?? 0);
			});
			return items;
		},
		resolveShortcut(shortcut) {
			return shortcutIndex.get(shortcut);
		},
		destroy() {
			const ids = [...observerDisposers.keys()];
			for (const id of ids) disposeAllObservers(id);
			entries.clear();
			handleCache.clear();
			subscribableCache.clear();
			shortcutIndex.clear();
		}
	};
	return registry;
}
function buildNoOpHandle(id) {
	return {
		observe() {
			return () => {};
		},
		execute: ((..._args) => {
			console.warn(`[superdoc/ui] ui.commands['${id}'].execute(): registration was refused (built-in collision without override).`);
			return false;
		})
	};
}
function createScope(owner) {
	const teardowns = [];
	const childScopes = /* @__PURE__ */ new Set();
	let destroyed = false;
	const scope = {
		get destroyed() {
			return destroyed;
		},
		add(teardown) {
			if (destroyed) {
				runTeardown(teardown);
				return;
			}
			teardowns.push(teardown);
		},
		register(registration) {
			if (destroyed) throw new Error("[superdoc/ui] scope has been destroyed; cannot register a new command.");
			const result = owner.register(registration);
			teardowns.push(() => result.unregister());
			return result;
		},
		on(target, type, listener, options) {
			if (destroyed) return;
			target.addEventListener(type, listener, options);
			teardowns.push(() => target.removeEventListener(type, listener, options));
		},
		child() {
			if (destroyed) {
				const inert = createScope({
					register: owner.register,
					trackScope: () => () => void 0
				});
				inert.destroy();
				return inert;
			}
			return createScope({
				register: owner.register,
				trackScope: (s) => {
					childScopes.add(s);
					return () => {
						childScopes.delete(s);
					};
				}
			});
		},
		destroy() {
			if (destroyed) return;
			destroyed = true;
			const childSnapshot = [...childScopes];
			childScopes.clear();
			for (const child of childSnapshot) try {
				child.destroy();
			} catch (err) {
				console.error("[superdoc/ui] child scope destroy threw", err);
			}
			for (let i = teardowns.length - 1; i >= 0; i -= 1) runTeardown(teardowns[i]);
			teardowns.length = 0;
		}
	};
	const untrack = owner.trackScope(scope);
	teardowns.unshift(untrack);
	return scope;
}
function runTeardown(teardown) {
	try {
		teardown();
	} catch (err) {
		console.error("[superdoc/ui] scope teardown threw", err);
	}
}
var EDITOR_EVENTS = [
	"transaction",
	"selectionUpdate",
	"commentsUpdate",
	"commentsLoaded",
	"comment-positions",
	"tracked-changes-changed"
];
var LIST_REFRESH_EVENTS = [
	"commentsUpdate",
	"commentsLoaded",
	"tracked-changes-changed"
];
var SUPERDOC_EVENTS = [
	"editorCreate",
	"document-mode-change",
	"zoomChange"
];
var PRESENTATION_EVENTS = [
	"headerFooterEditingContext",
	"headerFooterUpdate",
	"headerFooterTransaction",
	"activeSurfaceChange",
	"historyStateChange"
];
var FALLBACK_COMMAND_STATE = {
	active: false,
	disabled: true,
	value: void 0
};
var FALLBACK_DYNAMIC_STATE = {
	active: false,
	disabled: true,
	value: void 0,
	source: "built-in"
};
var ALL_TOOLBAR_COMMAND_IDS = Object.keys(require_create_headless_toolbar.createToolbarRegistry());
var EMPTY_ACTIVE_IDS = Object.freeze([]);
function deepClone(value) {
	if (value === null || typeof value !== "object") return value;
	if (Array.isArray(value)) return value.map((item) => deepClone(item));
	const out = {};
	for (const key of Object.keys(value)) out[key] = deepClone(value[key]);
	return out;
}
function deepFreeze(value) {
	if (value === null || typeof value !== "object") return value;
	if (Object.isFrozen(value)) return value;
	if (Array.isArray(value)) for (const item of value) deepFreeze(item);
	else for (const key of Object.keys(value)) deepFreeze(value[key]);
	return Object.freeze(value);
}
function resolveFreshToolbarSources(superdoc) {
	return require_create_headless_toolbar.resolveToolbarSources(superdoc);
}
function resolveRoutedEditor(superdoc) {
	try {
		return resolveFreshToolbarSources(superdoc).activeEditor ?? null;
	} catch {
		return superdoc.activeEditor ?? null;
	}
}
function resolveHostEditor(superdoc) {
	return superdoc.activeEditor ?? null;
}
function resolvePresentationEditor(superdoc) {
	try {
		return resolveFreshToolbarSources(superdoc).presentationEditor ?? null;
	} catch {
		return null;
	}
}
function textTargetToSelectionTarget(textTarget) {
	if (!textTarget) return null;
	const segments = textTarget.segments;
	if (!segments || segments.length === 0) return null;
	const first = segments[0];
	const last = segments[segments.length - 1];
	const story = textTarget.story;
	const start = story ? {
		kind: "text",
		blockId: first.blockId,
		offset: first.range.start,
		story
	} : {
		kind: "text",
		blockId: first.blockId,
		offset: first.range.start
	};
	const end = story ? {
		kind: "text",
		blockId: last.blockId,
		offset: last.range.end,
		story
	} : {
		kind: "text",
		blockId: last.blockId,
		offset: last.range.end
	};
	return story ? {
		kind: "selection",
		start,
		end,
		story
	} : {
		kind: "selection",
		start,
		end
	};
}
function readActiveStoryLocator(superdoc) {
	let presentation = null;
	try {
		presentation = resolveFreshToolbarSources(superdoc).presentationEditor ?? null;
	} catch {
		return null;
	}
	if (!presentation || typeof presentation.getActiveStoryLocator !== "function") return null;
	try {
		return presentation.getActiveStoryLocator() ?? null;
	} catch {
		return null;
	}
}
function attachStoryToTextTarget(textTarget, story) {
	if (!textTarget || !story) return textTarget;
	if (textTarget.story) return textTarget;
	return {
		...textTarget,
		story
	};
}
function createSuperDocUI(options) {
	const { superdoc } = options;
	let destroyed = false;
	const stateChangeListeners = /* @__PURE__ */ new Set();
	const teardown = [];
	let scheduled = false;
	const scheduleNotify = () => {
		if (scheduled || destroyed) return;
		scheduled = true;
		queueMicrotask(() => {
			scheduled = false;
			if (destroyed) return;
			stateChangeListeners.forEach((listener) => {
				try {
					listener();
				} catch {}
			});
		});
	};
	const toolbarController = require_create_headless_toolbar.createHeadlessToolbar({
		superdoc,
		commands: ALL_TOOLBAR_COMMAND_IDS
	});
	let toolbarSnapshot = toolbarController.getSnapshot();
	const offToolbarSubscribe = toolbarController.subscribe(({ snapshot }) => {
		toolbarSnapshot = snapshot;
		scheduleNotify();
	});
	teardown.push(() => {
		offToolbarSubscribe();
		try {
			toolbarController.destroy();
		} catch {}
	});
	const BUILT_IN_COMMAND_ID_SET = new Set(ALL_TOOLBAR_COMMAND_IDS);
	const EMPTY_COMMENTS_LIST = {
		evaluatedRevision: "",
		total: 0,
		items: [],
		page: {
			limit: 0,
			offset: 0,
			returned: 0
		}
	};
	let commentsListCache = EMPTY_COMMENTS_LIST;
	const refreshCommentsListCache = () => {
		const editor = resolveRoutedEditor(superdoc);
		const list = editor?.doc?.comments?.list;
		if (typeof list !== "function") {
			commentsListCache = EMPTY_COMMENTS_LIST;
			return;
		}
		try {
			commentsListCache = list.call(editor.doc.comments, void 0) ?? EMPTY_COMMENTS_LIST;
		} catch {
			commentsListCache = EMPTY_COMMENTS_LIST;
		}
	};
	refreshCommentsListCache();
	const EMPTY_TRACK_CHANGES_LIST = {
		evaluatedRevision: "",
		total: 0,
		items: [],
		page: {
			limit: 0,
			offset: 0,
			returned: 0
		}
	};
	let trackChangesListCache = EMPTY_TRACK_CHANGES_LIST;
	const refreshTrackChangesListCache = () => {
		const editor = resolveRoutedEditor(superdoc);
		const list = editor?.doc?.trackChanges?.list;
		if (typeof list !== "function") {
			trackChangesListCache = EMPTY_TRACK_CHANGES_LIST;
			return;
		}
		try {
			trackChangesListCache = list.call(editor.doc.trackChanges, { in: "all" }) ?? EMPTY_TRACK_CHANGES_LIST;
		} catch {
			trackChangesListCache = EMPTY_TRACK_CHANGES_LIST;
		}
	};
	refreshTrackChangesListCache();
	const authorColorResolver = require_SuperConverter.composeAuthorColorResolver(superdoc.config?.modules?.trackChanges?.authorColors);
	const EMPTY_CONTENT_CONTROLS_LIST = {
		items: [],
		total: 0
	};
	let contentControlsListCache = EMPTY_CONTENT_CONTROLS_LIST;
	const refreshContentControlsListCache = () => {
		const editor = resolveRoutedEditor(superdoc);
		const list = editor?.doc?.contentControls?.list;
		if (typeof list !== "function") {
			contentControlsListCache = EMPTY_CONTENT_CONTROLS_LIST;
			return;
		}
		try {
			contentControlsListCache = list.call(editor.doc.contentControls, void 0) ?? EMPTY_CONTENT_CONTROLS_LIST;
		} catch {
			contentControlsListCache = EMPTY_CONTENT_CONTROLS_LIST;
		}
	};
	refreshContentControlsListCache();
	const EMPTY_ACTIVE_CONTENT_CONTROL_IDS = Object.freeze([]);
	let lastContentControlsListItems = null;
	let lastActiveContentControlIds = EMPTY_ACTIVE_CONTENT_CONTROL_IDS;
	let memoContentControlsSlice = null;
	const computeActiveContentControlIds = (validIds) => {
		const editor = resolveRoutedEditor(superdoc);
		const selection$1 = (editor?.state ?? editor?.view?.state)?.selection;
		if (!selection$1) return EMPTY_ACTIVE_CONTENT_CONTROL_IDS;
		const ids = [];
		const selectedNode = selection$1.node;
		if (selectedNode && (selectedNode.type?.name === "structuredContent" || selectedNode.type?.name === "structuredContentBlock")) {
			const id = selectedNode.attrs?.id;
			if (typeof id === "string" && id.length > 0 && validIds.has(id)) ids.push(id);
		}
		const anchor = selection$1.$anchor;
		if (anchor && typeof anchor.depth === "number" && typeof anchor.node === "function") for (let d = anchor.depth; d >= 0; d -= 1) {
			const node = anchor.node(d);
			const typeName = node?.type?.name;
			if (typeName !== "structuredContent" && typeName !== "structuredContentBlock") continue;
			const id = node?.attrs?.id;
			if (typeof id !== "string" || id.length === 0) continue;
			if (!validIds.has(id)) continue;
			if (ids.includes(id)) continue;
			ids.push(id);
		}
		if (ids.length === 0) return EMPTY_ACTIVE_CONTENT_CONTROL_IDS;
		return Object.freeze(ids);
	};
	let activeTrackChangeId = null;
	let lastSelectionDrivenId = null;
	let trackChangesMemo = null;
	let selectionMemo = null;
	let documentMemo = null;
	let dirty = false;
	const buildSelectionKey = (empty, target, activeMarks, activeCommentIds, activeChangeIds, quotedText) => {
		const story = target ? target.story : void 0;
		let storyKey = "";
		if (story) {
			const storyType = typeof story.storyType === "string" ? story.storyType : "";
			const refId = typeof story.refId === "string" ? story.refId : "";
			const noteId = typeof story.noteId === "string" ? story.noteId : "";
			const section = story.section && typeof story.section === "object" ? JSON.stringify(story.section) : "";
			storyKey = `s=${storyType}:r=${refId}:n=${noteId}:hf=${typeof story.headerFooterKind === "string" ? story.headerFooterKind : ""}:v=${typeof story.variant === "string" ? story.variant : ""}:sec=${section}`;
		}
		const targetKey = target ? target.segments.map((s) => `${s.blockId}:${s.range.start}-${s.range.end}`).join("|") : "null";
		const marks = [...activeMarks].sort().join(",");
		const comments$1 = [...activeCommentIds].sort().join(",");
		const changes = [...activeChangeIds].sort().join(",");
		return `${empty ? "1" : "0"}:${storyKey}:${targetKey}:m=${marks}:c=${comments$1}:tc=${changes}:t=${quotedText}`;
	};
	const computeState = () => {
		const editor = resolveRoutedEditor(superdoc);
		const ready = editor != null;
		const selectionInfo = editor?.doc?.selection?.current?.({ includeText: true });
		const empty = selectionInfo ? selectionInfo.empty : true;
		const quotedText = selectionInfo?.text ?? "";
		const documentMode = superdoc.config?.documentMode ?? null;
		const activeIds = selectionInfo?.activeCommentIds ?? EMPTY_ACTIVE_IDS;
		const activeChangeIdsFromSelection = selectionInfo?.activeChangeIds ?? EMPTY_ACTIVE_IDS;
		const selectionDrivenActiveId = activeChangeIdsFromSelection[0] ?? null;
		const selectionMoved = selectionDrivenActiveId !== lastSelectionDrivenId;
		lastSelectionDrivenId = selectionDrivenActiveId;
		if (selectionMoved && selectionDrivenActiveId) activeTrackChangeId = selectionDrivenActiveId;
		let trackChangesSlice;
		if (trackChangesMemo && trackChangesMemo.changesRef === trackChangesListCache.items && trackChangesMemo.activeId === activeTrackChangeId) trackChangesSlice = trackChangesMemo.slice;
		else {
			const authors = [];
			const seenAuthorKeys = /* @__PURE__ */ new Set();
			const items = trackChangesListCache.items.map((change) => {
				if (!authorColorResolver) return {
					id: change.id,
					change
				};
				const author = {
					name: typeof change.author === "string" ? change.author : void 0,
					email: typeof change.authorEmail === "string" ? change.authorEmail : void 0,
					image: typeof change.authorImage === "string" ? change.authorImage : void 0
				};
				const authorColor = authorColorResolver(author);
				if (authorColor && (author.name || author.email)) {
					const key = JSON.stringify([author.name ?? "", author.email ?? ""]);
					if (!seenAuthorKeys.has(key)) {
						seenAuthorKeys.add(key);
						authors.push({
							...author,
							color: authorColor
						});
					}
				}
				if (!authorColor) return {
					id: change.id,
					change
				};
				return {
					id: change.id,
					change: {
						...change,
						authorColor
					},
					authorColor
				};
			});
			if (activeTrackChangeId && !items.some((item) => item.id === activeTrackChangeId)) activeTrackChangeId = null;
			trackChangesSlice = {
				items,
				total: items.length,
				activeId: activeTrackChangeId,
				authors
			};
			trackChangesMemo = {
				changesRef: trackChangesListCache.items,
				activeId: activeTrackChangeId,
				slice: trackChangesSlice
			};
		}
		const hostEditor = resolveHostEditor(superdoc);
		const activeStory = editor != null && hostEditor != null && editor !== hostEditor ? readActiveStoryLocator(superdoc) : null;
		const selectionTextTarget = attachStoryToTextTarget(selectionInfo?.target ?? null, activeStory);
		const selectionActiveMarks = selectionInfo?.activeMarks ?? EMPTY_ACTIVE_IDS;
		const selectionKey = buildSelectionKey(empty, selectionTextTarget, selectionActiveMarks, activeIds, activeChangeIdsFromSelection, quotedText);
		let selectionSlice;
		if (selectionMemo && selectionMemo.key === selectionKey) selectionSlice = selectionMemo.slice;
		else {
			selectionSlice = {
				empty,
				target: selectionTextTarget,
				selectionTarget: textTargetToSelectionTarget(selectionTextTarget),
				activeMarks: selectionActiveMarks,
				activeCommentIds: activeIds,
				activeChangeIds: activeChangeIdsFromSelection,
				quotedText
			};
			selectionMemo = {
				key: selectionKey,
				slice: selectionSlice
			};
		}
		const builtInCommands = {};
		if (toolbarSnapshot.commands) for (const [id, cmdState] of Object.entries(toolbarSnapshot.commands)) {
			if (!cmdState) continue;
			builtInCommands[id] = {
				active: cmdState.active,
				disabled: cmdState.disabled,
				value: cmdState.value,
				source: "built-in"
			};
		}
		let documentSlice;
		if (documentMemo && documentMemo.slice.ready === ready && documentMemo.slice.mode === documentMode && documentMemo.slice.dirty === dirty) documentSlice = documentMemo.slice;
		else {
			documentSlice = {
				ready,
				mode: documentMode,
				dirty
			};
			documentMemo = { slice: documentSlice };
		}
		const partial = {
			ready,
			documentMode,
			document: documentSlice,
			selection: selectionSlice,
			toolbar: {
				context: toolbarSnapshot.context,
				commands: builtInCommands
			},
			comments: {
				total: commentsListCache.total,
				items: commentsListCache.items,
				activeIds: selectionSlice.activeCommentIds
			},
			trackChanges: trackChangesSlice,
			contentControls: (() => {
				const items = contentControlsListCache.items;
				const total = contentControlsListCache.total;
				const nextActive = computeActiveContentControlIds(new Set(items.map((it) => it.id)));
				const activeIdsSame = nextActive === lastActiveContentControlIds || nextActive.length === lastActiveContentControlIds.length && nextActive.every((id, i) => id === lastActiveContentControlIds[i]);
				const activeIds$1 = activeIdsSame ? lastActiveContentControlIds : nextActive;
				if (memoContentControlsSlice && items === lastContentControlsListItems && activeIdsSame) return memoContentControlsSlice;
				lastContentControlsListItems = items;
				lastActiveContentControlIds = activeIds$1;
				memoContentControlsSlice = {
					total,
					items,
					activeIds: activeIds$1,
					activeId: activeIds$1[0] ?? null
				};
				return memoContentControlsSlice;
			})()
		};
		const customCommandStates = customCommandsRegistry.computeStates(partial);
		const mergedCommands = customCommandStates ? {
			...builtInCommands,
			...customCommandStates
		} : builtInCommands;
		return {
			...partial,
			toolbar: {
				context: toolbarSnapshot.context,
				commands: mergedCommands
			}
		};
	};
	const geometryListeners = /* @__PURE__ */ new Set();
	const pendingGeometryReasons = /* @__PURE__ */ new Set();
	let geometryRaf = null;
	let zoomPending = false;
	const cancelGeometryFrame = () => {
		if (geometryRaf == null) return;
		if (typeof cancelAnimationFrame === "function") cancelAnimationFrame(geometryRaf);
		else clearTimeout(geometryRaf);
		geometryRaf = null;
	};
	const flushGeometry = () => {
		geometryRaf = null;
		const reasons = [...pendingGeometryReasons];
		pendingGeometryReasons.clear();
		if (geometryListeners.size === 0 || reasons.length === 0) return;
		const reason = reasons.length === 1 ? reasons[0] : "mixed";
		[...geometryListeners].forEach((listener) => {
			try {
				listener({ reason });
			} catch {}
		});
	};
	const scheduleGeometry = (reason) => {
		if (geometryListeners.size === 0) return;
		pendingGeometryReasons.add(reason);
		if (geometryRaf != null) return;
		geometryRaf = typeof requestAnimationFrame === "function" ? requestAnimationFrame(flushGeometry) : setTimeout(flushGeometry, 0);
	};
	const onGeometryZoom = () => {
		zoomPending = true;
	};
	const onGeometryLayout = () => {
		if (zoomPending) {
			zoomPending = false;
			scheduleGeometry("zoom");
		} else scheduleGeometry("layout");
	};
	const onWindowScrollGeometry = () => scheduleGeometry("scroll");
	const onWindowResizeGeometry = () => scheduleGeometry("resize");
	let domGeometryAttached = false;
	const attachDomGeometryListeners = () => {
		if (domGeometryAttached || typeof window === "undefined") return;
		domGeometryAttached = true;
		window.addEventListener("scroll", onWindowScrollGeometry, true);
		window.addEventListener("resize", onWindowResizeGeometry);
	};
	const detachDomGeometryListeners = () => {
		if (!domGeometryAttached || typeof window === "undefined") return;
		domGeometryAttached = false;
		window.removeEventListener("scroll", onWindowScrollGeometry, true);
		window.removeEventListener("resize", onWindowResizeGeometry);
	};
	teardown.push(() => {
		detachDomGeometryListeners();
		cancelGeometryFrame();
		geometryListeners.clear();
		pendingGeometryReasons.clear();
	});
	if (typeof superdoc.on === "function" && typeof superdoc.off === "function") {
		SUPERDOC_EVENTS.forEach((name) => {
			superdoc.on?.(name, scheduleNotify);
		});
		superdoc.on?.("zoomChange", onGeometryZoom);
		teardown.push(() => {
			SUPERDOC_EVENTS.forEach((name) => superdoc.off?.(name, scheduleNotify));
			superdoc.off?.("zoomChange", onGeometryZoom);
		});
	}
	let currentEditor = null;
	let currentEditorTeardown = null;
	const refreshAndNotify = () => {
		refreshCommentsListCache();
		refreshTrackChangesListCache();
		scheduleNotify();
	};
	const refreshContentControlsAndNotify = () => {
		refreshContentControlsListCache();
		scheduleNotify();
	};
	const onDocChangedForContentControls = (payload) => {
		const tr = payload?.transaction;
		if (tr && tr.docChanged === true) refreshContentControlsAndNotify();
	};
	const onTransaction = (payload) => {
		if (dirty) return;
		const tr = payload?.transaction;
		if (tr && tr.docChanged === true) dirty = true;
	};
	const attachEditorListeners = () => {
		const next = resolveRoutedEditor(superdoc);
		if (next === currentEditor) return;
		currentEditorTeardown?.();
		currentEditorTeardown = null;
		currentEditor = next;
		if (!next || typeof next.on !== "function" || typeof next.off !== "function") return;
		EDITOR_EVENTS.forEach((name) => {
			next.on?.(name, scheduleNotify);
		});
		LIST_REFRESH_EVENTS.forEach((name) => {
			next.on?.(name, refreshAndNotify);
		});
		next.on?.("transaction", onTransaction);
		next.on?.("transaction", onDocChangedForContentControls);
		currentEditorTeardown = () => {
			EDITOR_EVENTS.forEach((name) => next.off?.(name, scheduleNotify));
			LIST_REFRESH_EVENTS.forEach((name) => next.off?.(name, refreshAndNotify));
			next.off?.("transaction", onTransaction);
			next.off?.("transaction", onDocChangedForContentControls);
		};
		refreshCommentsListCache();
		refreshContentControlsListCache();
		scheduleNotify();
	};
	let currentPresentation = null;
	let currentPresentationTeardown = null;
	const attachPresentationListeners = () => {
		const next = resolvePresentationEditor(superdoc);
		if (next === currentPresentation) return;
		currentPresentationTeardown?.();
		currentPresentationTeardown = null;
		currentPresentation = next;
		if (!next || typeof next.on !== "function" || typeof next.off !== "function") return;
		const onPresentationChange = () => {
			attachEditorListeners();
			scheduleNotify();
		};
		PRESENTATION_EVENTS.forEach((name) => {
			next.on?.(name, onPresentationChange);
		});
		next.on?.("layoutUpdated", onGeometryLayout);
		currentPresentationTeardown = () => {
			PRESENTATION_EVENTS.forEach((name) => next.off?.(name, onPresentationChange));
			next.off?.("layoutUpdated", onGeometryLayout);
		};
	};
	const resetDirtyOnNewDocument = () => {
		if (dirty) {
			dirty = false;
			scheduleNotify();
		}
	};
	attachPresentationListeners();
	attachEditorListeners();
	if (typeof superdoc.on === "function") {
		superdoc.on?.("editorCreate", attachPresentationListeners);
		superdoc.on?.("editorCreate", attachEditorListeners);
		superdoc.on?.("editorCreate", resetDirtyOnNewDocument);
	}
	teardown.push(() => {
		if (typeof superdoc.off === "function") {
			superdoc.off?.("editorCreate", attachPresentationListeners);
			superdoc.off?.("editorCreate", attachEditorListeners);
			superdoc.off?.("editorCreate", resetDirtyOnNewDocument);
		}
		currentPresentationTeardown?.();
		currentPresentationTeardown = null;
		currentPresentation = null;
		currentEditorTeardown?.();
		currentEditorTeardown = null;
		currentEditor = null;
	});
	const select = (selector, equality = Object.is) => {
		let last = selector(computeState());
		const listeners = /* @__PURE__ */ new Set();
		const onStateChange = () => {
			const next = selector(computeState());
			if (equality(last, next)) return;
			last = next;
			listeners.forEach((listener) => {
				try {
					listener(next);
				} catch {}
			});
		};
		return {
			get() {
				if (listeners.size === 0) last = selector(computeState());
				return last;
			},
			subscribe(listener) {
				if (listeners.size === 0) {
					last = selector(computeState());
					stateChangeListeners.add(onStateChange);
				}
				listeners.add(listener);
				try {
					listener(last);
				} catch {}
				return () => {
					listeners.delete(listener);
					if (listeners.size === 0) stateChangeListeners.delete(onStateChange);
				};
			}
		};
	};
	const toolbar = {
		getSnapshot: () => computeState().toolbar,
		observe(listener) {
			return select((state) => state.toolbar, () => false).subscribe((snapshot) => {
				try {
					listener(snapshot);
				} catch {}
			});
		},
		subscribe(listener) {
			return toolbar.observe((snapshot) => listener({ snapshot }));
		},
		execute: ((id, payload) => {
			const result = dispatchCommand(id, payload);
			return result instanceof Promise ? true : result;
		})
	};
	const commandHandleCache = /* @__PURE__ */ new Map();
	const commandSubscribableCache = /* @__PURE__ */ new Map();
	const getCommandSubscribable = (id) => {
		let sub = commandSubscribableCache.get(id);
		if (sub) return sub;
		sub = select((state) => state.toolbar.commands?.[id], shallowEqual);
		commandSubscribableCache.set(id, sub);
		return sub;
	};
	const buildCommandHandle = (id) => {
		return {
			observe(listener) {
				return getCommandSubscribable(id).subscribe((cmdState) => {
					const next = cmdState ?? FALLBACK_COMMAND_STATE;
					try {
						listener(next);
					} catch {}
				});
			},
			execute: ((payload) => {
				const result = dispatchCommand(id, payload);
				return result instanceof Promise ? true : result;
			})
		};
	};
	const customCommandsRegistry = createCustomCommandsRegistry({
		superdoc,
		getEditor: () => resolveRoutedEditor(superdoc),
		isBuiltIn: (id) => BUILT_IN_COMMAND_ID_SET.has(id),
		scheduleNotify,
		buildSubscribable: (id) => select((state) => state.toolbar.commands?.[id], shallowEqual)
	});
	teardown.push(() => {
		customCommandsRegistry.destroy();
	});
	if (typeof globalThis !== "undefined" && globalThis.document) {
		const dom = globalThis.document;
		const onKeyDown = (event) => {
			const ke = event;
			const editor = resolveRoutedEditor(superdoc);
			if (!editor) return;
			const target = ke.target;
			if (!target) return;
			const inHost = editor.presentationEditor?.visibleHost?.contains(target) === true;
			const inPmDom = editor.view?.dom?.contains(target) === true;
			if (!inHost && !inPmDom) return;
			const combo = shortcutFromEvent(ke);
			if (!combo) return;
			const id = customCommandsRegistry.resolveShortcut(combo);
			if (!id) return;
			customCommandsRegistry.execute(id);
			ke.preventDefault();
		};
		dom.addEventListener("keydown", onKeyDown);
		teardown.push(() => {
			dom.removeEventListener("keydown", onKeyDown);
		});
	}
	const dispatchCommand = (id, payload) => {
		if (customCommandsRegistry.has(id)) return customCommandsRegistry.execute(id, payload);
		return toolbarController.execute(id, payload);
	};
	const dynamicHandleCache = /* @__PURE__ */ new Map();
	const buildBuiltInDynamicHandle = (id) => {
		return {
			observe(listener) {
				return getCommandSubscribable(id).subscribe((cmdState) => {
					const next = cmdState ?? FALLBACK_DYNAMIC_STATE;
					try {
						listener(next);
					} catch {}
				});
			},
			execute(payload) {
				return dispatchCommand(id, payload);
			}
		};
	};
	const buildCustomDynamicHandle = (id) => {
		const customHandle = customCommandsRegistry.getHandle(id);
		if (!customHandle) return void 0;
		return {
			observe(listener) {
				return customHandle.observe(listener);
			},
			execute(payload) {
				return customHandle.execute(payload);
			}
		};
	};
	const getDynamicHandle = (id) => {
		if (typeof id !== "string" || id.length === 0) return void 0;
		if (customCommandsRegistry.has(id)) return buildCustomDynamicHandle(id);
		if (!BUILT_IN_COMMAND_ID_SET.has(id)) return void 0;
		let cached = dynamicHandleCache.get(id);
		if (cached) return cached;
		cached = buildBuiltInDynamicHandle(id);
		dynamicHandleCache.set(id, cached);
		return cached;
	};
	const commands = new Proxy({}, { get(_, prop) {
		if (typeof prop !== "string") return void 0;
		if (prop === "register") return customCommandsRegistry.register.bind(customCommandsRegistry);
		if (prop === "get") return getDynamicHandle;
		if (prop === "has") return (id) => {
			if (typeof id !== "string" || id.length === 0) return false;
			return BUILT_IN_COMMAND_ID_SET.has(id) || customCommandsRegistry.has(id);
		};
		if (prop === "require") return (id) => {
			const handle$1 = getDynamicHandle(id);
			if (!handle$1) throw new Error(`[superdoc/ui] commands.require: unknown command id "${id}".`);
			return handle$1;
		};
		if (prop === "getContextMenuItems") return (input) => {
			if (isViewportContextBundle(input)) return customCommandsRegistry.getContextMenuItems(computeState(), input);
			return customCommandsRegistry.getContextMenuItems(computeState(), input?.entities ?? []);
		};
		if (customCommandsRegistry.has(prop)) {
			const customHandle = customCommandsRegistry.getHandle(prop);
			if (customHandle) return customHandle;
		}
		let handle = commandHandleCache.get(prop);
		if (handle) return handle;
		handle = buildCommandHandle(prop);
		commandHandleCache.set(prop, handle);
		return handle;
	} });
	const requireDocComments = () => {
		const api = resolveRoutedEditor(superdoc)?.doc?.comments;
		if (!api) throw new Error("ui.comments: no active editor / comments API. Open a document first.");
		return api;
	};
	const runScrollIntoView = async (input) => {
		const editor = resolveHostEditor(superdoc);
		if (!editor) return { success: false };
		return scrollRangeIntoView(editor, input);
	};
	const comments = {
		getSnapshot: () => computeState().comments,
		observe(listener) {
			return select((state) => state.comments, shallowEqual).subscribe((snapshot) => {
				try {
					listener(snapshot);
				} catch {}
			});
		},
		subscribe(listener) {
			return comments.observe((snapshot) => listener({ snapshot }));
		},
		createFromSelection({ text }) {
			const target = resolveRoutedEditor(superdoc)?.doc?.selection?.current?.()?.target;
			if (!target) return {
				success: false,
				failure: {
					code: "NO_OP",
					message: "ui.comments.createFromSelection: no addressable selection target."
				}
			};
			const api = requireDocComments();
			const receipt = api.create.call(api, {
				target,
				text
			});
			refreshAndNotify();
			return receipt;
		},
		createFromCapture(capture, { text }) {
			const target = capture?.target ?? null;
			if (!target) return {
				success: false,
				failure: {
					code: "NO_OP",
					message: "ui.comments.createFromCapture: capture has no addressable target."
				}
			};
			const api = requireDocComments();
			const receipt = api.create.call(api, {
				target,
				text
			});
			refreshAndNotify();
			return receipt;
		},
		reply(parentCommentId, { text }) {
			if (!(typeof text === "string" ? text.trim() : "")) return {
				success: false,
				failure: {
					code: "NO_OP",
					message: "ui.comments.reply: text is empty."
				}
			};
			const api = requireDocComments();
			const receipt = api.create.call(api, {
				parentCommentId,
				text
			});
			refreshAndNotify();
			return receipt;
		},
		resolve(commentId) {
			const api = requireDocComments();
			const receipt = api.patch.call(api, {
				commentId,
				status: "resolved"
			});
			refreshAndNotify();
			return receipt;
		},
		reopen(commentId) {
			const api = requireDocComments();
			const receipt = api.patch.call(api, {
				commentId,
				status: "active"
			});
			refreshAndNotify();
			return receipt;
		},
		delete(commentId) {
			const api = requireDocComments();
			const receipt = api.delete.call(api, { commentId });
			refreshAndNotify();
			return receipt;
		},
		async scrollTo(commentId) {
			return runScrollIntoView({
				target: {
					kind: "entity",
					entityType: "comment",
					entityId: commentId
				},
				block: "center",
				behavior: "smooth"
			});
		}
	};
	const requireDocTrackChanges = () => {
		const api = resolveHostEditor(superdoc)?.doc?.trackChanges;
		if (!api?.decide) throw new Error("ui.trackChanges: no active editor / trackChanges API. Open a document first.");
		return api;
	};
	const buildChangeDecideTarget = (changeId) => {
		const story = trackChangesListCache.items.find((c) => c.id === changeId)?.address?.story;
		if (story != null) return {
			id: changeId,
			story
		};
		return { id: changeId };
	};
	const lookupChangeStory = (id) => {
		return trackChangesListCache.items.find((c) => c.id === id)?.address?.story;
	};
	const trackChanges = {
		getSnapshot: () => computeState().trackChanges,
		observe(listener) {
			return select((state) => state.trackChanges, shallowEqual).subscribe((snapshot) => {
				try {
					listener(snapshot);
				} catch {}
			});
		},
		subscribe(listener) {
			return trackChanges.observe((snapshot) => listener({ snapshot }));
		},
		accept(changeId) {
			const api = requireDocTrackChanges();
			const receipt = api.decide.call(api, {
				decision: "accept",
				target: buildChangeDecideTarget(changeId)
			});
			refreshAndNotify();
			return receipt;
		},
		reject(changeId) {
			const api = requireDocTrackChanges();
			const receipt = api.decide.call(api, {
				decision: "reject",
				target: buildChangeDecideTarget(changeId)
			});
			refreshAndNotify();
			return receipt;
		},
		acceptAll() {
			const api = requireDocTrackChanges();
			const receipt = api.decide.call(api, {
				decision: "accept",
				target: { scope: "all" }
			});
			refreshAndNotify();
			return receipt;
		},
		rejectAll() {
			const api = requireDocTrackChanges();
			const receipt = api.decide.call(api, {
				decision: "reject",
				target: { scope: "all" }
			});
			refreshAndNotify();
			return receipt;
		},
		next() {
			const items = computeState().trackChanges.items;
			if (items.length === 0) return null;
			const current = activeTrackChangeId ? items.findIndex((i) => i.id === activeTrackChangeId) : -1;
			activeTrackChangeId = items[current < 0 || current >= items.length - 1 ? 0 : current + 1].id;
			scheduleNotify();
			return activeTrackChangeId;
		},
		previous() {
			const items = computeState().trackChanges.items;
			if (items.length === 0) return null;
			const current = activeTrackChangeId ? items.findIndex((i) => i.id === activeTrackChangeId) : -1;
			activeTrackChangeId = items[current <= 0 ? items.length - 1 : current - 1].id;
			scheduleNotify();
			return activeTrackChangeId;
		},
		async scrollTo(id) {
			activeTrackChangeId = id;
			scheduleNotify();
			const story = lookupChangeStory(id);
			return runScrollIntoView({
				target: story != null ? {
					kind: "entity",
					entityType: "trackedChange",
					entityId: id,
					story
				} : {
					kind: "entity",
					entityType: "trackedChange",
					entityId: id
				},
				block: "center",
				behavior: "smooth"
			});
		}
	};
	const toViewportRect$1 = (rect) => ({
		top: rect.top,
		left: rect.left,
		width: rect.width,
		height: rect.height,
		pageIndex: rect.pageIndex
	});
	const viewport = {
		getRect(input) {
			const target = input?.target;
			if (!target || typeof target !== "object") return {
				success: false,
				reason: "invalid-target"
			};
			const presentation = resolveHostEditor(superdoc)?.presentationEditor;
			if (!presentation || typeof presentation.getEntityRects !== "function") return {
				success: false,
				reason: "not-ready"
			};
			if (!("kind" in target) || target.kind !== "entity") return {
				success: false,
				reason: "invalid-target"
			};
			const entity = target;
			if (typeof entity.entityType !== "string" || typeof entity.entityId !== "string" || !entity.entityId) return {
				success: false,
				reason: "invalid-target"
			};
			if (entity.entityType !== "comment" && entity.entityType !== "trackedChange" && entity.entityType !== "contentControl") return {
				success: false,
				reason: "invalid-target"
			};
			const rangeRects = presentation.getEntityRects({
				entityType: entity.entityType,
				entityId: entity.entityId,
				story: entity.story
			});
			if (!rangeRects || rangeRects.length === 0) return {
				success: false,
				reason: "not-mounted"
			};
			const rects = rangeRects.map(toViewportRect$1);
			return {
				success: true,
				rect: rects[0],
				rects,
				pageIndex: rects[0].pageIndex
			};
		},
		observe(listener) {
			geometryListeners.add(listener);
			if (geometryListeners.size === 1) attachDomGeometryListeners();
			return () => {
				if (!geometryListeners.delete(listener)) return;
				if (geometryListeners.size === 0) {
					detachDomGeometryListeners();
					cancelGeometryFrame();
					pendingGeometryReasons.clear();
					zoomPending = false;
				}
			};
		},
		async scrollIntoView(input) {
			return runScrollIntoView(input);
		},
		entityAt(input) {
			if (!input || typeof input.x !== "number" || typeof input.y !== "number") return [];
			const dom = globalThis.document;
			if (!dom || typeof dom.elementFromPoint !== "function") return [];
			const host = resolveHostEditor(superdoc)?.presentationEditor?.visibleHost;
			if (!host) return [];
			const startEl = dom.elementFromPoint(input.x, input.y);
			if (!startEl || !host.contains(startEl)) return [];
			return collectEntityHitsFromChain(startEl);
		},
		getHost() {
			return resolveHostEditor(superdoc)?.presentationEditor?.visibleHost ?? null;
		},
		positionAt(input) {
			if (!input || typeof input.x !== "number" || typeof input.y !== "number") return null;
			return resolvePositionAt(resolveHostEditor(superdoc), resolveRoutedEditor(superdoc), input.x, input.y);
		},
		contextAt(input) {
			const x = typeof input?.x === "number" ? input.x : 0;
			const y = typeof input?.y === "number" ? input.y : 0;
			const hostEditor = resolveHostEditor(superdoc);
			const routedEditor = resolveRoutedEditor(superdoc);
			const entities = viewport.entityAt({
				x,
				y
			});
			const position = viewport.positionAt({
				x,
				y
			});
			const selectionSlice = computeState().selection;
			return buildViewportContext({
				x,
				y,
				entities,
				position,
				selection: selectionSlice,
				selectionRects: getSelectionRects(hostEditor, routedEditor)
			});
		}
	};
	const selection = {
		getSnapshot: () => computeState().selection,
		observe(listener) {
			return select((state) => state.selection, shallowEqual).subscribe((snapshot) => {
				try {
					listener(snapshot);
				} catch {}
			});
		},
		subscribe(listener) {
			return selection.observe((snapshot) => listener({ snapshot }));
		},
		capture() {
			const slice = computeState().selection;
			if (!slice.target && !slice.selectionTarget) return null;
			return deepFreeze(deepClone(slice));
		},
		getRects(capture) {
			return getSelectionRects(resolveHostEditor(superdoc), resolveRoutedEditor(superdoc), capture);
		},
		getAnchorRect(options$1, capture) {
			return getSelectionAnchorRect(resolveHostEditor(superdoc), resolveRoutedEditor(superdoc), options$1, capture);
		},
		restore(capture) {
			return restoreSelection(resolveRoutedEditor(superdoc), capture, { activeStory: readActiveStoryLocator(superdoc) });
		}
	};
	const document$1 = {
		getSnapshot: () => computeState().document,
		observe(listener) {
			return select((state) => state.document, shallowEqual).subscribe((snapshot) => {
				try {
					listener(snapshot);
				} catch {}
			});
		},
		subscribe(listener) {
			return document$1.observe((snapshot) => listener({ snapshot }));
		},
		setMode(mode) {
			const setter = superdoc.setDocumentMode;
			if (typeof setter !== "function") return;
			try {
				setter.call(superdoc, mode);
			} catch (err) {
				console.error("[superdoc/ui] ui.document.setMode failed:", err);
			}
		},
		async export(options$1) {
			const exportFn = superdoc.export;
			if (typeof exportFn !== "function") throw new Error("ui.document.export: host SuperDoc instance does not implement export().");
			const result = await exportFn.call(superdoc, options$1);
			if (dirty) {
				dirty = false;
				scheduleNotify();
			}
			return result;
		},
		async replaceFile(file) {
			const editor = superdoc.activeEditor;
			const replace = editor?.replaceFile;
			if (typeof replace !== "function") throw new Error("ui.document.replaceFile: host has no active editor with replaceFile().");
			await replace.call(editor, file);
			if (dirty) {
				dirty = false;
				scheduleNotify();
			}
			const emit = editor.emit;
			if (typeof emit === "function") try {
				const replacedFile = editor.options?.replacedFile === true ? true : void 0;
				emit.call(editor, "commentsLoaded", {
					editor,
					...replacedFile ? { replacedFile } : {},
					comments: editor.converter?.comments ?? []
				});
			} catch (err) {
				console.error("[superdoc/ui] ui.document.replaceFile commentsLoaded re-emit failed:", err);
			}
		}
	};
	const liveScopes = /* @__PURE__ */ new Set();
	const createScopeFn = () => {
		if (destroyed) {
			const inert = createScope({
				register: customCommandsRegistry.register.bind(customCommandsRegistry),
				trackScope: () => () => void 0
			});
			inert.destroy();
			return inert;
		}
		return createScope({
			register: customCommandsRegistry.register.bind(customCommandsRegistry),
			trackScope: (scope) => {
				liveScopes.add(scope);
				return () => {
					liveScopes.delete(scope);
				};
			}
		});
	};
	const contentControls = {
		getSnapshot: () => computeState().contentControls,
		observe(listener) {
			return select((state) => state.contentControls, shallowEqual).subscribe((snapshot) => {
				try {
					listener(snapshot);
				} catch {}
			});
		},
		subscribe(listener) {
			return contentControls.observe((snapshot) => listener({ snapshot }));
		},
		get({ id }) {
			const items = contentControlsListCache.items;
			for (const item of items) if (item.id === id) return item;
			return null;
		},
		getRect({ id }) {
			return viewport.getRect({ target: {
				kind: "entity",
				entityType: "contentControl",
				entityId: id
			} });
		},
		async scrollIntoView({ id, block, behavior }) {
			if (typeof id !== "string" || id.length === 0) return { success: false };
			const presentation = resolveHostEditor(superdoc)?.presentationEditor;
			if (!presentation || typeof presentation.scrollContentControlIntoView !== "function") return { success: false };
			const ok = await presentation.scrollContentControlIntoView(id, {
				block: block ?? "center",
				behavior: behavior ?? "smooth"
			});
			return { success: Boolean(ok) };
		},
		async focus({ id, block, behavior }) {
			if (typeof id !== "string" || id.length === 0) return {
				success: false,
				reason: "invalid-id"
			};
			const presentation = resolveHostEditor(superdoc)?.presentationEditor;
			if (!presentation || typeof presentation.focusContentControl !== "function") return {
				success: false,
				reason: "not-ready"
			};
			return presentation.focusContentControl(id, {
				block: block ?? "center",
				behavior: behavior ?? "smooth"
			});
		}
	};
	const findContentControlIdByMetadataId = (metadataId) => {
		for (const item of contentControlsListCache.items) if (item.properties?.tag === metadataId) return item.id;
		return null;
	};
	const selectionTargetToTextTarget = (target) => {
		const { start, end } = target;
		if (start.kind !== "text" || end.kind !== "text") return null;
		if (start.blockId === end.blockId) return {
			kind: "text",
			segments: [{
				blockId: start.blockId,
				range: {
					start: start.offset,
					end: end.offset
				}
			}],
			...target.story ? { story: target.story } : {}
		};
		return {
			kind: "text",
			segments: [{
				blockId: start.blockId,
				range: {
					start: start.offset,
					end: start.offset
				}
			}, {
				blockId: end.blockId,
				range: {
					start: end.offset,
					end: end.offset
				}
			}],
			...target.story ? { story: target.story } : {}
		};
	};
	const hasMetadataPayload = (id) => {
		const editor = superdoc.activeEditor;
		const getFn = editor?.doc?.metadata?.get;
		if (typeof getFn !== "function") return false;
		return getFn.call(editor.doc.metadata, { id }) != null;
	};
	const metadata = {
		getRect({ id }) {
			if (!id) return {
				success: false,
				reason: "invalid-target"
			};
			if (!hasMetadataPayload(id)) return {
				success: false,
				reason: "unresolved"
			};
			const ccId = findContentControlIdByMetadataId(id);
			if (ccId === null) return {
				success: false,
				reason: "unresolved"
			};
			return contentControls.getRect({ id: ccId });
		},
		async scrollIntoView({ id, block, behavior }) {
			if (!id) return { success: false };
			if (!hasMetadataPayload(id)) return { success: false };
			const editor = superdoc.activeEditor;
			const resolveFn = editor?.doc?.metadata?.resolve;
			if (typeof resolveFn !== "function") return { success: false };
			const info = resolveFn.call(editor.doc.metadata, { id });
			if (!info) return { success: false };
			const textTarget = selectionTargetToTextTarget(info.target);
			if (!textTarget) return { success: false };
			return viewport.scrollIntoView({
				target: textTarget,
				...block !== void 0 ? { block } : {},
				...behavior !== void 0 ? { behavior } : {}
			});
		}
	};
	const destroy = () => {
		if (destroyed) return;
		destroyed = true;
		const scopeSnapshot = [...liveScopes];
		liveScopes.clear();
		for (const scope of scopeSnapshot) try {
			scope.destroy();
		} catch (err) {
			console.error("[superdoc/ui] scope destroy threw during ui.destroy()", err);
		}
		stateChangeListeners.clear();
		commandHandleCache.clear();
		commandSubscribableCache.clear();
		dynamicHandleCache.clear();
		teardown.forEach((fn) => {
			try {
				fn();
			} catch {}
		});
		teardown.length = 0;
	};
	return {
		select,
		toolbar,
		commands,
		comments,
		trackChanges,
		contentControls,
		metadata,
		selection,
		viewport,
		document: document$1,
		createScope: createScopeFn,
		destroy
	};
}
Object.defineProperty(exports, "BUILT_IN_COMMAND_IDS", {
	enumerable: true,
	get: function() {
		return BUILT_IN_COMMAND_IDS;
	}
});
Object.defineProperty(exports, "createSuperDocUI", {
	enumerable: true,
	get: function() {
		return createSuperDocUI;
	}
});
Object.defineProperty(exports, "headlessToolbarConstants", {
	enumerable: true,
	get: function() {
		return headlessToolbarConstants;
	}
});
Object.defineProperty(exports, "headlessToolbarHelpers", {
	enumerable: true,
	get: function() {
		return headlessToolbarHelpers;
	}
});
Object.defineProperty(exports, "shallowEqual", {
	enumerable: true,
	get: function() {
		return shallowEqual;
	}
});
