opencrm/frontend/node_modules/@tiptap/react/dist/index.cjs

1195 lines
38 KiB
JavaScript

"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
EditorConsumer: () => EditorConsumer,
EditorContent: () => EditorContent,
EditorContext: () => EditorContext,
EditorProvider: () => EditorProvider,
MarkViewContent: () => MarkViewContent,
NodeViewContent: () => NodeViewContent,
NodeViewWrapper: () => NodeViewWrapper,
PureEditorContent: () => PureEditorContent,
ReactMarkView: () => ReactMarkView,
ReactMarkViewContext: () => ReactMarkViewContext,
ReactMarkViewRenderer: () => ReactMarkViewRenderer,
ReactNodeView: () => ReactNodeView,
ReactNodeViewContentProvider: () => ReactNodeViewContentProvider,
ReactNodeViewContext: () => ReactNodeViewContext,
ReactNodeViewRenderer: () => ReactNodeViewRenderer,
ReactRenderer: () => ReactRenderer,
Tiptap: () => Tiptap,
TiptapContent: () => TiptapContent,
TiptapContext: () => TiptapContext,
TiptapWrapper: () => TiptapWrapper,
useCurrentEditor: () => useCurrentEditor,
useEditor: () => useEditor,
useEditorState: () => useEditorState,
useReactNodeView: () => useReactNodeView,
useTiptap: () => useTiptap,
useTiptapState: () => useTiptapState
});
module.exports = __toCommonJS(index_exports);
// src/Context.tsx
var import_react4 = require("react");
// src/EditorContent.tsx
var import_react = __toESM(require("react"), 1);
var import_react_dom = __toESM(require("react-dom"), 1);
var import_shim = require("use-sync-external-store/shim/index.js");
var import_jsx_runtime = require("react/jsx-runtime");
var mergeRefs = (...refs) => {
return (node) => {
refs.forEach((ref) => {
if (typeof ref === "function") {
ref(node);
} else if (ref) {
;
ref.current = node;
}
});
};
};
var Portals = ({ contentComponent }) => {
const renderers = (0, import_shim.useSyncExternalStore)(
contentComponent.subscribe,
contentComponent.getSnapshot,
contentComponent.getServerSnapshot
);
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: Object.values(renderers) });
};
function getInstance() {
const subscribers = /* @__PURE__ */ new Set();
let renderers = {};
return {
/**
* Subscribe to the editor instance's changes.
*/
subscribe(callback) {
subscribers.add(callback);
return () => {
subscribers.delete(callback);
};
},
getSnapshot() {
return renderers;
},
getServerSnapshot() {
return renderers;
},
/**
* Adds a new NodeView Renderer to the editor.
*/
setRenderer(id, renderer) {
renderers = {
...renderers,
[id]: import_react_dom.default.createPortal(renderer.reactElement, renderer.element, id)
};
subscribers.forEach((subscriber) => subscriber());
},
/**
* Removes a NodeView Renderer from the editor.
*/
removeRenderer(id) {
const nextRenderers = { ...renderers };
delete nextRenderers[id];
renderers = nextRenderers;
subscribers.forEach((subscriber) => subscriber());
}
};
}
var PureEditorContent = class extends import_react.default.Component {
constructor(props) {
var _a;
super(props);
this.editorContentRef = import_react.default.createRef();
this.initialized = false;
this.state = {
hasContentComponentInitialized: Boolean((_a = props.editor) == null ? void 0 : _a.contentComponent)
};
}
componentDidMount() {
this.init();
}
componentDidUpdate() {
this.init();
}
init() {
var _a;
const editor = this.props.editor;
if (editor && !editor.isDestroyed && ((_a = editor.view.dom) == null ? void 0 : _a.parentNode)) {
if (editor.contentComponent) {
return;
}
const element = this.editorContentRef.current;
element.append(...editor.view.dom.parentNode.childNodes);
editor.setOptions({
element
});
editor.contentComponent = getInstance();
if (!this.state.hasContentComponentInitialized) {
this.unsubscribeToContentComponent = editor.contentComponent.subscribe(() => {
this.setState((prevState) => {
if (!prevState.hasContentComponentInitialized) {
return {
hasContentComponentInitialized: true
};
}
return prevState;
});
if (this.unsubscribeToContentComponent) {
this.unsubscribeToContentComponent();
}
});
}
editor.createNodeViews();
this.initialized = true;
}
}
componentWillUnmount() {
var _a;
const editor = this.props.editor;
if (!editor) {
return;
}
this.initialized = false;
if (!editor.isDestroyed) {
editor.view.setProps({
nodeViews: {}
});
}
if (this.unsubscribeToContentComponent) {
this.unsubscribeToContentComponent();
}
editor.contentComponent = null;
try {
if (!((_a = editor.view.dom) == null ? void 0 : _a.parentNode)) {
return;
}
const newElement = document.createElement("div");
newElement.append(...editor.view.dom.parentNode.childNodes);
editor.setOptions({
element: newElement
});
} catch {
}
}
render() {
const { editor, innerRef, ...rest } = this.props;
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: mergeRefs(innerRef, this.editorContentRef), ...rest }),
(editor == null ? void 0 : editor.contentComponent) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Portals, { contentComponent: editor.contentComponent })
] });
}
};
var EditorContentWithKey = (0, import_react.forwardRef)(
(props, ref) => {
const key = import_react.default.useMemo(() => {
return Math.floor(Math.random() * 4294967295).toString();
}, [props.editor]);
return import_react.default.createElement(PureEditorContent, {
key,
innerRef: ref,
...props
});
}
);
var EditorContent = import_react.default.memo(EditorContentWithKey);
// src/useEditor.ts
var import_core = require("@tiptap/core");
var import_react3 = require("react");
var import_shim2 = require("use-sync-external-store/shim/index.js");
// src/useEditorState.ts
var import_fast_equals = require("fast-equals");
var import_react2 = require("react");
var import_with_selector = require("use-sync-external-store/shim/with-selector.js");
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? import_react2.useLayoutEffect : import_react2.useEffect;
var EditorStateManager = class {
constructor(initialEditor) {
this.transactionNumber = 0;
this.lastTransactionNumber = 0;
this.subscribers = /* @__PURE__ */ new Set();
this.editor = initialEditor;
this.lastSnapshot = { editor: initialEditor, transactionNumber: 0 };
this.getSnapshot = this.getSnapshot.bind(this);
this.getServerSnapshot = this.getServerSnapshot.bind(this);
this.watch = this.watch.bind(this);
this.subscribe = this.subscribe.bind(this);
}
/**
* Get the current editor instance.
*/
getSnapshot() {
if (this.transactionNumber === this.lastTransactionNumber) {
return this.lastSnapshot;
}
this.lastTransactionNumber = this.transactionNumber;
this.lastSnapshot = { editor: this.editor, transactionNumber: this.transactionNumber };
return this.lastSnapshot;
}
/**
* Always disable the editor on the server-side.
*/
getServerSnapshot() {
return { editor: null, transactionNumber: 0 };
}
/**
* Subscribe to the editor instance's changes.
*/
subscribe(callback) {
this.subscribers.add(callback);
return () => {
this.subscribers.delete(callback);
};
}
/**
* Watch the editor instance for changes.
*/
watch(nextEditor) {
this.editor = nextEditor;
if (this.editor) {
const fn = () => {
this.transactionNumber += 1;
this.subscribers.forEach((callback) => callback());
};
const currentEditor = this.editor;
currentEditor.on("transaction", fn);
return () => {
currentEditor.off("transaction", fn);
};
}
return void 0;
}
};
function useEditorState(options) {
var _a;
const [editorStateManager] = (0, import_react2.useState)(() => new EditorStateManager(options.editor));
const selectedState = (0, import_with_selector.useSyncExternalStoreWithSelector)(
editorStateManager.subscribe,
editorStateManager.getSnapshot,
editorStateManager.getServerSnapshot,
options.selector,
(_a = options.equalityFn) != null ? _a : import_fast_equals.deepEqual
);
useIsomorphicLayoutEffect(() => {
return editorStateManager.watch(options.editor);
}, [options.editor, editorStateManager]);
(0, import_react2.useDebugValue)(selectedState);
return selectedState;
}
// src/useEditor.ts
var isDev = process.env.NODE_ENV !== "production";
var isSSR = typeof window === "undefined";
var isNext = isSSR || Boolean(typeof window !== "undefined" && window.next);
var EditorInstanceManager = class _EditorInstanceManager {
constructor(options) {
/**
* The current editor instance.
*/
this.editor = null;
/**
* The subscriptions to notify when the editor instance
* has been created or destroyed.
*/
this.subscriptions = /* @__PURE__ */ new Set();
/**
* Whether the editor has been mounted.
*/
this.isComponentMounted = false;
/**
* The most recent dependencies array.
*/
this.previousDeps = null;
/**
* The unique instance ID. This is used to identify the editor instance. And will be re-generated for each new instance.
*/
this.instanceId = "";
this.options = options;
this.subscriptions = /* @__PURE__ */ new Set();
this.setEditor(this.getInitialEditor());
this.scheduleDestroy();
this.getEditor = this.getEditor.bind(this);
this.getServerSnapshot = this.getServerSnapshot.bind(this);
this.subscribe = this.subscribe.bind(this);
this.refreshEditorInstance = this.refreshEditorInstance.bind(this);
this.scheduleDestroy = this.scheduleDestroy.bind(this);
this.onRender = this.onRender.bind(this);
this.createEditor = this.createEditor.bind(this);
}
setEditor(editor) {
this.editor = editor;
this.instanceId = Math.random().toString(36).slice(2, 9);
this.subscriptions.forEach((cb) => cb());
}
getInitialEditor() {
if (this.options.current.immediatelyRender === void 0) {
if (isSSR || isNext) {
if (isDev) {
throw new Error(
"Tiptap Error: SSR has been detected, please set `immediatelyRender` explicitly to `false` to avoid hydration mismatches."
);
}
return null;
}
return this.createEditor();
}
if (this.options.current.immediatelyRender && isSSR && isDev) {
throw new Error(
"Tiptap Error: SSR has been detected, and `immediatelyRender` has been set to `true` this is an unsupported configuration that may result in errors, explicitly set `immediatelyRender` to `false` to avoid hydration mismatches."
);
}
if (this.options.current.immediatelyRender) {
return this.createEditor();
}
return null;
}
/**
* Create a new editor instance. And attach event listeners.
*/
createEditor() {
const optionsToApply = {
...this.options.current,
// Always call the most recent version of the callback function by default
onBeforeCreate: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onBeforeCreate) == null ? void 0 : _b.call(_a, ...args);
},
onBlur: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onBlur) == null ? void 0 : _b.call(_a, ...args);
},
onCreate: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onCreate) == null ? void 0 : _b.call(_a, ...args);
},
onDestroy: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onDestroy) == null ? void 0 : _b.call(_a, ...args);
},
onFocus: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onFocus) == null ? void 0 : _b.call(_a, ...args);
},
onSelectionUpdate: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onSelectionUpdate) == null ? void 0 : _b.call(_a, ...args);
},
onTransaction: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onTransaction) == null ? void 0 : _b.call(_a, ...args);
},
onUpdate: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onUpdate) == null ? void 0 : _b.call(_a, ...args);
},
onContentError: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onContentError) == null ? void 0 : _b.call(_a, ...args);
},
onDrop: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onDrop) == null ? void 0 : _b.call(_a, ...args);
},
onPaste: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onPaste) == null ? void 0 : _b.call(_a, ...args);
},
onDelete: (...args) => {
var _a, _b;
return (_b = (_a = this.options.current).onDelete) == null ? void 0 : _b.call(_a, ...args);
}
};
const editor = new import_core.Editor(optionsToApply);
return editor;
}
/**
* Get the current editor instance.
*/
getEditor() {
return this.editor;
}
/**
* Always disable the editor on the server-side.
*/
getServerSnapshot() {
return null;
}
/**
* Subscribe to the editor instance's changes.
*/
subscribe(onStoreChange) {
this.subscriptions.add(onStoreChange);
return () => {
this.subscriptions.delete(onStoreChange);
};
}
static compareOptions(a, b) {
return Object.keys(a).every((key) => {
if ([
"onCreate",
"onBeforeCreate",
"onDestroy",
"onUpdate",
"onTransaction",
"onFocus",
"onBlur",
"onSelectionUpdate",
"onContentError",
"onDrop",
"onPaste"
].includes(key)) {
return true;
}
if (key === "extensions" && a.extensions && b.extensions) {
if (a.extensions.length !== b.extensions.length) {
return false;
}
return a.extensions.every((extension, index) => {
var _a;
if (extension !== ((_a = b.extensions) == null ? void 0 : _a[index])) {
return false;
}
return true;
});
}
if (a[key] !== b[key]) {
return false;
}
return true;
});
}
/**
* On each render, we will create, update, or destroy the editor instance.
* @param deps The dependencies to watch for changes
* @returns A cleanup function
*/
onRender(deps) {
return () => {
this.isComponentMounted = true;
clearTimeout(this.scheduledDestructionTimeout);
if (this.editor && !this.editor.isDestroyed && deps.length === 0) {
if (!_EditorInstanceManager.compareOptions(this.options.current, this.editor.options)) {
this.editor.setOptions({
...this.options.current,
editable: this.editor.isEditable
});
}
} else {
this.refreshEditorInstance(deps);
}
return () => {
this.isComponentMounted = false;
this.scheduleDestroy();
};
};
}
/**
* Recreate the editor instance if the dependencies have changed.
*/
refreshEditorInstance(deps) {
if (this.editor && !this.editor.isDestroyed) {
if (this.previousDeps === null) {
this.previousDeps = deps;
return;
}
const depsAreEqual = this.previousDeps.length === deps.length && this.previousDeps.every((dep, index) => dep === deps[index]);
if (depsAreEqual) {
return;
}
}
if (this.editor && !this.editor.isDestroyed) {
this.editor.destroy();
}
this.setEditor(this.createEditor());
this.previousDeps = deps;
}
/**
* Schedule the destruction of the editor instance.
* This will only destroy the editor if it was not mounted on the next tick.
* This is to avoid destroying the editor instance when it's actually still mounted.
*/
scheduleDestroy() {
const currentInstanceId = this.instanceId;
const currentEditor = this.editor;
this.scheduledDestructionTimeout = setTimeout(() => {
if (this.isComponentMounted && this.instanceId === currentInstanceId) {
if (currentEditor) {
currentEditor.setOptions(this.options.current);
}
return;
}
if (currentEditor && !currentEditor.isDestroyed) {
currentEditor.destroy();
if (this.instanceId === currentInstanceId) {
this.setEditor(null);
}
}
}, 1);
}
};
function useEditor(options = {}, deps = []) {
const mostRecentOptions = (0, import_react3.useRef)(options);
mostRecentOptions.current = options;
const [instanceManager] = (0, import_react3.useState)(() => new EditorInstanceManager(mostRecentOptions));
const editor = (0, import_shim2.useSyncExternalStore)(
instanceManager.subscribe,
instanceManager.getEditor,
instanceManager.getServerSnapshot
);
(0, import_react3.useDebugValue)(editor);
(0, import_react3.useEffect)(instanceManager.onRender(deps));
useEditorState({
editor,
selector: ({ transactionNumber }) => {
if (options.shouldRerenderOnTransaction === false || options.shouldRerenderOnTransaction === void 0) {
return null;
}
if (options.immediatelyRender && transactionNumber === 0) {
return 0;
}
return transactionNumber + 1;
}
});
return editor;
}
// src/Context.tsx
var import_jsx_runtime2 = require("react/jsx-runtime");
var EditorContext = (0, import_react4.createContext)({
editor: null
});
var EditorConsumer = EditorContext.Consumer;
var useCurrentEditor = () => (0, import_react4.useContext)(EditorContext);
function EditorProvider({
children,
slotAfter,
slotBefore,
editorContainerProps = {},
...editorOptions
}) {
const editor = useEditor(editorOptions);
const contextValue = (0, import_react4.useMemo)(() => ({ editor }), [editor]);
if (!editor) {
return null;
}
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(EditorContext.Provider, { value: contextValue, children: [
slotBefore,
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EditorConsumer, { children: ({ editor: currentEditor }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EditorContent, { editor: currentEditor, ...editorContainerProps }) }),
children,
slotAfter
] });
}
// src/useReactNodeView.ts
var import_react5 = require("react");
var ReactNodeViewContext = (0, import_react5.createContext)({
onDragStart: () => {
},
nodeViewContentChildren: void 0,
nodeViewContentRef: () => {
}
});
var ReactNodeViewContentProvider = ({ children, content }) => {
return (0, import_react5.createElement)(ReactNodeViewContext.Provider, { value: { nodeViewContentChildren: content } }, children);
};
var useReactNodeView = () => (0, import_react5.useContext)(ReactNodeViewContext);
// src/NodeViewContent.tsx
var import_jsx_runtime3 = (
// @ts-ignore
require("react/jsx-runtime")
);
function NodeViewContent({
as: Tag = "div",
...props
}) {
const { nodeViewContentRef, nodeViewContentChildren } = useReactNodeView();
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
Tag,
{
...props,
ref: nodeViewContentRef,
"data-node-view-content": "",
style: {
whiteSpace: "pre-wrap",
...props.style
},
children: nodeViewContentChildren
}
);
}
// src/NodeViewWrapper.tsx
var import_react6 = __toESM(require("react"), 1);
var import_jsx_runtime4 = (
// @ts-ignore
require("react/jsx-runtime")
);
var NodeViewWrapper = import_react6.default.forwardRef((props, ref) => {
const { onDragStart } = useReactNodeView();
const Tag = props.as || "div";
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
Tag,
{
...props,
ref,
"data-node-view-wrapper": "",
onDragStart,
style: {
whiteSpace: "normal",
...props.style
}
}
);
});
// src/ReactMarkViewRenderer.tsx
var import_core2 = require("@tiptap/core");
var import_react8 = __toESM(require("react"), 1);
// src/ReactRenderer.tsx
var import_react7 = require("react");
var import_react_dom2 = require("react-dom");
var import_jsx_runtime5 = require("react/jsx-runtime");
function isClassComponent(Component) {
return !!(typeof Component === "function" && Component.prototype && Component.prototype.isReactComponent);
}
function isForwardRefComponent(Component) {
return !!(typeof Component === "object" && Component.$$typeof && (Component.$$typeof.toString() === "Symbol(react.forward_ref)" || Component.$$typeof.description === "react.forward_ref"));
}
function isMemoComponent(Component) {
return !!(typeof Component === "object" && Component.$$typeof && (Component.$$typeof.toString() === "Symbol(react.memo)" || Component.$$typeof.description === "react.memo"));
}
function canReceiveRef(Component) {
if (isClassComponent(Component)) {
return true;
}
if (isForwardRefComponent(Component)) {
return true;
}
if (isMemoComponent(Component)) {
const wrappedComponent = Component.type;
if (wrappedComponent) {
return isClassComponent(wrappedComponent) || isForwardRefComponent(wrappedComponent);
}
}
return false;
}
function isReact19Plus() {
try {
if (import_react7.version) {
const majorVersion = parseInt(import_react7.version.split(".")[0], 10);
return majorVersion >= 19;
}
} catch {
}
return false;
}
var ReactRenderer = class {
/**
* Immediately creates element and renders the provided React component.
*/
constructor(component, { editor, props = {}, as = "div", className = "" }) {
this.ref = null;
/**
* Flag to track if the renderer has been destroyed, preventing queued or asynchronous renders from executing after teardown.
*/
this.destroyed = false;
this.id = Math.floor(Math.random() * 4294967295).toString();
this.component = component;
this.editor = editor;
this.props = props;
this.element = document.createElement(as);
this.element.classList.add("react-renderer");
if (className) {
this.element.classList.add(...className.split(" "));
}
if (this.editor.isInitialized) {
(0, import_react_dom2.flushSync)(() => {
this.render();
});
} else {
queueMicrotask(() => {
if (this.destroyed) {
return;
}
this.render();
});
}
}
/**
* Render the React component.
*/
render() {
var _a;
if (this.destroyed) {
return;
}
const Component = this.component;
const props = this.props;
const editor = this.editor;
const isReact19 = isReact19Plus();
const componentCanReceiveRef = canReceiveRef(Component);
const elementProps = { ...props };
if (elementProps.ref && !(isReact19 || componentCanReceiveRef)) {
delete elementProps.ref;
}
if (!elementProps.ref && (isReact19 || componentCanReceiveRef)) {
elementProps.ref = (ref) => {
this.ref = ref;
};
}
this.reactElement = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Component, { ...elementProps });
(_a = editor == null ? void 0 : editor.contentComponent) == null ? void 0 : _a.setRenderer(this.id, this);
}
/**
* Re-renders the React component with new props.
*/
updateProps(props = {}) {
if (this.destroyed) {
return;
}
this.props = {
...this.props,
...props
};
this.render();
}
/**
* Destroy the React component.
*/
destroy() {
var _a;
this.destroyed = true;
const editor = this.editor;
(_a = editor == null ? void 0 : editor.contentComponent) == null ? void 0 : _a.removeRenderer(this.id);
try {
if (this.element && this.element.parentNode) {
this.element.parentNode.removeChild(this.element);
}
} catch {
}
}
/**
* Update the attributes of the element that holds the React component.
*/
updateAttributes(attributes) {
Object.keys(attributes).forEach((key) => {
this.element.setAttribute(key, attributes[key]);
});
}
};
// src/ReactMarkViewRenderer.tsx
var import_jsx_runtime6 = (
// @ts-ignore
require("react/jsx-runtime")
);
var ReactMarkViewContext = import_react8.default.createContext({
markViewContentRef: () => {
}
});
var MarkViewContent = (props) => {
const { as: Tag = "span", ...rest } = props;
const { markViewContentRef } = import_react8.default.useContext(ReactMarkViewContext);
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Tag, { ...rest, ref: markViewContentRef, "data-mark-view-content": "" });
};
var ReactMarkView = class extends import_core2.MarkView {
constructor(component, props, options) {
super(component, props, options);
const { as = "span", attrs, className = "" } = options || {};
const componentProps = { ...props, updateAttributes: this.updateAttributes.bind(this) };
this.contentDOMElement = document.createElement("span");
const markViewContentRef = (el) => {
if (el && !el.contains(this.contentDOMElement)) {
el.appendChild(this.contentDOMElement);
}
};
const context = {
markViewContentRef
};
const ReactMarkViewProvider = import_react8.default.memo((componentProps2) => {
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ReactMarkViewContext.Provider, { value: context, children: import_react8.default.createElement(component, componentProps2) });
});
ReactMarkViewProvider.displayName = "ReactMarkView";
this.renderer = new ReactRenderer(ReactMarkViewProvider, {
editor: props.editor,
props: componentProps,
as,
className: `mark-${props.mark.type.name} ${className}`.trim()
});
if (attrs) {
this.renderer.updateAttributes(attrs);
}
}
get dom() {
return this.renderer.element;
}
get contentDOM() {
return this.contentDOMElement;
}
};
function ReactMarkViewRenderer(component, options = {}) {
return (props) => new ReactMarkView(component, props, options);
}
// src/ReactNodeViewRenderer.tsx
var import_core3 = require("@tiptap/core");
var import_react9 = require("react");
var import_jsx_runtime7 = require("react/jsx-runtime");
var ReactNodeView = class extends import_core3.NodeView {
constructor(component, props, options) {
super(component, props, options);
/**
* The requestAnimationFrame ID used for selection updates.
*/
this.selectionRafId = null;
this.cachedExtensionWithSyncedStorage = null;
if (!this.node.isLeaf) {
if (this.options.contentDOMElementTag) {
this.contentDOMElement = document.createElement(this.options.contentDOMElementTag);
} else {
this.contentDOMElement = document.createElement(this.node.isInline ? "span" : "div");
}
this.contentDOMElement.dataset.nodeViewContentReact = "";
this.contentDOMElement.dataset.nodeViewWrapper = "";
this.contentDOMElement.style.whiteSpace = "inherit";
const contentTarget = this.dom.querySelector("[data-node-view-content]");
if (!contentTarget) {
return;
}
contentTarget.appendChild(this.contentDOMElement);
}
}
/**
* Returns a proxy of the extension that redirects storage access to the editor's mutable storage.
* This preserves the original prototype chain (instanceof checks, methods like configure/extend work).
* Cached to avoid proxy creation on every update.
*/
get extensionWithSyncedStorage() {
if (!this.cachedExtensionWithSyncedStorage) {
const editor = this.editor;
const extension = this.extension;
this.cachedExtensionWithSyncedStorage = new Proxy(extension, {
get(target, prop, receiver) {
var _a;
if (prop === "storage") {
return (_a = editor.storage[extension.name]) != null ? _a : {};
}
return Reflect.get(target, prop, receiver);
}
});
}
return this.cachedExtensionWithSyncedStorage;
}
/**
* Setup the React component.
* Called on initialization.
*/
mount() {
const props = {
editor: this.editor,
node: this.node,
decorations: this.decorations,
innerDecorations: this.innerDecorations,
view: this.view,
selected: false,
extension: this.extensionWithSyncedStorage,
HTMLAttributes: this.HTMLAttributes,
getPos: () => this.getPos(),
updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
deleteNode: () => this.deleteNode(),
ref: (0, import_react9.createRef)()
};
if (!this.component.displayName) {
const capitalizeFirstChar = (string) => {
return string.charAt(0).toUpperCase() + string.substring(1);
};
this.component.displayName = capitalizeFirstChar(this.extension.name);
}
const onDragStart = this.onDragStart.bind(this);
const nodeViewContentRef = (element) => {
if (element && this.contentDOMElement && element.firstChild !== this.contentDOMElement) {
if (element.hasAttribute("data-node-view-wrapper")) {
element.removeAttribute("data-node-view-wrapper");
}
element.appendChild(this.contentDOMElement);
}
};
const context = { onDragStart, nodeViewContentRef };
const Component = this.component;
const ReactNodeViewProvider = (0, import_react9.memo)((componentProps) => {
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ReactNodeViewContext.Provider, { value: context, children: (0, import_react9.createElement)(Component, componentProps) });
});
ReactNodeViewProvider.displayName = "ReactNodeView";
let as = this.node.isInline ? "span" : "div";
if (this.options.as) {
as = this.options.as;
}
const { className = "" } = this.options;
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
this.renderer = new ReactRenderer(ReactNodeViewProvider, {
editor: this.editor,
props,
as,
className: `node-${this.node.type.name} ${className}`.trim()
});
this.editor.on("selectionUpdate", this.handleSelectionUpdate);
this.updateElementAttributes();
}
/**
* Return the DOM element.
* This is the element that will be used to display the node view.
*/
get dom() {
var _a;
if (this.renderer.element.firstElementChild && !((_a = this.renderer.element.firstElementChild) == null ? void 0 : _a.hasAttribute("data-node-view-wrapper"))) {
throw Error("Please use the NodeViewWrapper component for your node view.");
}
return this.renderer.element;
}
/**
* Return the content DOM element.
* This is the element that will be used to display the rich-text content of the node.
*/
get contentDOM() {
if (this.node.isLeaf) {
return null;
}
return this.contentDOMElement;
}
/**
* On editor selection update, check if the node is selected.
* If it is, call `selectNode`, otherwise call `deselectNode`.
*/
handleSelectionUpdate() {
if (this.selectionRafId) {
cancelAnimationFrame(this.selectionRafId);
this.selectionRafId = null;
}
this.selectionRafId = requestAnimationFrame(() => {
this.selectionRafId = null;
const { from, to } = this.editor.state.selection;
const pos = this.getPos();
if (typeof pos !== "number") {
return;
}
if (from <= pos && to >= pos + this.node.nodeSize) {
if (this.renderer.props.selected) {
return;
}
this.selectNode();
} else {
if (!this.renderer.props.selected) {
return;
}
this.deselectNode();
}
});
}
/**
* On update, update the React component.
* To prevent unnecessary updates, the `update` option can be used.
*/
update(node, decorations, innerDecorations) {
const rerenderComponent = (props) => {
this.renderer.updateProps(props);
if (typeof this.options.attrs === "function") {
this.updateElementAttributes();
}
};
if (node.type !== this.node.type) {
return false;
}
if (typeof this.options.update === "function") {
const oldNode = this.node;
const oldDecorations = this.decorations;
const oldInnerDecorations = this.innerDecorations;
this.node = node;
this.decorations = decorations;
this.innerDecorations = innerDecorations;
return this.options.update({
oldNode,
oldDecorations,
newNode: node,
newDecorations: decorations,
oldInnerDecorations,
innerDecorations,
updateProps: () => rerenderComponent({ node, decorations, innerDecorations, extension: this.extensionWithSyncedStorage })
});
}
if (node === this.node && this.decorations === decorations && this.innerDecorations === innerDecorations) {
return true;
}
this.node = node;
this.decorations = decorations;
this.innerDecorations = innerDecorations;
rerenderComponent({ node, decorations, innerDecorations, extension: this.extensionWithSyncedStorage });
return true;
}
/**
* Select the node.
* Add the `selected` prop and the `ProseMirror-selectednode` class.
*/
selectNode() {
this.renderer.updateProps({
selected: true
});
this.renderer.element.classList.add("ProseMirror-selectednode");
}
/**
* Deselect the node.
* Remove the `selected` prop and the `ProseMirror-selectednode` class.
*/
deselectNode() {
this.renderer.updateProps({
selected: false
});
this.renderer.element.classList.remove("ProseMirror-selectednode");
}
/**
* Destroy the React component instance.
*/
destroy() {
this.renderer.destroy();
this.editor.off("selectionUpdate", this.handleSelectionUpdate);
this.contentDOMElement = null;
if (this.selectionRafId) {
cancelAnimationFrame(this.selectionRafId);
this.selectionRafId = null;
}
}
/**
* Update the attributes of the top-level element that holds the React component.
* Applying the attributes defined in the `attrs` option.
*/
updateElementAttributes() {
if (this.options.attrs) {
let attrsObj = {};
if (typeof this.options.attrs === "function") {
const extensionAttributes = this.editor.extensionManager.attributes;
const HTMLAttributes = (0, import_core3.getRenderedAttributes)(this.node, extensionAttributes);
attrsObj = this.options.attrs({ node: this.node, HTMLAttributes });
} else {
attrsObj = this.options.attrs;
}
this.renderer.updateAttributes(attrsObj);
}
}
};
function ReactNodeViewRenderer(component, options) {
return (props) => {
if (!props.editor.contentComponent) {
return {};
}
return new ReactNodeView(component, props, options);
};
}
// src/Tiptap.tsx
var import_react10 = require("react");
var import_jsx_runtime8 = require("react/jsx-runtime");
var TiptapContext = (0, import_react10.createContext)({
get editor() {
throw new Error("useTiptap must be used within a <Tiptap> provider");
}
});
TiptapContext.displayName = "TiptapContext";
var useTiptap = () => (0, import_react10.useContext)(TiptapContext);
function useTiptapState(selector, equalityFn) {
const { editor } = useTiptap();
return useEditorState({
editor,
selector,
equalityFn
});
}
function TiptapWrapper({ editor, instance, children }) {
const resolvedEditor = editor != null ? editor : instance;
if (!resolvedEditor) {
throw new Error("Tiptap: An editor instance is required. Pass a non-null `editor` prop.");
}
const tiptapContextValue = (0, import_react10.useMemo)(() => ({ editor: resolvedEditor }), [resolvedEditor]);
const legacyContextValue = (0, import_react10.useMemo)(() => ({ editor: resolvedEditor }), [resolvedEditor]);
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(EditorContext.Provider, { value: legacyContextValue, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TiptapContext.Provider, { value: tiptapContextValue, children }) });
}
TiptapWrapper.displayName = "Tiptap";
function TiptapContent({ ...rest }) {
const { editor } = useTiptap();
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(EditorContent, { editor, ...rest });
}
TiptapContent.displayName = "Tiptap.Content";
var Tiptap = Object.assign(TiptapWrapper, {
/**
* The Tiptap Content component that renders the EditorContent with the editor instance from the context.
* @see TiptapContent
*/
Content: TiptapContent
});
// src/index.ts
__reExport(index_exports, require("@tiptap/core"), module.exports);
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
EditorConsumer,
EditorContent,
EditorContext,
EditorProvider,
MarkViewContent,
NodeViewContent,
NodeViewWrapper,
PureEditorContent,
ReactMarkView,
ReactMarkViewContext,
ReactMarkViewRenderer,
ReactNodeView,
ReactNodeViewContentProvider,
ReactNodeViewContext,
ReactNodeViewRenderer,
ReactRenderer,
Tiptap,
TiptapContent,
TiptapContext,
TiptapWrapper,
useCurrentEditor,
useEditor,
useEditorState,
useReactNodeView,
useTiptap,
useTiptapState,
...require("@tiptap/core")
});
//# sourceMappingURL=index.cjs.map