{"version":3,"file":"defaultCommentEditorSchema-CxYfuFDM.cjs","names":[],"sources":["../src/editor/BlockNoteContext.ts","../src/hooks/useBlockNoteEditor.ts","../src/hooks/useExtension.ts","../src/components/Popovers/GenericPopover.tsx","../src/editor/ComponentsContext.tsx","../src/i18n/dictionary.ts","../src/hooks/useEditorState.ts","../src/components/Popovers/PositionPopover.tsx","../src/hooks/useCreateBlockNote.tsx","../src/components/Comments/CommentEditor.tsx","../src/components/Comments/defaultCommentEditorSchema.ts"],"sourcesContent":["import {\n  BlockNoteEditor,\n  BlockNoteSchema,\n  BlockSchema,\n  DefaultBlockSchema,\n  DefaultInlineContentSchema,\n  DefaultStyleSchema,\n  InlineContentSchema,\n  StyleSchema,\n} from \"@blocknote/core\";\nimport { createContext, useContext, useState } from \"react\";\n\nexport type BlockNoteContextValue<\n  BSchema extends BlockSchema = DefaultBlockSchema,\n  ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n  SSchema extends StyleSchema = DefaultStyleSchema,\n> = {\n  setContentEditableProps?: ReturnType<typeof useState<Record<string, any>>>[1]; // copy type of setXXX from useState\n  editor?: BlockNoteEditor<BSchema, ISchema, SSchema>;\n  colorSchemePreference?: \"light\" | \"dark\";\n};\n\nexport const BlockNoteContext = createContext<\n  BlockNoteContextValue | undefined\n>(undefined);\n\n/**\n * Get the BlockNoteContext instance from the nearest BlockNoteContext provider\n * @param _schema: optional, pass in the schema to return type-safe Context if you're using a custom schema\n */\nexport function useBlockNoteContext<\n  BSchema extends BlockSchema = DefaultBlockSchema,\n  ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n  SSchema extends StyleSchema = DefaultStyleSchema,\n>(\n  _schema?: BlockNoteSchema<BSchema, ISchema, SSchema>,\n): BlockNoteContextValue<BSchema, ISchema, SSchema> | undefined {\n  const context = useContext(BlockNoteContext) as any;\n\n  return context;\n}\n","import {\n  BlockNoteEditor,\n  BlockNoteSchema,\n  BlockSchema,\n  DefaultBlockSchema,\n  DefaultInlineContentSchema,\n  DefaultStyleSchema,\n  InlineContentSchema,\n  StyleSchema,\n} from \"@blocknote/core\";\n\nimport { useBlockNoteContext } from \"../editor/BlockNoteContext.js\";\n\n/**\n * Get the BlockNoteEditor instance from the nearest BlockNoteContext provider\n * @param _schema: optional, pass in the schema to return type-safe BlockNoteEditor if you're using a custom schema\n */\nexport function useBlockNoteEditor<\n  BSchema extends BlockSchema = DefaultBlockSchema,\n  ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n  SSchema extends StyleSchema = DefaultStyleSchema,\n>(\n  _schema?: BlockNoteSchema<BSchema, ISchema, SSchema>,\n): BlockNoteEditor<BSchema, ISchema, SSchema> {\n  const context = useBlockNoteContext(_schema);\n\n  if (!context?.editor) {\n    throw new Error(\n      \"useBlockNoteEditor was called outside of a BlockNoteContext provider or BlockNoteView component\",\n    );\n  }\n\n  return context.editor;\n}\n","import {\n  BlockNoteEditor,\n  createStore,\n  Extension,\n  ExtensionFactory,\n} from \"@blocknote/core\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { useBlockNoteEditor } from \"./useBlockNoteEditor.js\";\n\ntype Store<T> = ReturnType<typeof createStore<T>>;\n\n/**\n * Use an extension instance\n */\nexport function useExtension<\n  const T extends ExtensionFactory | Extension | string,\n>(\n  plugin: T,\n  ctx?: { editor?: BlockNoteEditor<any, any, any> },\n): T extends ExtensionFactory\n  ? NonNullable<ReturnType<ReturnType<T>>>\n  : T extends string\n    ? Extension\n    : T extends Extension\n      ? T\n      : never {\n  // eslint-disable-next-line react-hooks/rules-of-hooks\n  const editor = ctx?.editor ?? useBlockNoteEditor();\n\n  const instance = editor.getExtension(plugin as any);\n\n  if (!instance) {\n    throw new Error(\"Extension not found\", { cause: { plugin } });\n  }\n\n  return instance;\n}\n\ntype ExtractStore<T> = T extends Store<infer U> ? U : never;\n\n/**\n * Use the state of an extension\n */\nexport function useExtensionState<\n  T extends ExtensionFactory | Extension,\n  TExtension = T extends ExtensionFactory ? ReturnType<ReturnType<T>> : T,\n  TStore = TExtension extends { store: Store<any> }\n    ? TExtension[\"store\"]\n    : never,\n  TSelected = NoInfer<ExtractStore<TStore>>,\n>(\n  plugin: T,\n  ctx?: {\n    editor?: BlockNoteEditor<any, any, any>;\n    selector?: (state: NoInfer<ExtractStore<TStore>>) => TSelected;\n  },\n): TSelected {\n  const { store } = useExtension(plugin, ctx);\n  if (!store) {\n    throw new Error(\"Store not found on plugin\", { cause: { plugin } });\n  }\n  return useStore<ExtractStore<TStore>, TSelected>(store, ctx?.selector as any);\n}\n","import {\n  autoUpdate,\n  FloatingFocusManager,\n  FloatingPortal,\n  useDismiss,\n  useFloating,\n  UseFloatingOptions,\n  useHover,\n  useInteractions,\n  useMergeRefs,\n  useTransitionStatus,\n  useTransitionStyles,\n} from \"@floating-ui/react\";\nimport { HTMLAttributes, ReactNode, useEffect, useRef } from \"react\";\n\nimport { useBlockNoteEditor } from \"../../hooks/useBlockNoteEditor.js\";\nimport { FloatingUIOptions } from \"./FloatingUIOptions.js\";\n\nexport type GenericPopoverReference =\n  | {\n      // A DOM element to use as the reference element for the popover.\n      element: Element;\n      // To update the popover position, `element.getReferenceBoundingRect`\n      // is called. This flag caches the last result of the call while the\n      // element is mounted to the DOM, so it doesn't update while the\n      // popover is closing and transitioning out. Useful for if the\n      // reference element unmounts, as `element.getReferenceBoundingRect`\n      // would return a `DOMRect` with x, y, width, and height of 0.\n      // Defaults to `true`.\n      cacheMountedBoundingClientRect?: boolean;\n    }\n  | {\n      element: undefined;\n      // When no reference element is provided, this can be provided as an\n      // alternative \"virtual\" element to position the popover around.\n      getBoundingClientRect: () => DOMRect;\n    }\n  | {\n      element: Element;\n      cacheMountedBoundingClientRect?: boolean;\n      // If both `element` and `getBoundingClientRect` are provided, uses\n      // `getBoundingClientRect` to position the popover, but still treats\n      // `element` as the reference element for all other purposes. When\n      // `cacheMountedBoundingClientRect` is `true` or unspecified, this\n      // function is not called while the reference element is not mounted.\n      getBoundingClientRect: () => DOMRect;\n    };\n\n// Returns a modified version of `getBoundingClientRect`, if\n// `reference.element` is passed and `reference.cacheMountedBoundingClientRect`\n// is `true` or `undefined`. In the modified version, each new result is cached\n// and returned while `reference.element` is connected to the DOM. If it is no\n// longer connected, the cache is no longer updated and the last cached result\n// is used.\n//\n// In all other cases, just returns `reference.getBoundingClientRect`, or\n// `reference.element.getBoundingClientRect` if it's not defined.\nexport function getMountedBoundingClientRectCache(\n  reference: GenericPopoverReference,\n) {\n  let lastBoundingClientRect = new DOMRect();\n  const getBoundingClientRect =\n    \"getBoundingClientRect\" in reference\n      ? () => reference.getBoundingClientRect()\n      : () => reference.element.getBoundingClientRect();\n\n  return () => {\n    if (\n      reference.element &&\n      (reference.cacheMountedBoundingClientRect ?? true)\n    ) {\n      if (reference.element.isConnected) {\n        lastBoundingClientRect = getBoundingClientRect();\n      }\n\n      return lastBoundingClientRect;\n    }\n\n    return getBoundingClientRect();\n  };\n}\n\n/**\n * Merges two `whileElementsMounted` handlers into one. Both run when elements\n * mount, and both cleanup functions are called on unmount.\n */\nfunction mergeWhileElementsMounted(\n  a: UseFloatingOptions[\"whileElementsMounted\"],\n  b: UseFloatingOptions[\"whileElementsMounted\"],\n): UseFloatingOptions[\"whileElementsMounted\"] {\n  if (!a) {\n    return b;\n  }\n  if (!b) {\n    return a;\n  }\n\n  return (reference, floating, update) => {\n    const cleanupA = a(reference, floating, update);\n    const cleanupB = b(reference, floating, update);\n    return () => {\n      cleanupA?.();\n      cleanupB?.();\n    };\n  };\n}\n\nexport const GenericPopover = (\n  props: FloatingUIOptions & {\n    reference?: GenericPopoverReference;\n    children: ReactNode;\n  },\n) => {\n  const editor = useBlockNoteEditor();\n  const portalRoot = editor?.portalElement;\n  if (!portalRoot) {\n    throw new Error(\"Portal element not found\");\n  }\n  const {\n    whileElementsMounted: _whileElementsMounted,\n    ...restFloatingOptions\n  } = props.useFloatingOptions ?? {};\n\n  const { refs, floatingStyles, context } = useFloating<HTMLDivElement>({\n    whileElementsMounted: mergeWhileElementsMounted(\n      autoUpdate,\n      props.useFloatingOptions?.whileElementsMounted,\n    ),\n    ...restFloatingOptions,\n  });\n\n  const { isMounted, styles } = useTransitionStyles(\n    context,\n    props.useTransitionStylesProps,\n  );\n  const { status } = useTransitionStatus(\n    context,\n    props.useTransitionStatusProps,\n  );\n\n  const dismiss = useDismiss(context, props.useDismissProps);\n  const hover = useHover(context, { enabled: false, ...props.useHoverProps });\n  // Also returns `getReferenceProps` but unused as the reference element may\n  // not even be managed by React, so we may be unable to set them. Seems like\n  // `refs.setReferences` attaches most of the same listeners anyway, but\n  // possible both are needed.\n  const { getFloatingProps } = useInteractions([dismiss, hover]);\n\n  const innerHTML = useRef<string>(\"\");\n  const ref = useRef<HTMLDivElement>(null);\n  const mergedRefs = useMergeRefs([ref, refs.setFloating]);\n\n  useEffect(() => {\n    if (props.reference) {\n      const element =\n        \"element\" in props.reference ? props.reference.element : undefined;\n\n      if (element !== undefined) {\n        refs.setReference(element);\n      }\n\n      refs.setPositionReference({\n        getBoundingClientRect: getMountedBoundingClientRectCache(\n          props.reference,\n        ),\n        contextElement: element,\n      });\n    }\n  }, [props.reference, refs]);\n\n  // Stores the last rendered `innerHTML` of the popover while it was open. The\n  // `innerHTML` is used while the popover is closing, as the React children\n  // may rerender during this time, causing unwanted behaviour.\n  useEffect(\n    () => {\n      if (status === \"initial\" || status === \"open\") {\n        if (ref.current?.innerHTML) {\n          innerHTML.current = ref.current.innerHTML;\n        }\n      }\n    },\n    // `props.children` is added to the deps, since it's ultimately the HTML of\n    // the children that we're storing.\n    [status, props.reference, props.children],\n  );\n\n  if (!isMounted) {\n    return false;\n  }\n\n  const mergedProps: HTMLAttributes<HTMLDivElement> = {\n    ...props.elementProps,\n    style: {\n      display: \"flex\",\n      ...props.elementProps?.style,\n      zIndex: `calc(var(--bn-ui-base-z-index, 0) + ${props.elementProps?.style?.zIndex || 0})`,\n      ...floatingStyles,\n      ...styles,\n    },\n    ...getFloatingProps(),\n  };\n\n  if (status === \"close\") {\n    // While the popover is closing, shows its last rendered `innerHTML` while\n    // it was open, instead of the React children. This is because they may\n    // rerender during this time, causing unwanted behaviour.\n    //\n    // When we use the `GenericPopover` for BlockNote's internal UI elements\n    // this isn't a huge deal, as we only pass child components if the popover\n    // should be open. So without this fix, the popover just won't transition\n    // out and will instead appear to hide instantly.\n    return (\n      <FloatingPortal root={portalRoot}>\n        <div\n          ref={mergedRefs}\n          {...mergedProps}\n          dangerouslySetInnerHTML={{ __html: innerHTML.current }}\n        />\n      </FloatingPortal>\n    );\n  }\n\n  if (!props.focusManagerProps?.disabled) {\n    return (\n      <FloatingPortal root={portalRoot}>\n        <FloatingFocusManager {...props.focusManagerProps} context={context}>\n          <div ref={mergedRefs} {...mergedProps}>\n            {props.children}\n          </div>\n        </FloatingFocusManager>\n      </FloatingPortal>\n    );\n  }\n\n  return (\n    <FloatingPortal root={portalRoot}>\n      <div ref={mergedRefs} {...mergedProps}>\n        {props.children}\n      </div>\n    </FloatingPortal>\n  );\n};\n","import {\n  ChangeEvent,\n  ComponentType,\n  createContext,\n  CSSProperties,\n  ForwardedRef,\n  HTMLInputAutoCompleteAttribute,\n  KeyboardEvent,\n  MouseEvent,\n  ReactNode,\n  useContext,\n} from \"react\";\n\nimport { BlockNoteEditor } from \"@blocknote/core\";\nimport { User } from \"@blocknote/core/comments\";\nimport { DefaultReactGridSuggestionItem } from \"../components/SuggestionMenu/GridSuggestionMenu/types.js\";\nimport { DefaultReactSuggestionItem } from \"../components/SuggestionMenu/types.js\";\n\ntype ToolbarRootType = {\n  className?: string;\n  children?: ReactNode;\n  onMouseEnter?: () => void;\n  onMouseLeave?: () => void;\n  variant?: \"default\" | \"action-toolbar\";\n};\n\ntype ToolbarButtonType = {\n  className?: string;\n  mainTooltip?: string;\n  secondaryTooltip?: string;\n  icon?: ReactNode;\n  onClick?: (e: MouseEvent) => void;\n  isSelected?: boolean;\n  isDisabled?: boolean;\n  variant?: \"default\" | \"compact\";\n} & (\n  | { children: ReactNode; label?: string }\n  | { children?: undefined; label: string }\n);\n\ntype ToolbarSelectType = {\n  className?: string;\n  items: {\n    text: string;\n    icon: ReactNode;\n    onClick: () => void;\n    isSelected: boolean;\n    isDisabled?: boolean;\n  }[];\n  isDisabled?: boolean;\n};\n\ntype MenuButtonType = {\n  className?: string;\n  onClick?: (e: MouseEvent) => void;\n  icon?: ReactNode;\n  onDragStart?: (e: React.DragEvent) => void;\n  onDragEnd?: (e: React.DragEvent) => void;\n  draggable?: boolean;\n} & (\n  | { children: ReactNode; label?: string }\n  | { children?: undefined; label: string }\n);\n\nexport type ComponentProps = {\n  FormattingToolbar: {\n    Root: ToolbarRootType;\n    Button: ToolbarButtonType;\n    Select: ToolbarSelectType;\n  };\n  FilePanel: {\n    Root: {\n      className?: string;\n      tabs: {\n        name: string;\n        tabPanel: ReactNode;\n      }[];\n      openTab: string;\n      setOpenTab: (name: string) => void;\n      defaultOpenTab: string;\n      loading: boolean;\n    };\n    Button: {\n      className?: string;\n      onClick: () => void;\n    } & (\n      | { children: ReactNode; label?: string }\n      | { children?: undefined; label: string }\n    );\n    FileInput: {\n      className?: string;\n      accept: string;\n      value: File | null;\n      placeholder: string;\n      onChange: (payload: File | null) => void;\n    };\n    TabPanel: {\n      className?: string;\n      children?: ReactNode;\n    };\n    TextInput: {\n      className?: string;\n      value: string;\n      placeholder: string;\n      onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n      onKeyDown: (event: KeyboardEvent) => void;\n    };\n  };\n  LinkToolbar: {\n    Root: ToolbarRootType;\n    Button: ToolbarButtonType;\n    Select: ToolbarSelectType;\n  };\n  SideMenu: {\n    Root: {\n      className?: string;\n      children?: ReactNode;\n    };\n    Button: {\n      className?: string;\n      onClick?: (e: MouseEvent) => void;\n      icon?: ReactNode;\n      onDragStart?: (e: React.DragEvent) => void;\n      onDragEnd?: (e: React.DragEvent) => void;\n      draggable?: boolean;\n    } & (\n      | { children: ReactNode; label?: string }\n      | { children?: undefined; label: string }\n    );\n  };\n  SuggestionMenu: {\n    Root: {\n      id: string;\n      className?: string;\n      children?: ReactNode;\n    };\n    EmptyItem: {\n      className?: string;\n      children?: ReactNode;\n    };\n    Item: {\n      className?: string;\n      id: string;\n      isSelected: boolean;\n      onClick: () => void;\n      item: Omit<DefaultReactSuggestionItem, \"onItemClick\">;\n    };\n    Label: {\n      className?: string;\n      children?: ReactNode;\n    };\n    Loader: {\n      className?: string;\n    };\n  };\n  GridSuggestionMenu: {\n    Root: {\n      id: string;\n      columns: number;\n      className?: string;\n      children?: ReactNode;\n    };\n    EmptyItem: {\n      columns: number;\n      className?: string;\n      children?: ReactNode;\n    };\n    Item: {\n      className?: string;\n      id: string;\n      isSelected: boolean;\n      onClick: () => void;\n      item: DefaultReactGridSuggestionItem;\n    };\n    // Label: {\n    //   className?: string;\n    //   children?: ReactNode;\n    // };\n    Loader: {\n      columns: number;\n      className?: string;\n      children?: ReactNode;\n    };\n  };\n  TableHandle: {\n    Root: {\n      className?: string;\n      draggable: boolean;\n      onDragStart: (e: React.DragEvent) => void;\n      onDragEnd: () => void;\n      style?: CSSProperties;\n    } & (\n      | { children: ReactNode; label?: string }\n      | { children?: undefined; label: string }\n    );\n    ExtendButton: {\n      className?: string;\n      onClick: (e: React.MouseEvent) => void;\n      onMouseDown: (e: React.MouseEvent) => void;\n      children: ReactNode;\n    };\n  };\n  Comments: {\n    Card: {\n      className?: string;\n      headerText?: string;\n      selected?: boolean;\n      onFocus?: (event: React.FocusEvent) => void;\n      onBlur?: (event: React.FocusEvent) => void;\n      tabIndex?: number;\n      children?: ReactNode;\n    };\n    CardSection: {\n      className?: string;\n      children?: ReactNode;\n    };\n    ExpandSectionsPrompt: {\n      className?: string;\n      children?: ReactNode;\n    };\n    Editor: {\n      className?: string;\n      autoFocus?: boolean;\n      editable: boolean;\n      editor: BlockNoteEditor<any, any, any>;\n      onFocus?: () => void;\n      onBlur?: () => void;\n    };\n    Comment: {\n      className?: string;\n      children?: ReactNode;\n      authorInfo: \"loading\" | User;\n      timeString: string;\n      edited: boolean;\n      actions?: ReactNode;\n      showActions?: boolean | \"hover\";\n      emojiPickerOpen?: boolean;\n    };\n  };\n  // TODO: We should try to make everything as generic as we can\n  Generic: {\n    Badge: {\n      Root: {\n        className?: string;\n        text: string;\n        icon?: ReactNode;\n        isSelected?: boolean;\n        mainTooltip?: string;\n        secondaryTooltip?: string;\n        onClick?: (event: React.MouseEvent) => void;\n        onMouseEnter?: () => void;\n      };\n      Group: {\n        className?: string;\n        children: ReactNode;\n      };\n    };\n    Form: {\n      Root: {\n        children?: ReactNode;\n      };\n      TextInput: {\n        className?: string;\n        name: string;\n        label?: string;\n        variant?: \"default\" | \"large\";\n        icon: ReactNode;\n        rightSection?: ReactNode;\n        autoFocus?: boolean;\n        placeholder?: string;\n        disabled?: boolean;\n        value: string;\n        onKeyDown: (event: KeyboardEvent<HTMLInputElement>) => void;\n        onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n        onSubmit?: () => void;\n        autoComplete?: HTMLInputAutoCompleteAttribute;\n        \"aria-activedescendant\"?: string;\n        ref?: ForwardedRef<HTMLInputElement>;\n      };\n    };\n    Menu: {\n      Root: {\n        sub?: boolean;\n        onOpenChange?: (open: boolean) => void;\n        position?:\n          | \"top\"\n          | \"right\"\n          | \"bottom\"\n          | \"left\"\n          | `${\"top\" | \"right\" | \"bottom\" | \"left\"}-${\"start\" | \"end\"}`;\n        children?: ReactNode;\n      };\n      Divider: {\n        className?: string;\n      };\n      Dropdown: {\n        className?: string;\n        children?: ReactNode;\n        sub?: boolean;\n      };\n      Item: {\n        className?: string;\n        children?: ReactNode;\n\n        subTrigger?: boolean;\n        icon?: ReactNode;\n        checked?: boolean;\n        onClick?: () => void;\n      };\n      Label: {\n        className?: string;\n        children?: ReactNode;\n      };\n      Trigger: {\n        children?: ReactNode;\n        sub?: boolean;\n      };\n      Button: MenuButtonType;\n    };\n    Popover: {\n      Root: {\n        open?: boolean;\n        onOpenChange?: (open: boolean) => void;\n        position?:\n          | \"top\"\n          | \"right\"\n          | \"bottom\"\n          | \"left\"\n          | `${\"top\" | \"right\" | \"bottom\" | \"left\"}-${\"start\" | \"end\"}`;\n        portalRoot?: HTMLElement | null;\n        children?: ReactNode;\n      };\n      Content: {\n        className?: string;\n        variant: \"form-popover\" | \"panel-popover\";\n        children?: ReactNode;\n      };\n      Trigger: {\n        children?: ReactNode;\n      };\n    };\n    Toolbar: {\n      Root: ToolbarRootType;\n      Button: ToolbarButtonType;\n      Select: ToolbarSelectType;\n    };\n  };\n};\n\nexport type Components = {\n  [Components in keyof Omit<ComponentProps, \"Generic\">]: {\n    [Component in keyof ComponentProps[Components]]: ComponentType<\n      ComponentProps[Components][Component]\n    >;\n  };\n} & {\n  // only needed as Generic Root/etc elements are 1 level of nesting deeper\n  Generic: {\n    [GenericComponents in keyof ComponentProps[\"Generic\"]]: {\n      [Component in keyof ComponentProps[\"Generic\"][GenericComponents]]: ComponentType<\n        ComponentProps[\"Generic\"][GenericComponents][Component]\n      >;\n    };\n  };\n};\n\nexport const ComponentsContext = createContext<Components | undefined>(\n  undefined,\n);\n\nexport function useComponentsContext(): Components | undefined {\n  return useContext(ComponentsContext)!;\n}\n","import { Dictionary } from \"@blocknote/core\";\nimport { useBlockNoteContext } from \"../editor/BlockNoteContext.js\";\n\nexport function useDictionary(): Dictionary {\n  const ctx = useBlockNoteContext();\n  return ctx!.editor!.dictionary;\n}\n","import type { BlockNoteEditor } from \"@blocknote/core\";\nimport deepEqual from \"fast-deep-equal/es6/react.js\";\nimport { useDebugValue, useEffect, useLayoutEffect, useState } from \"react\";\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/shim/with-selector\";\nimport { useBlockNoteContext } from \"../editor/BlockNoteContext.js\";\n\nconst useIsomorphicLayoutEffect =\n  typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\nexport type EditorStateSnapshot<\n  TEditor extends BlockNoteEditor<any, any, any> | null = BlockNoteEditor<\n    any,\n    any,\n    any\n  > | null,\n> = {\n  editor: TEditor;\n  transactionNumber: number;\n};\n\nexport type UseEditorStateOptions<\n  TSelectorResult,\n  TEditor extends BlockNoteEditor<any, any, any> | null = BlockNoteEditor<\n    any,\n    any,\n    any\n  > | null,\n> = {\n  /**\n   * The editor instance. If not provided, will use the editor from BlockNoteContext.\n   */\n  editor?: TEditor;\n\n  /**\n   * A selector function to determine the value to compare for re-rendering.\n   */\n  selector: (context: EditorStateSnapshot<TEditor>) => TSelectorResult;\n\n  /**\n   * A custom equality function to determine if the editor should re-render.\n   * @default `deepEqual` from `fast-deep-equal`\n   */\n  equalityFn?: (a: TSelectorResult, b: TSelectorResult | null) => boolean;\n\n  /**\n   * The event to subscribe to.\n   * @default \"all\"\n   */\n  on?: \"all\" | \"selection\" | \"change\";\n};\n\n/**\n * To synchronize the editor instance with the component state,\n * we need to create a separate instance that is not affected by the component re-renders.\n */\nclass EditorStateManager<\n  TEditor extends BlockNoteEditor<any, any, any> | null = BlockNoteEditor<\n    any,\n    any,\n    any\n  > | null,\n> {\n  private transactionNumber = 0;\n\n  private lastTransactionNumber = 0;\n\n  private lastSnapshot: EditorStateSnapshot<TEditor>;\n\n  private editor: TEditor;\n\n  private subscribers = new Set<() => void>();\n\n  constructor(initialEditor: TEditor) {\n    this.editor = initialEditor;\n    this.lastSnapshot = { editor: initialEditor, transactionNumber: 0 };\n\n    this.getSnapshot = this.getSnapshot.bind(this);\n    this.getServerSnapshot = this.getServerSnapshot.bind(this);\n    this.watch = this.watch.bind(this);\n    this.subscribe = this.subscribe.bind(this);\n  }\n\n  /**\n   * Get the current editor instance.\n   */\n  getSnapshot(): EditorStateSnapshot<TEditor> {\n    if (this.transactionNumber === this.lastTransactionNumber) {\n      return this.lastSnapshot;\n    }\n    this.lastTransactionNumber = this.transactionNumber;\n    this.lastSnapshot = {\n      editor: this.editor,\n      transactionNumber: this.transactionNumber,\n    };\n    return this.lastSnapshot;\n  }\n\n  /**\n   * Always disable the editor on the server-side.\n   */\n  getServerSnapshot(): EditorStateSnapshot<null> {\n    return { editor: null, transactionNumber: 0 };\n  }\n\n  /**\n   * Subscribe to the editor instance's changes.\n   */\n  subscribe(callback: () => void): () => void {\n    this.subscribers.add(callback);\n    return () => {\n      this.subscribers.delete(callback);\n    };\n  }\n\n  /**\n   * Watch the editor instance for changes.\n   */\n  watch(\n    nextEditor: BlockNoteEditor<any, any, any> | null,\n    on: \"all\" | \"selection\" | \"change\",\n  ): undefined | (() => void) {\n    this.editor = nextEditor as TEditor;\n\n    if (this.editor) {\n      /**\n       * This will force a re-render when the editor state changes.\n       * This is to support things like `editor.can().toggleBold()` in components that `useEditor`.\n       * This could be more efficient, but it's a good trade-off for now.\n       */\n      const fn = () => {\n        this.transactionNumber += 1;\n        this.subscribers.forEach((callback) => callback());\n      };\n\n      const currentTiptapEditor = this.editor._tiptapEditor;\n\n      const EVENT_TYPES = {\n        all: \"transaction\",\n        selection: \"selectionUpdate\",\n        change: \"update\",\n      } as const;\n\n      currentTiptapEditor.on(EVENT_TYPES[on], fn);\n      return () => {\n        currentTiptapEditor.off(EVENT_TYPES[on], fn);\n      };\n    }\n\n    return undefined;\n  }\n}\n\n/**\n * This hook allows you to watch for changes on the editor instance.\n * It will allow you to select a part of the editor state and re-render the component when it changes.\n * @example\n * ```tsx\n * const { currentSelection } = useEditorState({\n *  selector: snapshot => ({ currentSelection: snapshot.editor?._tiptapEditor.state.selection }),\n * })\n * ```\n */\nexport function useEditorState<TSelectorResult>(\n  options: UseEditorStateOptions<\n    TSelectorResult,\n    BlockNoteEditor<any, any, any>\n  >,\n): TSelectorResult;\n/**\n * This hook allows you to watch for changes on the editor instance.\n * It will allow you to select a part of the editor state and re-render the component when it changes.\n * @example\n * ```tsx\n * const { currentSelection } = useEditorState({\n *  selector: snapshot => ({ currentSelection: snapshot.editor?._tiptapEditor.state.selection }),\n * })\n * ```\n */\nexport function useEditorState<TSelectorResult>(\n  options: UseEditorStateOptions<\n    TSelectorResult,\n    BlockNoteEditor<any, any, any> | null\n  >,\n): TSelectorResult | null;\n\n/**\n * This hook allows you to watch for changes on the editor instance.\n * It will allow you to select a part of the editor state and re-render the component when it changes.\n * @example\n * ```tsx\n * const { currentSelection } = useEditorState({\n *  selector: snapshot => ({ currentSelection: snapshot.editor?._tiptapEditor.state.selection }),\n * })\n * ```\n */\nexport function useEditorState<TSelectorResult>(\n  options:\n    | UseEditorStateOptions<TSelectorResult, BlockNoteEditor<any, any, any>>\n    | UseEditorStateOptions<\n        TSelectorResult,\n        BlockNoteEditor<any, any, any> | null\n      >,\n): TSelectorResult | null {\n  const editorContext = useBlockNoteContext();\n  const editor = options.editor || editorContext?.editor || null;\n  const on = options.on || \"all\";\n\n  const [editorStateManager] = useState(() => new EditorStateManager(editor));\n\n  // Using the `useSyncExternalStore` hook to sync the editor instance with the component state\n  const selectedState = useSyncExternalStoreWithSelector(\n    editorStateManager.subscribe,\n    editorStateManager.getSnapshot,\n    editorStateManager.getServerSnapshot,\n    options.selector as UseEditorStateOptions<\n      TSelectorResult,\n      BlockNoteEditor<any, any, any> | null\n    >[\"selector\"],\n    options.equalityFn ?? deepEqual,\n  );\n\n  useIsomorphicLayoutEffect(() => {\n    return editorStateManager.watch(editor, on);\n  }, [editor, editorStateManager, on]);\n\n  useDebugValue(selectedState);\n\n  return selectedState;\n}\n","import { posToDOMRect } from \"@tiptap/core\";\nimport { ReactNode, useMemo } from \"react\";\n\nimport { useBlockNoteEditor } from \"../../hooks/useBlockNoteEditor.js\";\nimport { FloatingUIOptions } from \"./FloatingUIOptions.js\";\nimport { GenericPopover, GenericPopoverReference } from \"./GenericPopover.js\";\n\nexport const PositionPopover = (\n  props: FloatingUIOptions & {\n    position: { from: number; to?: number } | undefined;\n    children: ReactNode;\n  },\n) => {\n  const { position, children, ...floatingUIOptions } = props;\n  const { from, to } = position || {};\n\n  const editor = useBlockNoteEditor<any, any, any>();\n\n  const reference = useMemo<GenericPopoverReference | undefined>(() => {\n    if (from === undefined || to === undefined) {\n      return undefined;\n    }\n\n    return {\n      // Use first child as the editor DOM element may itself be scrollable.\n      // For FloatingUI to auto-update the position during scrolling, the\n      // `contextElement` must be a descendant of the scroll container.\n      element: editor.domElement?.firstElementChild || undefined,\n      getBoundingClientRect: () =>\n        posToDOMRect(editor.prosemirrorView, from, to ?? from),\n    };\n  }, [editor, from, to]);\n\n  return (\n    <GenericPopover reference={reference} {...floatingUIOptions}>\n      {position !== undefined && children}\n    </GenericPopover>\n  );\n};\n","import {\n  BlockNoteEditor,\n  BlockNoteEditorOptions,\n  CustomBlockNoteSchema,\n  DefaultBlockSchema,\n  DefaultInlineContentSchema,\n  DefaultStyleSchema,\n} from \"@blocknote/core\";\nimport { DependencyList, useMemo } from \"react\";\n\n/**\n * Hook to instantiate a BlockNote Editor instance in React\n */\nexport const useCreateBlockNote = <\n  Options extends Partial<BlockNoteEditorOptions<any, any, any>> | undefined,\n>(\n  options: Options = {} as Options,\n  deps: DependencyList = [],\n): Options extends {\n  schema: CustomBlockNoteSchema<infer BSchema, infer ISchema, infer SSchema>;\n}\n  ? BlockNoteEditor<BSchema, ISchema, SSchema>\n  : BlockNoteEditor<\n      DefaultBlockSchema,\n      DefaultInlineContentSchema,\n      DefaultStyleSchema\n    > => {\n  return useMemo(() => {\n    const editor = BlockNoteEditor.create(options) as any;\n    if (window) {\n      // for testing / dev purposes\n      (window as any).ProseMirror = editor._tiptapEditor;\n    }\n    return editor;\n  }, deps); //eslint-disable-line react-hooks/exhaustive-deps\n};\n","import { BlockNoteEditor } from \"@blocknote/core\";\nimport { FC, useCallback, useEffect, useState } from \"react\";\nimport { useComponentsContext } from \"../../editor/ComponentsContext.js\";\nimport { useEditorState } from \"../../hooks/useEditorState.js\";\n\n/**\n * The CommentEditor component displays an editor for creating or editing a comment.\n * Currently, we also use the non-editable version for displaying a comment.\n *\n * It's used:\n * - to create a new comment (FloatingComposer.tsx)\n * - As the last item in a Thread, to compose a reply (Thread.tsx)\n * - To edit or display an existing comment (Comment.tsx)\n *\n */\nexport const CommentEditor = (props: {\n  autoFocus?: boolean;\n  editable: boolean;\n  actions?: FC<{\n    isFocused: boolean;\n    isEmpty: boolean;\n  }>;\n  editor: BlockNoteEditor<any, any, any>;\n}) => {\n  const [isFocused, setIsFocused] = useState(false);\n  const isEmpty = useEditorState({\n    editor: props.editor,\n    selector: ({ editor }) => editor.isEmpty,\n  });\n\n  const components = useComponentsContext()!;\n\n  const onFocus = useCallback(() => {\n    setIsFocused(true);\n  }, []);\n\n  const onBlur = useCallback(() => {\n    setIsFocused(false);\n  }, []);\n\n  // When we click the edit button on a comment, we also want to focus the\n  // comment editor\n  useEffect(() => {\n    if (props.editable && props.autoFocus) {\n      props.editor.focus();\n    }\n  }, [props.autoFocus, props.editable, props.editor]);\n\n  return (\n    <>\n      <components.Comments.Editor\n        autoFocus={props.autoFocus}\n        className=\"bn-comment-editor\"\n        editor={props.editor}\n        onFocus={onFocus}\n        onBlur={onBlur}\n        editable={props.editable}\n      />\n      {props.actions && (\n        <div className={\"bn-comment-actions-wrapper\"}>\n          <props.actions isFocused={isFocused} isEmpty={isEmpty} />\n        </div>\n      )}\n    </>\n  );\n};\n","import { BlockNoteSchema, defaultStyleSpecs } from \"@blocknote/core\";\nimport { createParagraphBlockSpec } from \"@blocknote/core\";\n\n// this is quite convoluted. we'll clean this up when we make\n// it easier to extend / customize the default blocks\n\n// remove textColor, backgroundColor from styleSpecs\nconst { textColor, backgroundColor, ...styleSpecs } = defaultStyleSpecs;\n\n// the schema to use for comments\nexport const defaultCommentEditorSchema = BlockNoteSchema.create({\n  blockSpecs: {\n    paragraph: createParagraphBlockSpec(),\n  },\n  styleSpecs,\n});\n"],"mappings":"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"}