/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow strict
 */

/**
 * LexicalExtension
 */
import type {
  LexicalNode,
  NodeKey,
  ExtensionConfigBase,
  EditorState,
  AnyLexicalExtension,
  AnyLexicalExtensionArgument,
  LexicalEditor,
  LexicalEditorWithDispose,
  LexicalCommand,
  LexicalExtension,
  LexicalExtensionDependency,
  EditorUpdateOptions,
  EditorSetOptions,
  InitialEditorConfig,
  SerializedLexicalNode,
} from 'lexical';
import {DecoratorNode} from 'lexical';
export type {
  AnyLexicalExtension,
  AnyLexicalExtensionArgument,
  ExtensionConfigBase,
  ExtensionRegisterState,
  InitialEditorStateType,
  LexicalEditorWithDispose,
  LexicalExtension,
  LexicalExtensionArgument,
  LexicalExtensionConfig,
  LexicalExtensionDependency,
  LexicalExtensionInit,
  LexicalExtensionName,
  LexicalExtensionOutput,
  NormalizedLexicalExtensionArgument,
  NormalizedPeerDependency,
  OutputComponentExtension,
} from 'lexical';
export {
  configExtension,
  declarePeerDependency,
  defineExtension,
  safeCast,
  shallowMergeConfig,
} from 'lexical';

export type NamedSignalsOptions<Defaults> = {
  [K in keyof Defaults]?: Defaults[K];
};
export type NamedSignalsOutput<Defaults> = {
  [K in keyof Defaults]: Signal<Defaults[K]>;
};

declare export function namedSignals<Defaults>(
  defaults: Defaults,
  opts?: NamedSignalsOptions<Defaults>
): NamedSignalsOutput<Defaults>;

declare export class Signal<T = mixed> {
  constructor(value?: T, options?: SignalOptions<T>): this;
  subscribe(fn: (value: T) => void): () => void;
  name?: string;
  valueOf(): T;
  toString(): string;
  toJSON(): T;
  peek(): T;
  brand: symbol;
  value: T;
}
export interface ReadonlySignal<T = mixed> {
  +value: T;
  peek(): T;
  subscribe(fn: (value: T) => void): () => void;
  valueOf(): T;
  toString(): string;
  toJSON(): T;
  brand: symbol;  
}
export type SignalOptions<T = mixed> = {
  watched?: (this: Signal<T>) => void;
  unwatched?: (this: Signal<T>) => void;
  name?: string;
}
type EffectFn = ((this: {
  dispose: () => void;
}) => void | (() => void)) | (() => void | (() => void));
type EffectOptions = {
  name?: string;
}
declare export function batch<T>(fn: () => T): T;
declare export function computed<T>(fn: () => T, options?: SignalOptions<T>): ReadonlySignal<T>;
declare export function effect(fn: EffectFn, options?: EffectOptions): () => void;
declare export function signal<T>(value: T, options?: SignalOptions<T>): Signal<T>;
declare export function signal<T = void>(): Signal<T | void>;
declare export function untracked<T>(fn: () => T): T;

type DefaultSelection = 'rootStart' | 'rootEnd';
export type AutoFocusConfig = {
  defaultSelection: DefaultSelection;
  disabled: boolean;
}
declare export var AutoFocusExtension: LexicalExtension<AutoFocusConfig, "@lexical/extension/AutoFocus", NamedSignalsOutput<AutoFocusConfig>, void>;
export type ClearEditorConfig = {
  $onClear: () => void;
}
declare export var ClearEditorExtension: LexicalExtension<ClearEditorConfig, "@lexical/extension/ClearEditor", NamedSignalsOutput<ClearEditorConfig>, void>;
declare export var EditorStateExtension: LexicalExtension<ExtensionConfigBase, "@lexical/extension/EditorState", Signal<EditorState>, void>;
declare export function getExtensionDependencyFromEditor<
  Extension: AnyLexicalExtension,
>(
  editor: LexicalEditor,
  extension: Extension,
): LexicalExtensionDependency<Extension>;
declare export function getPeerDependencyFromEditor<
  Extension: AnyLexicalExtension = empty,
>(
  editor: LexicalEditor,
  extensionName: Extension['name'],
): LexicalExtensionDependency<Extension> | void;
declare export function getPeerDependencyFromEditorOrThrow<
  Extension: AnyLexicalExtension = empty,
>(
  editor: LexicalEditor,
  extensionName: Extension['name'],
): LexicalExtensionDependency<Extension>;

export type SerializedHorizontalRuleNode = SerializedLexicalNode;
declare export class HorizontalRuleNode extends DecoratorNode<React.Node> {
  static getType(): string;
  static clone(node: HorizontalRuleNode): HorizontalRuleNode;
  createDOM(): HTMLElement;
  getTextContent(): '\n';
  updateDOM(): false;
  decorate(): React.Node;
}

declare export function $createHorizontalRuleNode(): HorizontalRuleNode;
declare export function $isHorizontalRuleNode(
  node: ?LexicalNode,
): node is HorizontalRuleNode;

declare export var INSERT_HORIZONTAL_RULE_COMMAND: LexicalCommand<void>;
declare export var HorizontalRuleExtension: LexicalExtension<ExtensionConfigBase, "@lexical/extension/HorizontalRule", void, void>;

export type InitialStateConfig = {
  updateOptions: EditorUpdateOptions;
  setOptions: EditorSetOptions;
}
declare export var InitialStateExtension: LexicalExtension<InitialStateConfig, "@lexical/extension/InitialState", void, void>;

declare export function buildEditorFromExtensions(
  ...extensions: AnyLexicalExtensionArgument[]
): LexicalEditorWithDispose;

declare export class LexicalBuilder {
  static fromExtensions(
    extensions: AnyLexicalExtensionArgument[],
  ): LexicalBuilder;
  static maybeFromEditor(editor: LexicalEditor): void | LexicalBuilder;
  static fromEditor(editor: LexicalEditor): LexicalBuilder;
  hasExtensionByName(name: string): boolean;
}

declare export var NodeSelectionExtension: LexicalExtension<ExtensionConfigBase, "@lexical/extension/NodeSelection", {
  watchNodeKey: (key: NodeKey) => ReadonlySignal<boolean>;
}, void>;

export type TabIndentationConfig = {
  disabled: boolean;
  maxIndent: null | number;
}
declare export var TabIndentationExtension: LexicalExtension<TabIndentationConfig, "@lexical/extension/TabIndentation", NamedSignalsOutput<TabIndentationConfig>, void>;
declare export function watchedSignal<T>(
  getSnapshot: () => T,
  register: (self: Signal<T>) => () => void,
): Signal<T>;

declare export function registerClearEditor(
  editor: LexicalEditor,
  $onClear?: () => void,
): () => void;

export type KnownTypesAndNodes = {
  types: Set<string>;
  nodes: Set<Class<LexicalNode>>;
};
declare export function getKnownTypesAndNodes(config: InitialEditorConfig): KnownTypesAndNodes;

declare export function registerTabIndentation(
  editor: LexicalEditor,
  maxIndent?: number | ReadonlySignal<null | number>,
): () => void;
