REDROOM
PHP 8.2.30
Path:
Logout
Edit File
Size: 12.35 KB
Close
/proc/thread-self/root/home/byroehnu/.trash/node_modules11/@tiptap/react/src/useEditor.ts
Text
Base64
import { type EditorOptions, Editor } from '@tiptap/core' import { DependencyList, MutableRefObject, useDebugValue, useEffect, useRef, useState, } from 'react' import { useSyncExternalStore } from 'use-sync-external-store/shim' import { useEditorState } from './useEditorState.js' const isDev = process.env.NODE_ENV !== 'production' const isSSR = typeof window === 'undefined' const isNext = isSSR || Boolean(typeof window !== 'undefined' && (window as any).next) /** * The options for the `useEditor` hook. */ export type UseEditorOptions = Partial<EditorOptions> & { /** * Whether to render the editor on the first render. * If client-side rendering, set this to `true`. * If server-side rendering, set this to `false`. * @default true */ immediatelyRender?: boolean; /** * Whether to re-render the editor on each transaction. * This is legacy behavior that will be removed in future versions. * @default true */ shouldRerenderOnTransaction?: boolean; }; /** * This class handles the creation, destruction, and re-creation of the editor instance. */ class EditorInstanceManager { /** * The current editor instance. */ private editor: Editor | null = null /** * The most recent options to apply to the editor. */ private options: MutableRefObject<UseEditorOptions> /** * The subscriptions to notify when the editor instance * has been created or destroyed. */ private subscriptions = new Set<() => void>() /** * A timeout to destroy the editor if it was not mounted within a time frame. */ private scheduledDestructionTimeout: ReturnType<typeof setTimeout> | undefined /** * Whether the editor has been mounted. */ private isComponentMounted = false /** * The most recent dependencies array. */ private previousDeps: DependencyList | null = null /** * The unique instance ID. This is used to identify the editor instance. And will be re-generated for each new instance. */ public instanceId = '' constructor(options: MutableRefObject<UseEditorOptions>) { this.options = options this.subscriptions = new Set<() => void>() 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) } private setEditor(editor: Editor | null) { this.editor = editor this.instanceId = Math.random().toString(36).slice(2, 9) // Notify all subscribers that the editor instance has been created this.subscriptions.forEach(cb => cb()) } private getInitialEditor() { if (this.options.current.immediatelyRender === undefined) { if (isSSR || isNext) { // TODO in the next major release, we should throw an error here if (isDev) { /** * Throw an error in development, to make sure the developer is aware that tiptap cannot be SSR'd * and that they need to set `immediatelyRender` to `false` to avoid hydration mismatches. */ console.warn( 'Tiptap Error: SSR has been detected, please set `immediatelyRender` explicitly to `false` to avoid hydration mismatches.', ) } // Best faith effort in production, run the code in the legacy mode to avoid hydration mismatches and errors in production return null } // Default to immediately rendering when client-side rendering return this.createEditor() } if (this.options.current.immediatelyRender && isSSR && isDev) { // Warn in development, to make sure the developer is aware that tiptap cannot be SSR'd, set `immediatelyRender` to `false` to avoid hydration mismatches. 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. */ private createEditor(): Editor { const optionsToApply: Partial<EditorOptions> = { ...this.options.current, // Always call the most recent version of the callback function by default onBeforeCreate: (...args) => this.options.current.onBeforeCreate?.(...args), onBlur: (...args) => this.options.current.onBlur?.(...args), onCreate: (...args) => this.options.current.onCreate?.(...args), onDestroy: (...args) => this.options.current.onDestroy?.(...args), onFocus: (...args) => this.options.current.onFocus?.(...args), onSelectionUpdate: (...args) => this.options.current.onSelectionUpdate?.(...args), onTransaction: (...args) => this.options.current.onTransaction?.(...args), onUpdate: (...args) => this.options.current.onUpdate?.(...args), onContentError: (...args) => this.options.current.onContentError?.(...args), onDrop: (...args) => this.options.current.onDrop?.(...args), onPaste: (...args) => this.options.current.onPaste?.(...args), } const editor = new Editor(optionsToApply) // no need to keep track of the event listeners, they will be removed when the editor is destroyed return editor } /** * Get the current editor instance. */ getEditor(): Editor | null { return this.editor } /** * Always disable the editor on the server-side. */ getServerSnapshot(): null { return null } /** * Subscribe to the editor instance's changes. */ subscribe(onStoreChange: () => void) { this.subscriptions.add(onStoreChange) return () => { this.subscriptions.delete(onStoreChange) } } static compareOptions(a: UseEditorOptions, b: UseEditorOptions) { return (Object.keys(a) as (keyof UseEditorOptions)[]).every(key => { if (['onCreate', 'onBeforeCreate', 'onDestroy', 'onUpdate', 'onTransaction', 'onFocus', 'onBlur', 'onSelectionUpdate', 'onContentError', 'onDrop', 'onPaste'].includes(key)) { // we don't want to compare callbacks, they are always different and only registered once return true } // We often encourage putting extensions inlined in the options object, so we will do a slightly deeper comparison here if (key === 'extensions' && a.extensions && b.extensions) { if (a.extensions.length !== b.extensions.length) { return false } return a.extensions.every((extension, index) => { if (extension !== b.extensions?.[index]) { return false } return true }) } if (a[key] !== b[key]) { // if any of the options have changed, we should update the editor options 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: DependencyList) { // The returned callback will run on each render return () => { this.isComponentMounted = true // Cleanup any scheduled destructions, since we are currently rendering clearTimeout(this.scheduledDestructionTimeout) if (this.editor && !this.editor.isDestroyed && deps.length === 0) { // if the editor does exist & deps are empty, we don't need to re-initialize the editor generally if (!EditorInstanceManager.compareOptions(this.options.current, this.editor.options)) { // But, the options are different, so we need to update the editor options // Still, this is faster than re-creating the editor this.editor.setOptions({ ...this.options.current, editable: this.editor.isEditable, }) } } else { // When the editor: // - does not yet exist // - is destroyed // - the deps array changes // We need to destroy the editor instance and re-initialize it this.refreshEditorInstance(deps) } return () => { this.isComponentMounted = false this.scheduleDestroy() } } } /** * Recreate the editor instance if the dependencies have changed. */ private refreshEditorInstance(deps: DependencyList) { if (this.editor && !this.editor.isDestroyed) { // Editor instance already exists if (this.previousDeps === null) { // If lastDeps has not yet been initialized, reuse the current editor instance this.previousDeps = deps return } const depsAreEqual = this.previousDeps.length === deps.length && this.previousDeps.every((dep, index) => dep === deps[index]) if (depsAreEqual) { // deps exist and are equal, no need to recreate return } } if (this.editor && !this.editor.isDestroyed) { // Destroy the editor instance if it exists this.editor.destroy() } this.setEditor(this.createEditor()) // Update the lastDeps to the current deps 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. */ private scheduleDestroy() { const currentInstanceId = this.instanceId const currentEditor = this.editor // Wait two ticks to see if the component is still mounted this.scheduledDestructionTimeout = setTimeout(() => { if (this.isComponentMounted && this.instanceId === currentInstanceId) { // If still mounted on the following tick, with the same instanceId, do not destroy the editor if (currentEditor) { // just re-apply options as they might have changed currentEditor.setOptions(this.options.current) } return } if (currentEditor && !currentEditor.isDestroyed) { currentEditor.destroy() if (this.instanceId === currentInstanceId) { this.setEditor(null) } } // This allows the effect to run again between ticks // which may save us from having to re-create the editor }, 1) } } /** * This hook allows you to create an editor instance. * @param options The editor options * @param deps The dependencies to watch for changes * @returns The editor instance * @example const editor = useEditor({ extensions: [...] }) */ export function useEditor( options: UseEditorOptions & { immediatelyRender: true }, deps?: DependencyList ): Editor; /** * This hook allows you to create an editor instance. * @param options The editor options * @param deps The dependencies to watch for changes * @returns The editor instance * @example const editor = useEditor({ extensions: [...] }) */ export function useEditor(options?: UseEditorOptions, deps?: DependencyList): Editor | null; export function useEditor( options: UseEditorOptions = {}, deps: DependencyList = [], ): Editor | null { const mostRecentOptions = useRef(options) mostRecentOptions.current = options const [instanceManager] = useState(() => new EditorInstanceManager(mostRecentOptions)) const editor = useSyncExternalStore( instanceManager.subscribe, instanceManager.getEditor, instanceManager.getServerSnapshot, ) useDebugValue(editor) // This effect will handle creating/updating the editor instance // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(instanceManager.onRender(deps)) // The default behavior is to re-render on each transaction // This is legacy behavior that will be removed in future versions useEditorState({ editor, selector: ({ transactionNumber }) => { if (options.shouldRerenderOnTransaction === false) { // This will prevent the editor from re-rendering on each transaction return null } // This will avoid re-rendering on the first transaction when `immediatelyRender` is set to `true` if (options.immediatelyRender && transactionNumber === 0) { return 0 } return transactionNumber + 1 }, }) return editor }
Save
Close
Exit & Reset
Text mode: syntax highlighting auto-detects file type.
Directory Contents
Dirs: 0 × Files: 14
Delete Selected
Select All
Select None
Sort:
Name
Size
Modified
Enable drag-to-move
Name
Size
Perms
Modified
Actions
BubbleMenu.tsx
1.56 KB
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
Context.tsx
1.42 KB
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
Editor.ts
510 B
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
EditorContent.tsx
5.75 KB
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
FloatingMenu.tsx
1.56 KB
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
index.ts
443 B
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
NodeViewContent.tsx
546 B
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
NodeViewWrapper.tsx
579 B
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
ReactNodeViewRenderer.tsx
10.57 KB
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
ReactRenderer.tsx
6.18 KB
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
types.ts
210 B
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
useEditor.ts
12.35 KB
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
useEditorState.ts
5.54 KB
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
useReactNodeView.ts
392 B
lrw-r--r--
2026-02-28 11:47:14
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
Zip Selected
If ZipArchive is unavailable, a
.tar
will be created (no compression).