From 55870247890cb0e8dea651b5d7e5e775e515314e Mon Sep 17 00:00:00 2001 From: Benjamin Toby Date: Sun, 5 Jan 2025 07:25:38 +0100 Subject: [PATCH] Updates --- components/lib/editors/TinyMCE/index.tsx | 79 + components/lib/editors/TinyMCE/tinymce.d.ts | 3313 +++++++++++++++++ components/lib/editors/TinyMCE/useTinyMCE.tsx | 34 + components/lib/elements/Border.tsx | 2 +- components/lib/elements/Breadcrumbs.tsx | 4 +- components/lib/elements/Card.tsx | 31 +- components/lib/elements/Dropdown.tsx | 146 + components/lib/elements/Modal.tsx | 5 +- components/lib/elements/Paper.tsx | 2 +- components/lib/elements/Search.tsx | 17 +- components/lib/elements/StarRating.tsx | 164 + components/lib/elements/Tabs.tsx | 108 + components/lib/elements/Tag.tsx | 75 + components/lib/elements/Toast.tsx | 100 + components/lib/form/Checkbox.tsx | 98 + components/lib/form/Form.tsx | 18 +- components/lib/form/ImageUpload.tsx | 56 +- components/lib/form/Input.tsx | 156 +- components/lib/form/Textarea.tsx | 5 +- .../lib/hooks/useIntersectionObserver.tsx | 66 + components/lib/hooks/useLocalUser.tsx | 25 + components/lib/hooks/useWebSocket.tsx | 144 + components/lib/layout/Button.tsx | 19 +- components/lib/layout/HR.tsx | 2 +- components/lib/layout/Img.tsx | 82 + .../lib/layout/LoadingRectangleBlock.tsx | 1 + components/lib/layout/Stack.tsx | 9 +- components/lib/svgs/CheckMarkSVG.tsx | 18 + components/lib/utils/fetch/fetchApi.ts | 40 +- pages/api/coderank-code-server-auth.ts | 12 + 30 files changed, 4756 insertions(+), 75 deletions(-) create mode 100644 components/lib/editors/TinyMCE/index.tsx create mode 100644 components/lib/editors/TinyMCE/tinymce.d.ts create mode 100644 components/lib/editors/TinyMCE/useTinyMCE.tsx create mode 100644 components/lib/elements/Dropdown.tsx create mode 100644 components/lib/elements/StarRating.tsx create mode 100644 components/lib/elements/Tabs.tsx create mode 100644 components/lib/elements/Tag.tsx create mode 100644 components/lib/elements/Toast.tsx create mode 100644 components/lib/form/Checkbox.tsx create mode 100644 components/lib/hooks/useIntersectionObserver.tsx create mode 100644 components/lib/hooks/useLocalUser.tsx create mode 100644 components/lib/hooks/useWebSocket.tsx create mode 100644 components/lib/layout/Img.tsx create mode 100644 components/lib/svgs/CheckMarkSVG.tsx create mode 100644 pages/api/coderank-code-server-auth.ts diff --git a/components/lib/editors/TinyMCE/index.tsx b/components/lib/editors/TinyMCE/index.tsx new file mode 100644 index 0000000..a5fa58e --- /dev/null +++ b/components/lib/editors/TinyMCE/index.tsx @@ -0,0 +1,79 @@ +import React from "react"; +import { RawEditorOptions, TinyMCE, Editor } from "./tinymce"; +import { twMerge } from "tailwind-merge"; + +export type TinyMCEEditorProps = { + tinyMCE?: TinyMCE | null; + options?: RawEditorOptions; + editorRef?: React.MutableRefObject; + setEditor?: React.Dispatch>; + wrapperProps?: React.DetailedHTMLProps< + React.HTMLAttributes, + HTMLDivElement + >; + defaultValue?: string; +}; + +let interval: any; + +/** + * # Tiny MCE Editor Component + * @className_wrapper twui-rte-wrapper + */ +export default function TinyMCEEditor({ + options, + editorRef, + setEditor, + tinyMCE, + wrapperProps, + defaultValue, +}: TinyMCEEditorProps) { + const editorComponentRef = React.useRef(null); + + const FINAL_HEIGHT = options?.height || 500; + + React.useEffect(() => { + if (!editorComponentRef.current) { + return; + } + + tinyMCE?.init({ + height: FINAL_HEIGHT, + menubar: false, + plugins: [ + "advlist lists link image charmap print preview anchor", + "searchreplace visualblocks code fullscreen", + "insertdatetime media table paste code help wordcount", + ], + toolbar: + "undo redo | blocks | bold italic | bullist numlist outdent indent | removeformat", + content_style: + "body { font-family:Helvetica,Arial,sans-serif; font-size:14px }", + init_instance_callback: (editor) => { + setEditor?.(editor as any); + if (editorRef) editorRef.current = editor as any; + if (defaultValue) editor.setContent(defaultValue); + }, + base_url: "https://datasquirel.com/tinymce-public", + body_class: "twui-tinymce", + ...options, + license_key: "gpl", + target: editorComponentRef.current, + }); + }, [tinyMCE]); + + return ( +
+ ); +} diff --git a/components/lib/editors/TinyMCE/tinymce.d.ts b/components/lib/editors/TinyMCE/tinymce.d.ts new file mode 100644 index 0000000..2cfd57c --- /dev/null +++ b/components/lib/editors/TinyMCE/tinymce.d.ts @@ -0,0 +1,3313 @@ +interface StringPathBookmark { + start: string; + end?: string; + forward?: boolean; +} +interface RangeBookmark { + rng: Range; + forward?: boolean; +} +interface IdBookmark { + id: string; + keep?: boolean; + forward?: boolean; +} +interface IndexBookmark { + name: string; + index: number; +} +interface PathBookmark { + start: number[]; + end?: number[]; + isFakeCaret?: boolean; + forward?: boolean; +} +type Bookmark = StringPathBookmark | RangeBookmark | IdBookmark | IndexBookmark | PathBookmark; +type NormalizedEvent = E & { + readonly type: string; + readonly target: T; + readonly isDefaultPrevented: () => boolean; + readonly preventDefault: () => void; + readonly isPropagationStopped: () => boolean; + readonly stopPropagation: () => void; + readonly isImmediatePropagationStopped: () => boolean; + readonly stopImmediatePropagation: () => void; +}; +type MappedEvent = K extends keyof T ? T[K] : any; +interface NativeEventMap { + 'beforepaste': Event; + 'blur': FocusEvent; + 'beforeinput': InputEvent; + 'click': MouseEvent; + 'compositionend': Event; + 'compositionstart': Event; + 'compositionupdate': Event; + 'contextmenu': PointerEvent; + 'copy': ClipboardEvent; + 'cut': ClipboardEvent; + 'dblclick': MouseEvent; + 'drag': DragEvent; + 'dragdrop': DragEvent; + 'dragend': DragEvent; + 'draggesture': DragEvent; + 'dragover': DragEvent; + 'dragstart': DragEvent; + 'drop': DragEvent; + 'focus': FocusEvent; + 'focusin': FocusEvent; + 'focusout': FocusEvent; + 'input': InputEvent; + 'keydown': KeyboardEvent; + 'keypress': KeyboardEvent; + 'keyup': KeyboardEvent; + 'mousedown': MouseEvent; + 'mouseenter': MouseEvent; + 'mouseleave': MouseEvent; + 'mousemove': MouseEvent; + 'mouseout': MouseEvent; + 'mouseover': MouseEvent; + 'mouseup': MouseEvent; + 'paste': ClipboardEvent; + 'selectionchange': Event; + 'submit': Event; + 'touchend': TouchEvent; + 'touchmove': TouchEvent; + 'touchstart': TouchEvent; + 'touchcancel': TouchEvent; + 'wheel': WheelEvent; +} +type EditorEvent = NormalizedEvent; +interface EventDispatcherSettings { + scope?: any; + toggleEvent?: (name: string, state: boolean) => void | boolean; + beforeFire?: (args: EditorEvent) => void; +} +interface EventDispatcherConstructor { + readonly prototype: EventDispatcher; + new (settings?: EventDispatcherSettings): EventDispatcher; + isNative: (name: string) => boolean; +} +declare class EventDispatcher { + static isNative(name: string): boolean; + private readonly settings; + private readonly scope; + private readonly toggleEvent; + private bindings; + constructor(settings?: EventDispatcherSettings); + fire>(name: K, args?: U): EditorEvent; + dispatch>(name: K, args?: U): EditorEvent; + on(name: K, callback: false | ((event: EditorEvent>) => void | boolean), prepend?: boolean, extra?: {}): this; + off(name?: K, callback?: (event: EditorEvent>) => void): this; + once(name: K, callback: (event: EditorEvent>) => void, prepend?: boolean): this; + has(name: string): boolean; +} +type UndoLevelType = 'fragmented' | 'complete'; +interface BaseUndoLevel { + type: UndoLevelType; + bookmark: Bookmark | null; + beforeBookmark: Bookmark | null; +} +interface FragmentedUndoLevel extends BaseUndoLevel { + type: 'fragmented'; + fragments: string[]; + content: ''; +} +interface CompleteUndoLevel extends BaseUndoLevel { + type: 'complete'; + fragments: null; + content: string; +} +type NewUndoLevel = CompleteUndoLevel | FragmentedUndoLevel; +type UndoLevel = NewUndoLevel & { + bookmark: Bookmark; +}; +interface UndoManager { + data: UndoLevel[]; + typing: boolean; + add: (level?: Partial, event?: EditorEvent) => UndoLevel | null; + dispatchChange: () => void; + beforeChange: () => void; + undo: () => UndoLevel | undefined; + redo: () => UndoLevel | undefined; + clear: () => void; + reset: () => void; + hasUndo: () => boolean; + hasRedo: () => boolean; + transact: (callback: () => void) => UndoLevel | null; + ignore: (callback: () => void) => void; + extra: (callback1: () => void, callback2: () => void) => void; +} +type SchemaType = 'html4' | 'html5' | 'html5-strict'; +interface ElementSettings { + block_elements?: string; + boolean_attributes?: string; + move_caret_before_on_enter_elements?: string; + non_empty_elements?: string; + self_closing_elements?: string; + text_block_elements?: string; + text_inline_elements?: string; + void_elements?: string; + whitespace_elements?: string; + transparent_elements?: string; + wrap_block_elements?: string; +} +interface SchemaSettings extends ElementSettings { + custom_elements?: string | Record; + extended_valid_elements?: string; + invalid_elements?: string; + invalid_styles?: string | Record; + schema?: SchemaType; + valid_children?: string; + valid_classes?: string | Record; + valid_elements?: string; + valid_styles?: string | Record; + verify_html?: boolean; + padd_empty_block_inline_children?: boolean; +} +interface Attribute { + required?: boolean; + defaultValue?: string; + forcedValue?: string; + validValues?: Record; +} +interface DefaultAttribute { + name: string; + value: string; +} +interface AttributePattern extends Attribute { + pattern: RegExp; +} +interface ElementRule { + attributes: Record; + attributesDefault?: DefaultAttribute[]; + attributesForced?: DefaultAttribute[]; + attributesOrder: string[]; + attributePatterns?: AttributePattern[]; + attributesRequired?: string[]; + paddEmpty?: boolean; + removeEmpty?: boolean; + removeEmptyAttrs?: boolean; + paddInEmptyBlock?: boolean; +} +interface SchemaElement extends ElementRule { + outputName?: string; + parentsRequired?: string[]; + pattern?: RegExp; +} +interface SchemaMap { + [name: string]: {}; +} +interface SchemaRegExpMap { + [name: string]: RegExp; +} +interface CustomElementSpec { + extends?: string; + attributes?: string[]; + children?: string[]; + padEmpty?: boolean; +} +interface Schema { + type: SchemaType; + children: Record; + elements: Record; + getValidStyles: () => Record | undefined; + getValidClasses: () => Record | undefined; + getBlockElements: () => SchemaMap; + getInvalidStyles: () => Record | undefined; + getVoidElements: () => SchemaMap; + getTextBlockElements: () => SchemaMap; + getTextInlineElements: () => SchemaMap; + getBoolAttrs: () => SchemaMap; + getElementRule: (name: string) => SchemaElement | undefined; + getSelfClosingElements: () => SchemaMap; + getNonEmptyElements: () => SchemaMap; + getMoveCaretBeforeOnEnterElements: () => SchemaMap; + getWhitespaceElements: () => SchemaMap; + getTransparentElements: () => SchemaMap; + getSpecialElements: () => SchemaRegExpMap; + isValidChild: (name: string, child: string) => boolean; + isValid: (name: string, attr?: string) => boolean; + isBlock: (name: string) => boolean; + isInline: (name: string) => boolean; + isWrapper: (name: string) => boolean; + getCustomElements: () => SchemaMap; + addValidElements: (validElements: string) => void; + setValidElements: (validElements: string) => void; + addCustomElements: (customElements: string | Record) => void; + addValidChildren: (validChildren: any) => void; +} +type Attributes$1 = Array<{ + name: string; + value: string; +}> & { + map: Record; +}; +interface AstNodeConstructor { + readonly prototype: AstNode; + new (name: string, type: number): AstNode; + create(name: string, attrs?: Record): AstNode; +} +declare class AstNode { + static create(name: string, attrs?: Record): AstNode; + name: string; + type: number; + attributes?: Attributes$1; + value?: string; + parent?: AstNode | null; + firstChild?: AstNode | null; + lastChild?: AstNode | null; + next?: AstNode | null; + prev?: AstNode | null; + raw?: boolean; + constructor(name: string, type: number); + replace(node: AstNode): AstNode; + attr(name: string, value: string | null | undefined): AstNode | undefined; + attr(name: Record | undefined): AstNode | undefined; + attr(name: string): string | undefined; + clone(): AstNode; + wrap(wrapper: AstNode): AstNode; + unwrap(): void; + remove(): AstNode; + append(node: AstNode): AstNode; + insert(node: AstNode, refNode: AstNode, before?: boolean): AstNode; + getAll(name: string): AstNode[]; + children(): AstNode[]; + empty(): AstNode; + isEmpty(elements: SchemaMap, whitespace?: SchemaMap, predicate?: (node: AstNode) => boolean): boolean; + walk(prev?: boolean): AstNode | null | undefined; +} +type Content = string | AstNode; +type ContentFormat = 'raw' | 'text' | 'html' | 'tree'; +interface GetContentArgs { + format: ContentFormat; + get: boolean; + getInner: boolean; + no_events?: boolean; + save?: boolean; + source_view?: boolean; + [key: string]: any; +} +interface SetContentArgs { + format: string; + set: boolean; + content: Content; + no_events?: boolean; + no_selection?: boolean; + paste?: boolean; + load?: boolean; + initial?: boolean; + [key: string]: any; +} +interface GetSelectionContentArgs extends GetContentArgs { + selection?: boolean; + contextual?: boolean; +} +interface SetSelectionContentArgs extends SetContentArgs { + content: string; + selection?: boolean; +} +interface BlobInfoData { + id?: string; + name?: string; + filename?: string; + blob: Blob; + base64: string; + blobUri?: string; + uri?: string; +} +interface BlobInfo { + id: () => string; + name: () => string; + filename: () => string; + blob: () => Blob; + base64: () => string; + blobUri: () => string; + uri: () => string | undefined; +} +interface BlobCache { + create: { + (o: BlobInfoData): BlobInfo; + (id: string, blob: Blob, base64: string, name?: string, filename?: string): BlobInfo; + }; + add: (blobInfo: BlobInfo) => void; + get: (id: string) => BlobInfo | undefined; + getByUri: (blobUri: string) => BlobInfo | undefined; + getByData: (base64: string, type: string) => BlobInfo | undefined; + findFirst: (predicate: (blobInfo: BlobInfo) => boolean) => BlobInfo | undefined; + removeByUri: (blobUri: string) => void; + destroy: () => void; +} +interface BlobInfoImagePair { + image: HTMLImageElement; + blobInfo: BlobInfo; +} +declare class NodeChange { + private readonly editor; + private lastPath; + constructor(editor: Editor); + nodeChanged(args?: Record): void; + private isSameElementPath; +} +interface SelectionOverrides { + showCaret: (direction: number, node: HTMLElement, before: boolean, scrollIntoView?: boolean) => Range | null; + showBlockCaretContainer: (blockCaretContainer: HTMLElement) => void; + hideFakeCaret: () => void; + destroy: () => void; +} +interface Quirks { + refreshContentEditable(): void; + isHidden(): boolean; +} +type DecoratorData = Record; +type Decorator = (uid: string, data: DecoratorData) => { + attributes?: {}; + classes?: string[]; +}; +type AnnotationListener = (state: boolean, name: string, data?: { + uid: string; + nodes: any[]; +}) => void; +type AnnotationListenerApi = AnnotationListener; +interface AnnotatorSettings { + decorate: Decorator; + persistent?: boolean; +} +interface Annotator { + register: (name: string, settings: AnnotatorSettings) => void; + annotate: (name: string, data: DecoratorData) => void; + annotationChanged: (name: string, f: AnnotationListenerApi) => void; + remove: (name: string) => void; + removeAll: (name: string) => void; + getAll: (name: string) => Record; +} +interface IsEmptyOptions { + readonly skipBogus?: boolean; + readonly includeZwsp?: boolean; + readonly checkRootAsContent?: boolean; + readonly isContent?: (node: Node) => boolean; +} +interface GeomRect { + readonly x: number; + readonly y: number; + readonly w: number; + readonly h: number; +} +interface Rect { + inflate: (rect: GeomRect, w: number, h: number) => GeomRect; + relativePosition: (rect: GeomRect, targetRect: GeomRect, rel: string) => GeomRect; + findBestRelativePosition: (rect: GeomRect, targetRect: GeomRect, constrainRect: GeomRect, rels: string[]) => string | null; + intersect: (rect: GeomRect, cropRect: GeomRect) => GeomRect | null; + clamp: (rect: GeomRect, clampRect: GeomRect, fixedSize?: boolean) => GeomRect; + create: (x: number, y: number, w: number, h: number) => GeomRect; + fromClientRect: (clientRect: DOMRect) => GeomRect; +} +interface NotificationManagerImpl { + open: (spec: NotificationSpec, closeCallback: () => void, hasEditorFocus: () => boolean) => NotificationApi; + close: (notification: T) => void; + getArgs: (notification: T) => NotificationSpec; +} +interface NotificationSpec { + type?: 'info' | 'warning' | 'error' | 'success'; + text: string; + icon?: string; + progressBar?: boolean; + timeout?: number; +} +interface NotificationApi { + close: () => void; + progressBar: { + value: (percent: number) => void; + }; + text: (text: string) => void; + reposition: () => void; + getEl: () => HTMLElement; + settings: NotificationSpec; +} +interface NotificationManager { + open: (spec: NotificationSpec) => NotificationApi; + close: () => void; + getNotifications: () => NotificationApi[]; +} +interface UploadFailure { + message: string; + remove?: boolean; +} +type ProgressFn = (percent: number) => void; +type UploadHandler = (blobInfo: BlobInfo, progress: ProgressFn) => Promise; +interface UploadResult$2 { + url: string; + blobInfo: BlobInfo; + status: boolean; + error?: UploadFailure; +} +type BlockPatternTrigger = 'enter' | 'space'; +interface RawPattern { + start?: any; + end?: any; + format?: any; + cmd?: any; + value?: any; + replacement?: any; + trigger?: BlockPatternTrigger; +} +interface InlineBasePattern { + readonly start: string; + readonly end: string; +} +interface InlineFormatPattern extends InlineBasePattern { + readonly type: 'inline-format'; + readonly format: string[]; +} +interface InlineCmdPattern extends InlineBasePattern { + readonly type: 'inline-command'; + readonly cmd: string; + readonly value?: any; +} +type InlinePattern = InlineFormatPattern | InlineCmdPattern; +interface BlockBasePattern { + readonly start: string; + readonly trigger: BlockPatternTrigger; +} +interface BlockFormatPattern extends BlockBasePattern { + readonly type: 'block-format'; + readonly format: string; +} +interface BlockCmdPattern extends BlockBasePattern { + readonly type: 'block-command'; + readonly cmd: string; + readonly value?: any; +} +type BlockPattern = BlockFormatPattern | BlockCmdPattern; +type Pattern = InlinePattern | BlockPattern; +interface DynamicPatternContext { + readonly text: string; + readonly block: Element; +} +type DynamicPatternsLookup = (ctx: DynamicPatternContext) => Pattern[]; +type RawDynamicPatternsLookup = (ctx: DynamicPatternContext) => RawPattern[]; +interface AlertBannerSpec { + type: 'alertbanner'; + level: 'info' | 'warn' | 'error' | 'success'; + text: string; + icon: string; + url?: string; +} +interface ButtonSpec { + type: 'button'; + text: string; + enabled?: boolean; + primary?: boolean; + name?: string; + icon?: string; + borderless?: boolean; + buttonType?: 'primary' | 'secondary' | 'toolbar'; + context?: string; +} +interface FormComponentSpec { + type: string; + name: string; +} +interface FormComponentWithLabelSpec extends FormComponentSpec { + label?: string; +} +interface CheckboxSpec extends FormComponentSpec { + type: 'checkbox'; + label: string; + enabled?: boolean; + context?: string; +} +interface CollectionSpec extends FormComponentWithLabelSpec { + type: 'collection'; + context?: string; +} +interface CollectionItem { + value: string; + text: string; + icon: string; +} +interface ColorInputSpec extends FormComponentWithLabelSpec { + type: 'colorinput'; + storageKey?: string; + context?: string; +} +interface ColorPickerSpec extends FormComponentWithLabelSpec { + type: 'colorpicker'; +} +interface CustomEditorInit { + setValue: (value: string) => void; + getValue: () => string; + destroy: () => void; +} +type CustomEditorInitFn = (elm: HTMLElement, settings: any) => Promise; +interface CustomEditorOldSpec extends FormComponentSpec { + type: 'customeditor'; + tag?: string; + init: (e: HTMLElement) => Promise; +} +interface CustomEditorNewSpec extends FormComponentSpec { + type: 'customeditor'; + tag?: string; + scriptId: string; + scriptUrl: string; + onFocus?: (e: HTMLElement) => void; + settings?: any; +} +type CustomEditorSpec = CustomEditorOldSpec | CustomEditorNewSpec; +interface DropZoneSpec extends FormComponentWithLabelSpec { + type: 'dropzone'; + context?: string; +} +interface GridSpec { + type: 'grid'; + columns: number; + items: BodyComponentSpec[]; +} +interface HtmlPanelSpec { + type: 'htmlpanel'; + html: string; + onInit?: (el: HTMLElement) => void; + presets?: 'presentation' | 'document'; + stretched?: boolean; +} +interface IframeSpec extends FormComponentWithLabelSpec { + type: 'iframe'; + border?: boolean; + sandboxed?: boolean; + streamContent?: boolean; + transparent?: boolean; +} +interface ImagePreviewSpec extends FormComponentSpec { + type: 'imagepreview'; + height?: string; +} +interface InputSpec extends FormComponentWithLabelSpec { + type: 'input'; + inputMode?: string; + placeholder?: string; + maximized?: boolean; + enabled?: boolean; + context?: string; +} +type Alignment = 'start' | 'center' | 'end'; +interface LabelSpec { + type: 'label'; + label: string; + items: BodyComponentSpec[]; + align?: Alignment; + for?: string; +} +interface ListBoxSingleItemSpec { + text: string; + value: string; +} +interface ListBoxNestedItemSpec { + text: string; + items: ListBoxItemSpec[]; +} +type ListBoxItemSpec = ListBoxNestedItemSpec | ListBoxSingleItemSpec; +interface ListBoxSpec extends FormComponentWithLabelSpec { + type: 'listbox'; + items: ListBoxItemSpec[]; + disabled?: boolean; + context?: string; +} +interface PanelSpec { + type: 'panel'; + classes?: string[]; + items: BodyComponentSpec[]; +} +interface SelectBoxItemSpec { + text: string; + value: string; +} +interface SelectBoxSpec extends FormComponentWithLabelSpec { + type: 'selectbox'; + items: SelectBoxItemSpec[]; + size?: number; + enabled?: boolean; + context?: string; +} +interface SizeInputSpec extends FormComponentWithLabelSpec { + type: 'sizeinput'; + constrain?: boolean; + enabled?: boolean; + context?: string; +} +interface SliderSpec extends FormComponentSpec { + type: 'slider'; + label: string; + min?: number; + max?: number; +} +interface TableSpec { + type: 'table'; + header: string[]; + cells: string[][]; +} +interface TextAreaSpec extends FormComponentWithLabelSpec { + type: 'textarea'; + placeholder?: string; + maximized?: boolean; + enabled?: boolean; + context?: string; +} +interface BaseToolbarButtonSpec { + enabled?: boolean; + tooltip?: string; + icon?: string; + text?: string; + onSetup?: (api: I) => (api: I) => void; + context?: string; +} +interface BaseToolbarButtonInstanceApi { + isEnabled: () => boolean; + setEnabled: (state: boolean) => void; + setText: (text: string) => void; + setIcon: (icon: string) => void; +} +interface ToolbarButtonSpec extends BaseToolbarButtonSpec { + type?: 'button'; + onAction: (api: ToolbarButtonInstanceApi) => void; + shortcut?: string; +} +interface ToolbarButtonInstanceApi extends BaseToolbarButtonInstanceApi { +} +interface ToolbarGroupSetting { + name: string; + items: string[]; +} +type ToolbarConfig = string | ToolbarGroupSetting[]; +interface GroupToolbarButtonInstanceApi extends BaseToolbarButtonInstanceApi { +} +interface GroupToolbarButtonSpec extends BaseToolbarButtonSpec { + type?: 'grouptoolbarbutton'; + items?: ToolbarConfig; +} +interface CardImageSpec { + type: 'cardimage'; + src: string; + alt?: string; + classes?: string[]; +} +interface CardTextSpec { + type: 'cardtext'; + text: string; + name?: string; + classes?: string[]; +} +type CardItemSpec = CardContainerSpec | CardImageSpec | CardTextSpec; +type CardContainerDirection = 'vertical' | 'horizontal'; +type CardContainerAlign = 'left' | 'right'; +type CardContainerValign = 'top' | 'middle' | 'bottom'; +interface CardContainerSpec { + type: 'cardcontainer'; + items: CardItemSpec[]; + direction?: CardContainerDirection; + align?: CardContainerAlign; + valign?: CardContainerValign; +} +interface CommonMenuItemSpec { + enabled?: boolean; + text?: string; + value?: string; + meta?: Record; + shortcut?: string; + context?: string; +} +interface CommonMenuItemInstanceApi { + isEnabled: () => boolean; + setEnabled: (state: boolean) => void; +} +interface CardMenuItemInstanceApi extends CommonMenuItemInstanceApi { +} +interface CardMenuItemSpec extends Omit { + type: 'cardmenuitem'; + label?: string; + items: CardItemSpec[]; + onSetup?: (api: CardMenuItemInstanceApi) => (api: CardMenuItemInstanceApi) => void; + onAction?: (api: CardMenuItemInstanceApi) => void; +} +interface ChoiceMenuItemSpec extends CommonMenuItemSpec { + type?: 'choiceitem'; + icon?: string; +} +interface ChoiceMenuItemInstanceApi extends CommonMenuItemInstanceApi { + isActive: () => boolean; + setActive: (state: boolean) => void; +} +interface ContextMenuItem extends CommonMenuItemSpec { + text: string; + icon?: string; + type?: 'item'; + onAction: () => void; +} +interface ContextSubMenu extends CommonMenuItemSpec { + type: 'submenu'; + text: string; + icon?: string; + getSubmenuItems: () => string | Array; +} +type ContextMenuContents = string | ContextMenuItem | SeparatorMenuItemSpec | ContextSubMenu; +interface ContextMenuApi { + update: (element: Element) => string | Array; +} +interface FancyActionArgsMap { + 'inserttable': { + numRows: number; + numColumns: number; + }; + 'colorswatch': { + value: string; + }; +} +interface BaseFancyMenuItemSpec { + type: 'fancymenuitem'; + fancytype: T; + initData?: Record; + onAction?: (data: FancyActionArgsMap[T]) => void; +} +interface InsertTableMenuItemSpec extends BaseFancyMenuItemSpec<'inserttable'> { + fancytype: 'inserttable'; + initData?: {}; +} +interface ColorSwatchMenuItemSpec extends BaseFancyMenuItemSpec<'colorswatch'> { + fancytype: 'colorswatch'; + select?: (value: string) => boolean; + initData?: { + allowCustomColors?: boolean; + colors?: ChoiceMenuItemSpec[]; + storageKey?: string; + }; +} +type FancyMenuItemSpec = InsertTableMenuItemSpec | ColorSwatchMenuItemSpec; +interface MenuItemSpec extends CommonMenuItemSpec { + type?: 'menuitem'; + icon?: string; + onSetup?: (api: MenuItemInstanceApi) => (api: MenuItemInstanceApi) => void; + onAction?: (api: MenuItemInstanceApi) => void; +} +interface MenuItemInstanceApi extends CommonMenuItemInstanceApi { +} +interface SeparatorMenuItemSpec { + type?: 'separator'; + text?: string; +} +interface ToggleMenuItemSpec extends CommonMenuItemSpec { + type?: 'togglemenuitem'; + icon?: string; + active?: boolean; + onSetup?: (api: ToggleMenuItemInstanceApi) => void; + onAction: (api: ToggleMenuItemInstanceApi) => void; +} +interface ToggleMenuItemInstanceApi extends CommonMenuItemInstanceApi { + isActive: () => boolean; + setActive: (state: boolean) => void; +} +type NestedMenuItemContents = string | MenuItemSpec | NestedMenuItemSpec | ToggleMenuItemSpec | SeparatorMenuItemSpec | FancyMenuItemSpec; +interface NestedMenuItemSpec extends CommonMenuItemSpec { + type?: 'nestedmenuitem'; + icon?: string; + getSubmenuItems: () => string | Array; + onSetup?: (api: NestedMenuItemInstanceApi) => (api: NestedMenuItemInstanceApi) => void; +} +interface NestedMenuItemInstanceApi extends CommonMenuItemInstanceApi { + setTooltip: (tooltip: string) => void; + setIconFill: (id: string, value: string) => void; +} +type MenuButtonItemTypes = NestedMenuItemContents; +type SuccessCallback$1 = (menu: string | MenuButtonItemTypes[]) => void; +interface MenuButtonFetchContext { + pattern: string; +} +interface BaseMenuButtonSpec { + text?: string; + tooltip?: string; + icon?: string; + search?: boolean | { + placeholder?: string; + }; + fetch: (success: SuccessCallback$1, fetchContext: MenuButtonFetchContext, api: BaseMenuButtonInstanceApi) => void; + onSetup?: (api: BaseMenuButtonInstanceApi) => (api: BaseMenuButtonInstanceApi) => void; + context?: string; +} +interface BaseMenuButtonInstanceApi { + isEnabled: () => boolean; + setEnabled: (state: boolean) => void; + isActive: () => boolean; + setActive: (state: boolean) => void; + setText: (text: string) => void; + setIcon: (icon: string) => void; +} +interface ToolbarMenuButtonSpec extends BaseMenuButtonSpec { + type?: 'menubutton'; + onSetup?: (api: ToolbarMenuButtonInstanceApi) => (api: ToolbarMenuButtonInstanceApi) => void; +} +interface ToolbarMenuButtonInstanceApi extends BaseMenuButtonInstanceApi { +} +type ToolbarSplitButtonItemTypes = ChoiceMenuItemSpec | SeparatorMenuItemSpec; +type SuccessCallback = (menu: ToolbarSplitButtonItemTypes[]) => void; +type SelectPredicate = (value: string) => boolean; +type PresetTypes = 'color' | 'normal' | 'listpreview'; +type ColumnTypes$1 = number | 'auto'; +interface ToolbarSplitButtonSpec { + type?: 'splitbutton'; + tooltip?: string; + icon?: string; + text?: string; + select?: SelectPredicate; + presets?: PresetTypes; + columns?: ColumnTypes$1; + fetch: (success: SuccessCallback) => void; + onSetup?: (api: ToolbarSplitButtonInstanceApi) => (api: ToolbarSplitButtonInstanceApi) => void; + onAction: (api: ToolbarSplitButtonInstanceApi) => void; + onItemAction: (api: ToolbarSplitButtonInstanceApi, value: string) => void; + context?: string; +} +interface ToolbarSplitButtonInstanceApi { + isEnabled: () => boolean; + setEnabled: (state: boolean) => void; + setIconFill: (id: string, value: string) => void; + isActive: () => boolean; + setActive: (state: boolean) => void; + setTooltip: (tooltip: string) => void; + setText: (text: string) => void; + setIcon: (icon: string) => void; +} +interface BaseToolbarToggleButtonSpec extends BaseToolbarButtonSpec { + active?: boolean; +} +interface BaseToolbarToggleButtonInstanceApi extends BaseToolbarButtonInstanceApi { + isActive: () => boolean; + setActive: (state: boolean) => void; +} +interface ToolbarToggleButtonSpec extends BaseToolbarToggleButtonSpec { + type?: 'togglebutton'; + onAction: (api: ToolbarToggleButtonInstanceApi) => void; + shortcut?: string; +} +interface ToolbarToggleButtonInstanceApi extends BaseToolbarToggleButtonInstanceApi { +} +type Id = string; +interface TreeSpec { + type: 'tree'; + items: TreeItemSpec[]; + onLeafAction?: (id: Id) => void; + defaultExpandedIds?: Id[]; + onToggleExpand?: (expandedIds: Id[], { expanded, node }: { + expanded: boolean; + node: Id; + }) => void; + defaultSelectedId?: Id; +} +interface BaseTreeItemSpec { + title: string; + id: Id; + menu?: ToolbarMenuButtonSpec; + customStateIcon?: string; + customStateIconTooltip?: string; +} +interface DirectorySpec extends BaseTreeItemSpec { + type: 'directory'; + children: TreeItemSpec[]; +} +interface LeafSpec extends BaseTreeItemSpec { + type: 'leaf'; +} +type TreeItemSpec = DirectorySpec | LeafSpec; +interface UrlInputSpec extends FormComponentWithLabelSpec { + type: 'urlinput'; + filetype?: 'image' | 'media' | 'file'; + enabled?: boolean; + picker_text?: string; + context?: string; +} +interface UrlInputData { + value: string; + meta: { + text?: string; + }; +} +type BodyComponentSpec = BarSpec | ButtonSpec | CheckboxSpec | TextAreaSpec | InputSpec | ListBoxSpec | SelectBoxSpec | SizeInputSpec | SliderSpec | IframeSpec | HtmlPanelSpec | UrlInputSpec | DropZoneSpec | ColorInputSpec | GridSpec | ColorPickerSpec | ImagePreviewSpec | AlertBannerSpec | CollectionSpec | LabelSpec | TableSpec | TreeSpec | PanelSpec | CustomEditorSpec; +interface BarSpec { + type: 'bar'; + items: BodyComponentSpec[]; +} +interface DialogToggleMenuItemSpec extends CommonMenuItemSpec { + type?: 'togglemenuitem'; + name: string; +} +type DialogFooterMenuButtonItemSpec = DialogToggleMenuItemSpec; +interface BaseDialogFooterButtonSpec { + name?: string; + align?: 'start' | 'end'; + primary?: boolean; + enabled?: boolean; + icon?: string; + buttonType?: 'primary' | 'secondary'; + context?: string; +} +interface DialogFooterNormalButtonSpec extends BaseDialogFooterButtonSpec { + type: 'submit' | 'cancel' | 'custom'; + text: string; +} +interface DialogFooterMenuButtonSpec extends BaseDialogFooterButtonSpec { + type: 'menu'; + text?: string; + tooltip?: string; + icon?: string; + items: DialogFooterMenuButtonItemSpec[]; +} +interface DialogFooterToggleButtonSpec extends BaseDialogFooterButtonSpec { + type: 'togglebutton'; + tooltip?: string; + icon?: string; + text?: string; + active?: boolean; +} +type DialogFooterButtonSpec = DialogFooterNormalButtonSpec | DialogFooterMenuButtonSpec | DialogFooterToggleButtonSpec; +interface TabSpec { + name?: string; + title: string; + items: BodyComponentSpec[]; +} +interface TabPanelSpec { + type: 'tabpanel'; + tabs: TabSpec[]; +} +type DialogDataItem = any; +type DialogData = Record; +interface DialogInstanceApi { + getData: () => T; + setData: (data: Partial) => void; + setEnabled: (name: string, state: boolean) => void; + focus: (name: string) => void; + showTab: (name: string) => void; + redial: (nu: DialogSpec) => void; + block: (msg: string) => void; + unblock: () => void; + toggleFullscreen: () => void; + close: () => void; +} +interface DialogActionDetails { + name: string; + value?: any; +} +interface DialogChangeDetails { + name: keyof T; +} +interface DialogTabChangeDetails { + newTabName: string; + oldTabName: string; +} +type DialogActionHandler = (api: DialogInstanceApi, details: DialogActionDetails) => void; +type DialogChangeHandler = (api: DialogInstanceApi, details: DialogChangeDetails) => void; +type DialogSubmitHandler = (api: DialogInstanceApi) => void; +type DialogCloseHandler = () => void; +type DialogCancelHandler = (api: DialogInstanceApi) => void; +type DialogTabChangeHandler = (api: DialogInstanceApi, details: DialogTabChangeDetails) => void; +type DialogSize = 'normal' | 'medium' | 'large'; +interface DialogSpec { + title: string; + size?: DialogSize; + body: TabPanelSpec | PanelSpec; + buttons?: DialogFooterButtonSpec[]; + initialData?: Partial; + onAction?: DialogActionHandler; + onChange?: DialogChangeHandler; + onSubmit?: DialogSubmitHandler; + onClose?: DialogCloseHandler; + onCancel?: DialogCancelHandler; + onTabChange?: DialogTabChangeHandler; +} +interface UrlDialogInstanceApi { + block: (msg: string) => void; + unblock: () => void; + close: () => void; + sendMessage: (msg: any) => void; +} +interface UrlDialogActionDetails { + name: string; + value?: any; +} +interface UrlDialogMessage { + mceAction: string; + [key: string]: any; +} +type UrlDialogActionHandler = (api: UrlDialogInstanceApi, actions: UrlDialogActionDetails) => void; +type UrlDialogCloseHandler = () => void; +type UrlDialogCancelHandler = (api: UrlDialogInstanceApi) => void; +type UrlDialogMessageHandler = (api: UrlDialogInstanceApi, message: UrlDialogMessage) => void; +interface UrlDialogFooterButtonSpec extends DialogFooterNormalButtonSpec { + type: 'cancel' | 'custom'; +} +interface UrlDialogSpec { + title: string; + url: string; + height?: number; + width?: number; + buttons?: UrlDialogFooterButtonSpec[]; + onAction?: UrlDialogActionHandler; + onClose?: UrlDialogCloseHandler; + onCancel?: UrlDialogCancelHandler; + onMessage?: UrlDialogMessageHandler; +} +type ColumnTypes = number | 'auto'; +type SeparatorItemSpec = SeparatorMenuItemSpec; +interface AutocompleterItemSpec { + type?: 'autocompleteitem'; + value: string; + text?: string; + icon?: string; + meta?: Record; +} +type AutocompleterContents = SeparatorItemSpec | AutocompleterItemSpec | CardMenuItemSpec; +interface AutocompleterSpec { + type?: 'autocompleter'; + trigger: string; + minChars?: number; + columns?: ColumnTypes; + matches?: (rng: Range, text: string, pattern: string) => boolean; + fetch: (pattern: string, maxResults: number, fetchOptions: Record) => Promise; + onAction: (autocompleterApi: AutocompleterInstanceApi, rng: Range, value: string, meta: Record) => void; + maxResults?: number; + highlightOn?: string[]; +} +interface AutocompleterInstanceApi { + hide: () => void; + reload: (fetchOptions: Record) => void; +} +type ContextPosition = 'node' | 'selection' | 'line'; +type ContextScope = 'node' | 'editor'; +interface ContextBarSpec { + predicate?: (elem: Element) => boolean; + position?: ContextPosition; + scope?: ContextScope; +} +interface ContextFormLaunchButtonApi extends BaseToolbarButtonSpec { + type: 'contextformbutton'; +} +interface ContextFormLaunchToggleButtonSpec extends BaseToolbarToggleButtonSpec { + type: 'contextformtogglebutton'; +} +interface ContextFormButtonInstanceApi extends BaseToolbarButtonInstanceApi { +} +interface ContextFormToggleButtonInstanceApi extends BaseToolbarToggleButtonInstanceApi { +} +interface ContextFormButtonSpec extends BaseToolbarButtonSpec { + type?: 'contextformbutton'; + primary?: boolean; + align?: 'start' | 'end'; + onAction: (formApi: ContextFormInstanceApi, api: ContextFormButtonInstanceApi) => void; +} +interface ContextFormToggleButtonSpec extends BaseToolbarToggleButtonSpec { + type?: 'contextformtogglebutton'; + primary?: boolean; + align?: 'start' | 'end'; + onAction: (formApi: ContextFormInstanceApi, buttonApi: ContextFormToggleButtonInstanceApi) => void; +} +interface ContextFormInstanceApi { + setInputEnabled: (state: boolean) => void; + isInputEnabled: () => boolean; + hide: () => void; + back: () => void; + getValue: () => T; + setValue: (value: T) => void; +} +interface SizeData { + width: string; + height: string; +} +interface BaseContextFormSpec extends ContextBarSpec { + initValue?: () => T; + label?: string; + launch?: ContextFormLaunchButtonApi | ContextFormLaunchToggleButtonSpec; + commands: Array | ContextFormButtonSpec>; + onInput?: (api: ContextFormInstanceApi) => void; + onSetup?: (api: ContextFormInstanceApi) => (api: ContextFormInstanceApi) => void; +} +interface ContextInputFormSpec extends BaseContextFormSpec { + type?: 'contextform'; + placeholder?: string; +} +interface ContextSliderFormSpec extends BaseContextFormSpec { + type: 'contextsliderform'; + min?: () => number; + max?: () => number; +} +interface ContextSizeInputFormSpec extends BaseContextFormSpec { + type: 'contextsizeinputform'; +} +type ContextFormSpec = ContextInputFormSpec | ContextSliderFormSpec | ContextSizeInputFormSpec; +interface ToolbarGroupSpec { + name?: string; + label?: string; + items: string[]; +} +interface ContextToolbarSpec extends ContextBarSpec { + type?: 'contexttoolbar'; + items: string | ToolbarGroupSpec[]; +} +type PublicDialog_d_AlertBannerSpec = AlertBannerSpec; +type PublicDialog_d_BarSpec = BarSpec; +type PublicDialog_d_BodyComponentSpec = BodyComponentSpec; +type PublicDialog_d_ButtonSpec = ButtonSpec; +type PublicDialog_d_CheckboxSpec = CheckboxSpec; +type PublicDialog_d_CollectionItem = CollectionItem; +type PublicDialog_d_CollectionSpec = CollectionSpec; +type PublicDialog_d_ColorInputSpec = ColorInputSpec; +type PublicDialog_d_ColorPickerSpec = ColorPickerSpec; +type PublicDialog_d_CustomEditorSpec = CustomEditorSpec; +type PublicDialog_d_CustomEditorInit = CustomEditorInit; +type PublicDialog_d_CustomEditorInitFn = CustomEditorInitFn; +type PublicDialog_d_DialogData = DialogData; +type PublicDialog_d_DialogSize = DialogSize; +type PublicDialog_d_DialogSpec = DialogSpec; +type PublicDialog_d_DialogInstanceApi = DialogInstanceApi; +type PublicDialog_d_DialogFooterButtonSpec = DialogFooterButtonSpec; +type PublicDialog_d_DialogActionDetails = DialogActionDetails; +type PublicDialog_d_DialogChangeDetails = DialogChangeDetails; +type PublicDialog_d_DialogTabChangeDetails = DialogTabChangeDetails; +type PublicDialog_d_DropZoneSpec = DropZoneSpec; +type PublicDialog_d_GridSpec = GridSpec; +type PublicDialog_d_HtmlPanelSpec = HtmlPanelSpec; +type PublicDialog_d_IframeSpec = IframeSpec; +type PublicDialog_d_ImagePreviewSpec = ImagePreviewSpec; +type PublicDialog_d_InputSpec = InputSpec; +type PublicDialog_d_LabelSpec = LabelSpec; +type PublicDialog_d_ListBoxSpec = ListBoxSpec; +type PublicDialog_d_ListBoxItemSpec = ListBoxItemSpec; +type PublicDialog_d_ListBoxNestedItemSpec = ListBoxNestedItemSpec; +type PublicDialog_d_ListBoxSingleItemSpec = ListBoxSingleItemSpec; +type PublicDialog_d_PanelSpec = PanelSpec; +type PublicDialog_d_SelectBoxSpec = SelectBoxSpec; +type PublicDialog_d_SelectBoxItemSpec = SelectBoxItemSpec; +type PublicDialog_d_SizeInputSpec = SizeInputSpec; +type PublicDialog_d_SliderSpec = SliderSpec; +type PublicDialog_d_TableSpec = TableSpec; +type PublicDialog_d_TabSpec = TabSpec; +type PublicDialog_d_TabPanelSpec = TabPanelSpec; +type PublicDialog_d_TextAreaSpec = TextAreaSpec; +type PublicDialog_d_TreeSpec = TreeSpec; +type PublicDialog_d_TreeItemSpec = TreeItemSpec; +type PublicDialog_d_UrlInputData = UrlInputData; +type PublicDialog_d_UrlInputSpec = UrlInputSpec; +type PublicDialog_d_UrlDialogSpec = UrlDialogSpec; +type PublicDialog_d_UrlDialogFooterButtonSpec = UrlDialogFooterButtonSpec; +type PublicDialog_d_UrlDialogInstanceApi = UrlDialogInstanceApi; +type PublicDialog_d_UrlDialogActionDetails = UrlDialogActionDetails; +type PublicDialog_d_UrlDialogMessage = UrlDialogMessage; +declare namespace PublicDialog_d { + export { PublicDialog_d_AlertBannerSpec as AlertBannerSpec, PublicDialog_d_BarSpec as BarSpec, PublicDialog_d_BodyComponentSpec as BodyComponentSpec, PublicDialog_d_ButtonSpec as ButtonSpec, PublicDialog_d_CheckboxSpec as CheckboxSpec, PublicDialog_d_CollectionItem as CollectionItem, PublicDialog_d_CollectionSpec as CollectionSpec, PublicDialog_d_ColorInputSpec as ColorInputSpec, PublicDialog_d_ColorPickerSpec as ColorPickerSpec, PublicDialog_d_CustomEditorSpec as CustomEditorSpec, PublicDialog_d_CustomEditorInit as CustomEditorInit, PublicDialog_d_CustomEditorInitFn as CustomEditorInitFn, PublicDialog_d_DialogData as DialogData, PublicDialog_d_DialogSize as DialogSize, PublicDialog_d_DialogSpec as DialogSpec, PublicDialog_d_DialogInstanceApi as DialogInstanceApi, PublicDialog_d_DialogFooterButtonSpec as DialogFooterButtonSpec, PublicDialog_d_DialogActionDetails as DialogActionDetails, PublicDialog_d_DialogChangeDetails as DialogChangeDetails, PublicDialog_d_DialogTabChangeDetails as DialogTabChangeDetails, PublicDialog_d_DropZoneSpec as DropZoneSpec, PublicDialog_d_GridSpec as GridSpec, PublicDialog_d_HtmlPanelSpec as HtmlPanelSpec, PublicDialog_d_IframeSpec as IframeSpec, PublicDialog_d_ImagePreviewSpec as ImagePreviewSpec, PublicDialog_d_InputSpec as InputSpec, PublicDialog_d_LabelSpec as LabelSpec, PublicDialog_d_ListBoxSpec as ListBoxSpec, PublicDialog_d_ListBoxItemSpec as ListBoxItemSpec, PublicDialog_d_ListBoxNestedItemSpec as ListBoxNestedItemSpec, PublicDialog_d_ListBoxSingleItemSpec as ListBoxSingleItemSpec, PublicDialog_d_PanelSpec as PanelSpec, PublicDialog_d_SelectBoxSpec as SelectBoxSpec, PublicDialog_d_SelectBoxItemSpec as SelectBoxItemSpec, PublicDialog_d_SizeInputSpec as SizeInputSpec, PublicDialog_d_SliderSpec as SliderSpec, PublicDialog_d_TableSpec as TableSpec, PublicDialog_d_TabSpec as TabSpec, PublicDialog_d_TabPanelSpec as TabPanelSpec, PublicDialog_d_TextAreaSpec as TextAreaSpec, PublicDialog_d_TreeSpec as TreeSpec, PublicDialog_d_TreeItemSpec as TreeItemSpec, DirectorySpec as TreeDirectorySpec, LeafSpec as TreeLeafSpec, PublicDialog_d_UrlInputData as UrlInputData, PublicDialog_d_UrlInputSpec as UrlInputSpec, PublicDialog_d_UrlDialogSpec as UrlDialogSpec, PublicDialog_d_UrlDialogFooterButtonSpec as UrlDialogFooterButtonSpec, PublicDialog_d_UrlDialogInstanceApi as UrlDialogInstanceApi, PublicDialog_d_UrlDialogActionDetails as UrlDialogActionDetails, PublicDialog_d_UrlDialogMessage as UrlDialogMessage, }; +} +type PublicInlineContent_d_AutocompleterSpec = AutocompleterSpec; +type PublicInlineContent_d_AutocompleterItemSpec = AutocompleterItemSpec; +type PublicInlineContent_d_AutocompleterContents = AutocompleterContents; +type PublicInlineContent_d_AutocompleterInstanceApi = AutocompleterInstanceApi; +type PublicInlineContent_d_ContextPosition = ContextPosition; +type PublicInlineContent_d_ContextScope = ContextScope; +type PublicInlineContent_d_ContextFormSpec = ContextFormSpec; +type PublicInlineContent_d_ContextFormInstanceApi = ContextFormInstanceApi; +type PublicInlineContent_d_ContextFormButtonSpec = ContextFormButtonSpec; +type PublicInlineContent_d_ContextFormButtonInstanceApi = ContextFormButtonInstanceApi; +type PublicInlineContent_d_ContextFormToggleButtonSpec = ContextFormToggleButtonSpec; +type PublicInlineContent_d_ContextFormToggleButtonInstanceApi = ContextFormToggleButtonInstanceApi; +type PublicInlineContent_d_ContextToolbarSpec = ContextToolbarSpec; +type PublicInlineContent_d_SeparatorItemSpec = SeparatorItemSpec; +declare namespace PublicInlineContent_d { + export { PublicInlineContent_d_AutocompleterSpec as AutocompleterSpec, PublicInlineContent_d_AutocompleterItemSpec as AutocompleterItemSpec, PublicInlineContent_d_AutocompleterContents as AutocompleterContents, PublicInlineContent_d_AutocompleterInstanceApi as AutocompleterInstanceApi, PublicInlineContent_d_ContextPosition as ContextPosition, PublicInlineContent_d_ContextScope as ContextScope, PublicInlineContent_d_ContextFormSpec as ContextFormSpec, PublicInlineContent_d_ContextFormInstanceApi as ContextFormInstanceApi, PublicInlineContent_d_ContextFormButtonSpec as ContextFormButtonSpec, PublicInlineContent_d_ContextFormButtonInstanceApi as ContextFormButtonInstanceApi, PublicInlineContent_d_ContextFormToggleButtonSpec as ContextFormToggleButtonSpec, PublicInlineContent_d_ContextFormToggleButtonInstanceApi as ContextFormToggleButtonInstanceApi, PublicInlineContent_d_ContextToolbarSpec as ContextToolbarSpec, PublicInlineContent_d_SeparatorItemSpec as SeparatorItemSpec, }; +} +type PublicMenu_d_MenuItemSpec = MenuItemSpec; +type PublicMenu_d_MenuItemInstanceApi = MenuItemInstanceApi; +type PublicMenu_d_NestedMenuItemContents = NestedMenuItemContents; +type PublicMenu_d_NestedMenuItemSpec = NestedMenuItemSpec; +type PublicMenu_d_NestedMenuItemInstanceApi = NestedMenuItemInstanceApi; +type PublicMenu_d_FancyMenuItemSpec = FancyMenuItemSpec; +type PublicMenu_d_ColorSwatchMenuItemSpec = ColorSwatchMenuItemSpec; +type PublicMenu_d_InsertTableMenuItemSpec = InsertTableMenuItemSpec; +type PublicMenu_d_ToggleMenuItemSpec = ToggleMenuItemSpec; +type PublicMenu_d_ToggleMenuItemInstanceApi = ToggleMenuItemInstanceApi; +type PublicMenu_d_ChoiceMenuItemSpec = ChoiceMenuItemSpec; +type PublicMenu_d_ChoiceMenuItemInstanceApi = ChoiceMenuItemInstanceApi; +type PublicMenu_d_SeparatorMenuItemSpec = SeparatorMenuItemSpec; +type PublicMenu_d_ContextMenuApi = ContextMenuApi; +type PublicMenu_d_ContextMenuContents = ContextMenuContents; +type PublicMenu_d_ContextMenuItem = ContextMenuItem; +type PublicMenu_d_ContextSubMenu = ContextSubMenu; +type PublicMenu_d_CardMenuItemSpec = CardMenuItemSpec; +type PublicMenu_d_CardMenuItemInstanceApi = CardMenuItemInstanceApi; +type PublicMenu_d_CardItemSpec = CardItemSpec; +type PublicMenu_d_CardContainerSpec = CardContainerSpec; +type PublicMenu_d_CardImageSpec = CardImageSpec; +type PublicMenu_d_CardTextSpec = CardTextSpec; +declare namespace PublicMenu_d { + export { PublicMenu_d_MenuItemSpec as MenuItemSpec, PublicMenu_d_MenuItemInstanceApi as MenuItemInstanceApi, PublicMenu_d_NestedMenuItemContents as NestedMenuItemContents, PublicMenu_d_NestedMenuItemSpec as NestedMenuItemSpec, PublicMenu_d_NestedMenuItemInstanceApi as NestedMenuItemInstanceApi, PublicMenu_d_FancyMenuItemSpec as FancyMenuItemSpec, PublicMenu_d_ColorSwatchMenuItemSpec as ColorSwatchMenuItemSpec, PublicMenu_d_InsertTableMenuItemSpec as InsertTableMenuItemSpec, PublicMenu_d_ToggleMenuItemSpec as ToggleMenuItemSpec, PublicMenu_d_ToggleMenuItemInstanceApi as ToggleMenuItemInstanceApi, PublicMenu_d_ChoiceMenuItemSpec as ChoiceMenuItemSpec, PublicMenu_d_ChoiceMenuItemInstanceApi as ChoiceMenuItemInstanceApi, PublicMenu_d_SeparatorMenuItemSpec as SeparatorMenuItemSpec, PublicMenu_d_ContextMenuApi as ContextMenuApi, PublicMenu_d_ContextMenuContents as ContextMenuContents, PublicMenu_d_ContextMenuItem as ContextMenuItem, PublicMenu_d_ContextSubMenu as ContextSubMenu, PublicMenu_d_CardMenuItemSpec as CardMenuItemSpec, PublicMenu_d_CardMenuItemInstanceApi as CardMenuItemInstanceApi, PublicMenu_d_CardItemSpec as CardItemSpec, PublicMenu_d_CardContainerSpec as CardContainerSpec, PublicMenu_d_CardImageSpec as CardImageSpec, PublicMenu_d_CardTextSpec as CardTextSpec, }; +} +interface SidebarInstanceApi { + element: () => HTMLElement; +} +interface SidebarSpec { + icon?: string; + tooltip?: string; + onShow?: (api: SidebarInstanceApi) => void; + onSetup?: (api: SidebarInstanceApi) => (api: SidebarInstanceApi) => void; + onHide?: (api: SidebarInstanceApi) => void; +} +type PublicSidebar_d_SidebarSpec = SidebarSpec; +type PublicSidebar_d_SidebarInstanceApi = SidebarInstanceApi; +declare namespace PublicSidebar_d { + export { PublicSidebar_d_SidebarSpec as SidebarSpec, PublicSidebar_d_SidebarInstanceApi as SidebarInstanceApi, }; +} +type PublicToolbar_d_ToolbarButtonSpec = ToolbarButtonSpec; +type PublicToolbar_d_ToolbarButtonInstanceApi = ToolbarButtonInstanceApi; +type PublicToolbar_d_ToolbarSplitButtonSpec = ToolbarSplitButtonSpec; +type PublicToolbar_d_ToolbarSplitButtonInstanceApi = ToolbarSplitButtonInstanceApi; +type PublicToolbar_d_ToolbarMenuButtonSpec = ToolbarMenuButtonSpec; +type PublicToolbar_d_ToolbarMenuButtonInstanceApi = ToolbarMenuButtonInstanceApi; +type PublicToolbar_d_ToolbarToggleButtonSpec = ToolbarToggleButtonSpec; +type PublicToolbar_d_ToolbarToggleButtonInstanceApi = ToolbarToggleButtonInstanceApi; +type PublicToolbar_d_GroupToolbarButtonSpec = GroupToolbarButtonSpec; +type PublicToolbar_d_GroupToolbarButtonInstanceApi = GroupToolbarButtonInstanceApi; +declare namespace PublicToolbar_d { + export { PublicToolbar_d_ToolbarButtonSpec as ToolbarButtonSpec, PublicToolbar_d_ToolbarButtonInstanceApi as ToolbarButtonInstanceApi, PublicToolbar_d_ToolbarSplitButtonSpec as ToolbarSplitButtonSpec, PublicToolbar_d_ToolbarSplitButtonInstanceApi as ToolbarSplitButtonInstanceApi, PublicToolbar_d_ToolbarMenuButtonSpec as ToolbarMenuButtonSpec, PublicToolbar_d_ToolbarMenuButtonInstanceApi as ToolbarMenuButtonInstanceApi, PublicToolbar_d_ToolbarToggleButtonSpec as ToolbarToggleButtonSpec, PublicToolbar_d_ToolbarToggleButtonInstanceApi as ToolbarToggleButtonInstanceApi, PublicToolbar_d_GroupToolbarButtonSpec as GroupToolbarButtonSpec, PublicToolbar_d_GroupToolbarButtonInstanceApi as GroupToolbarButtonInstanceApi, }; +} +interface ViewButtonApi { + setIcon: (newIcon: string) => void; +} +interface ViewToggleButtonApi extends ViewButtonApi { + isActive: () => boolean; + setActive: (state: boolean) => void; + focus: () => void; +} +interface BaseButtonSpec { + text?: string; + icon?: string; + tooltip?: string; + buttonType?: 'primary' | 'secondary'; + borderless?: boolean; + onAction: (api: Api) => void; + context?: string; +} +interface ViewNormalButtonSpec extends BaseButtonSpec { + text: string; + type: 'button'; +} +interface ViewToggleButtonSpec extends BaseButtonSpec { + type: 'togglebutton'; + active?: boolean; + onAction: (api: ViewToggleButtonApi) => void; +} +interface ViewButtonsGroupSpec { + type: 'group'; + buttons: Array; +} +type ViewButtonSpec = ViewNormalButtonSpec | ViewToggleButtonSpec | ViewButtonsGroupSpec; +interface ViewInstanceApi { + getContainer: () => HTMLElement; +} +interface ViewSpec { + buttons?: ViewButtonSpec[]; + onShow: (api: ViewInstanceApi) => void; + onHide: (api: ViewInstanceApi) => void; +} +type PublicView_d_ViewSpec = ViewSpec; +type PublicView_d_ViewInstanceApi = ViewInstanceApi; +declare namespace PublicView_d { + export { PublicView_d_ViewSpec as ViewSpec, PublicView_d_ViewInstanceApi as ViewInstanceApi, }; +} +interface Registry$1 { + addButton: (name: string, spec: ToolbarButtonSpec) => void; + addGroupToolbarButton: (name: string, spec: GroupToolbarButtonSpec) => void; + addToggleButton: (name: string, spec: ToolbarToggleButtonSpec) => void; + addMenuButton: (name: string, spec: ToolbarMenuButtonSpec) => void; + addSplitButton: (name: string, spec: ToolbarSplitButtonSpec) => void; + addMenuItem: (name: string, spec: MenuItemSpec) => void; + addNestedMenuItem: (name: string, spec: NestedMenuItemSpec) => void; + addToggleMenuItem: (name: string, spec: ToggleMenuItemSpec) => void; + addContextMenu: (name: string, spec: ContextMenuApi) => void; + addContextToolbar: (name: string, spec: ContextToolbarSpec) => void; + addContextForm: (name: string, spec: ContextFormSpec) => void; + addIcon: (name: string, svgData: string) => void; + addAutocompleter: (name: string, spec: AutocompleterSpec) => void; + addSidebar: (name: string, spec: SidebarSpec) => void; + addView: (name: string, spec: ViewSpec) => void; + addContext: (name: string, pred: (args: string) => boolean) => void; + getAll: () => { + buttons: Record; + menuItems: Record; + popups: Record; + contextMenus: Record; + contextToolbars: Record; + icons: Record; + sidebars: Record; + views: Record; + contexts: Record boolean>; + }; +} +interface AutocompleteLookupData { + readonly matchText: string; + readonly items: AutocompleterContents[]; + readonly columns: ColumnTypes; + readonly onAction: (autoApi: AutocompleterInstanceApi, rng: Range, value: string, meta: Record) => void; + readonly highlightOn: string[]; +} +interface AutocompleterEventArgs { + readonly lookupData: AutocompleteLookupData[]; +} +interface RangeLikeObject { + startContainer: Node; + startOffset: number; + endContainer: Node; + endOffset: number; +} +type ApplyFormat = BlockFormat | InlineFormat | SelectorFormat; +type RemoveFormat = RemoveBlockFormat | RemoveInlineFormat | RemoveSelectorFormat; +type Format = ApplyFormat | RemoveFormat; +type Formats = Record; +type FormatAttrOrStyleValue = string | ((vars?: FormatVars) => string | null); +type FormatVars = Record; +interface BaseFormat { + ceFalseOverride?: boolean; + classes?: string | string[]; + collapsed?: boolean; + exact?: boolean; + expand?: boolean; + links?: boolean; + mixed?: boolean; + block_expand?: boolean; + onmatch?: (node: Element, fmt: T, itemName: string) => boolean; + remove?: 'none' | 'empty' | 'all'; + remove_similar?: boolean; + split?: boolean; + deep?: boolean; + preserve_attributes?: string[]; +} +interface Block { + block: string; + list_block?: string; + wrapper?: boolean; +} +interface Inline { + inline: string; +} +interface Selector { + selector: string; + inherit?: boolean; +} +interface CommonFormat extends BaseFormat { + attributes?: Record; + styles?: Record; + toggle?: boolean; + preview?: string | false; + onformat?: (elm: Element, fmt: T, vars?: FormatVars, node?: Node | RangeLikeObject | null) => void; + clear_child_styles?: boolean; + merge_siblings?: boolean; + merge_with_parents?: boolean; +} +interface BlockFormat extends Block, CommonFormat { +} +interface InlineFormat extends Inline, CommonFormat { +} +interface SelectorFormat extends Selector, CommonFormat { +} +interface CommonRemoveFormat extends BaseFormat { + attributes?: string[] | Record; + styles?: string[] | Record; +} +interface RemoveBlockFormat extends Block, CommonRemoveFormat { +} +interface RemoveInlineFormat extends Inline, CommonRemoveFormat { +} +interface RemoveSelectorFormat extends Selector, CommonRemoveFormat { +} +interface Filter { + name: string; + callbacks: C[]; +} +interface ParserArgs { + getInner?: boolean | number; + forced_root_block?: boolean | string; + context?: string; + isRootContent?: boolean; + format?: string; + invalid?: boolean; + no_events?: boolean; + [key: string]: any; +} +type ParserFilterCallback = (nodes: AstNode[], name: string, args: ParserArgs) => void; +interface ParserFilter extends Filter { +} +interface DomParserSettings { + allow_html_data_urls?: boolean; + allow_svg_data_urls?: boolean; + allow_conditional_comments?: boolean; + allow_html_in_named_anchor?: boolean; + allow_script_urls?: boolean; + allow_unsafe_link_target?: boolean; + allow_mathml_annotation_encodings?: string[]; + blob_cache?: BlobCache; + convert_fonts_to_spans?: boolean; + convert_unsafe_embeds?: boolean; + document?: Document; + fix_list_elements?: boolean; + font_size_legacy_values?: string; + forced_root_block?: boolean | string; + forced_root_block_attrs?: Record; + inline_styles?: boolean; + pad_empty_with_br?: boolean; + preserve_cdata?: boolean; + root_name?: string; + sandbox_iframes?: boolean; + sandbox_iframes_exclusions?: string[]; + sanitize?: boolean; + validate?: boolean; +} +interface DomParser { + schema: Schema; + addAttributeFilter: (name: string, callback: ParserFilterCallback) => void; + getAttributeFilters: () => ParserFilter[]; + removeAttributeFilter: (name: string, callback?: ParserFilterCallback) => void; + addNodeFilter: (name: string, callback: ParserFilterCallback) => void; + getNodeFilters: () => ParserFilter[]; + removeNodeFilter: (name: string, callback?: ParserFilterCallback) => void; + parse: (html: string, args?: ParserArgs) => AstNode; +} +interface StyleSheetLoaderSettings { + maxLoadTime?: number; + contentCssCors?: boolean; + referrerPolicy?: ReferrerPolicy; +} +interface StyleSheetLoader { + load: (url: string) => Promise; + loadRawCss: (key: string, css: string) => void; + loadAll: (urls: string[]) => Promise; + unload: (url: string) => void; + unloadRawCss: (key: string) => void; + unloadAll: (urls: string[]) => void; + _setReferrerPolicy: (referrerPolicy: ReferrerPolicy) => void; + _setContentCssCors: (contentCssCors: boolean) => void; +} +type Registry = Registry$1; +interface EditorUiApi { + show: () => void; + hide: () => void; + setEnabled: (state: boolean) => void; + isEnabled: () => boolean; +} +interface EditorUi extends EditorUiApi { + registry: Registry; + styleSheetLoader: StyleSheetLoader; +} +type Ui_d_Registry = Registry; +type Ui_d_EditorUiApi = EditorUiApi; +type Ui_d_EditorUi = EditorUi; +declare namespace Ui_d { + export { Ui_d_Registry as Registry, PublicDialog_d as Dialog, PublicInlineContent_d as InlineContent, PublicMenu_d as Menu, PublicView_d as View, PublicSidebar_d as Sidebar, PublicToolbar_d as Toolbar, Ui_d_EditorUiApi as EditorUiApi, Ui_d_EditorUi as EditorUi, }; +} +interface WindowParams { + readonly inline?: 'cursor' | 'toolbar' | 'bottom'; + readonly ariaAttrs?: boolean; + readonly persistent?: boolean; +} +type InstanceApi = UrlDialogInstanceApi | DialogInstanceApi; +interface WindowManagerImpl { + open: (config: DialogSpec, params: WindowParams | undefined, closeWindow: (dialog: DialogInstanceApi) => void) => DialogInstanceApi; + openUrl: (config: UrlDialogSpec, closeWindow: (dialog: UrlDialogInstanceApi) => void) => UrlDialogInstanceApi; + alert: (message: string, callback: () => void) => void; + confirm: (message: string, callback: (state: boolean) => void) => void; + close: (dialog: InstanceApi) => void; +} +interface WindowManager { + open: (config: DialogSpec, params?: WindowParams) => DialogInstanceApi; + openUrl: (config: UrlDialogSpec) => UrlDialogInstanceApi; + alert: (message: string, callback?: () => void, scope?: any) => void; + confirm: (message: string, callback?: (state: boolean) => void, scope?: any) => void; + close: () => void; +} +interface ExecCommandEvent { + command: string; + ui: boolean; + value?: any; +} +interface BeforeGetContentEvent extends GetContentArgs { + selection?: boolean; +} +interface GetContentEvent extends BeforeGetContentEvent { + content: string; +} +interface BeforeSetContentEvent extends SetContentArgs { + content: string; + selection?: boolean; +} +interface SetContentEvent extends BeforeSetContentEvent { + content: string; +} +interface SaveContentEvent extends GetContentEvent { + save: boolean; +} +interface NewBlockEvent { + newBlock: Element; +} +interface NodeChangeEvent { + element: Element; + parents: Node[]; + selectionChange?: boolean; + initial?: boolean; +} +interface FormatEvent { + format: string; + vars?: FormatVars; + node?: Node | RangeLikeObject | null; +} +interface ObjectResizeEvent { + target: HTMLElement; + width: number; + height: number; + origin: string; +} +interface ObjectSelectedEvent { + target: Node; + targetClone?: Node; +} +interface ScrollIntoViewEvent { + elm: HTMLElement; + alignToTop: boolean | undefined; +} +interface SetSelectionRangeEvent { + range: Range; + forward: boolean | undefined; +} +interface ShowCaretEvent { + target: Node; + direction: number; + before: boolean; +} +interface SwitchModeEvent { + mode: string; +} +interface ChangeEvent { + level: UndoLevel; + lastLevel: UndoLevel | undefined; +} +interface AddUndoEvent extends ChangeEvent { + originalEvent: Event | undefined; +} +interface UndoRedoEvent { + level: UndoLevel; +} +interface WindowEvent { + dialog: InstanceApi; +} +interface ProgressStateEvent { + state: boolean; + time?: number; +} +interface AfterProgressStateEvent { + state: boolean; +} +interface PlaceholderToggleEvent { + state: boolean; +} +interface LoadErrorEvent { + message: string; +} +interface PreProcessEvent extends ParserArgs { + node: Element; +} +interface PostProcessEvent extends ParserArgs { + content: string; +} +interface PastePlainTextToggleEvent { + state: boolean; +} +interface PastePreProcessEvent { + content: string; + readonly internal: boolean; +} +interface PastePostProcessEvent { + node: HTMLElement; + readonly internal: boolean; +} +interface EditableRootStateChangeEvent { + state: boolean; +} +interface NewTableRowEvent { + node: HTMLTableRowElement; +} +interface NewTableCellEvent { + node: HTMLTableCellElement; +} +interface TableEventData { + readonly structure: boolean; + readonly style: boolean; +} +interface TableModifiedEvent extends TableEventData { + readonly table: HTMLTableElement; +} +interface BeforeOpenNotificationEvent { + notification: NotificationSpec; +} +interface OpenNotificationEvent { + notification: NotificationApi; +} +interface DisabledStateChangeEvent { + readonly state: boolean; +} +interface EditorEventMap extends Omit { + 'activate': { + relatedTarget: Editor | null; + }; + 'deactivate': { + relatedTarget: Editor; + }; + 'focus': { + blurredEditor: Editor | null; + }; + 'blur': { + focusedEditor: Editor | null; + }; + 'resize': UIEvent; + 'scroll': UIEvent; + 'input': InputEvent; + 'beforeinput': InputEvent; + 'detach': {}; + 'remove': {}; + 'init': {}; + 'ScrollIntoView': ScrollIntoViewEvent; + 'AfterScrollIntoView': ScrollIntoViewEvent; + 'ObjectResized': ObjectResizeEvent; + 'ObjectResizeStart': ObjectResizeEvent; + 'SwitchMode': SwitchModeEvent; + 'ScrollWindow': Event; + 'ResizeWindow': UIEvent; + 'SkinLoaded': {}; + 'SkinLoadError': LoadErrorEvent; + 'PluginLoadError': LoadErrorEvent; + 'ModelLoadError': LoadErrorEvent; + 'IconsLoadError': LoadErrorEvent; + 'ThemeLoadError': LoadErrorEvent; + 'LanguageLoadError': LoadErrorEvent; + 'BeforeExecCommand': ExecCommandEvent; + 'ExecCommand': ExecCommandEvent; + 'NodeChange': NodeChangeEvent; + 'FormatApply': FormatEvent; + 'FormatRemove': FormatEvent; + 'ShowCaret': ShowCaretEvent; + 'SelectionChange': {}; + 'ObjectSelected': ObjectSelectedEvent; + 'BeforeObjectSelected': ObjectSelectedEvent; + 'GetSelectionRange': { + range: Range; + }; + 'SetSelectionRange': SetSelectionRangeEvent; + 'AfterSetSelectionRange': SetSelectionRangeEvent; + 'BeforeGetContent': BeforeGetContentEvent; + 'GetContent': GetContentEvent; + 'BeforeSetContent': BeforeSetContentEvent; + 'SetContent': SetContentEvent; + 'SaveContent': SaveContentEvent; + 'RawSaveContent': SaveContentEvent; + 'LoadContent': { + load: boolean; + element: HTMLElement; + }; + 'PreviewFormats': {}; + 'AfterPreviewFormats': {}; + 'ScriptsLoaded': {}; + 'PreInit': {}; + 'PostRender': {}; + 'NewBlock': NewBlockEvent; + 'ClearUndos': {}; + 'TypingUndo': {}; + 'Redo': UndoRedoEvent; + 'Undo': UndoRedoEvent; + 'BeforeAddUndo': AddUndoEvent; + 'AddUndo': AddUndoEvent; + 'change': ChangeEvent; + 'CloseWindow': WindowEvent; + 'OpenWindow': WindowEvent; + 'ProgressState': ProgressStateEvent; + 'AfterProgressState': AfterProgressStateEvent; + 'PlaceholderToggle': PlaceholderToggleEvent; + 'tap': TouchEvent; + 'longpress': TouchEvent; + 'longpresscancel': {}; + 'PreProcess': PreProcessEvent; + 'PostProcess': PostProcessEvent; + 'AutocompleterStart': AutocompleterEventArgs; + 'AutocompleterUpdate': AutocompleterEventArgs; + 'AutocompleterEnd': {}; + 'PastePlainTextToggle': PastePlainTextToggleEvent; + 'PastePreProcess': PastePreProcessEvent; + 'PastePostProcess': PastePostProcessEvent; + 'TableModified': TableModifiedEvent; + 'NewRow': NewTableRowEvent; + 'NewCell': NewTableCellEvent; + 'SetAttrib': SetAttribEvent; + 'hide': {}; + 'show': {}; + 'dirty': {}; + 'BeforeOpenNotification': BeforeOpenNotificationEvent; + 'OpenNotification': OpenNotificationEvent; +} +interface EditorManagerEventMap { + 'AddEditor': { + editor: Editor; + }; + 'RemoveEditor': { + editor: Editor; + }; + 'BeforeUnload': { + returnValue: any; + }; +} +type EventTypes_d_ExecCommandEvent = ExecCommandEvent; +type EventTypes_d_BeforeGetContentEvent = BeforeGetContentEvent; +type EventTypes_d_GetContentEvent = GetContentEvent; +type EventTypes_d_BeforeSetContentEvent = BeforeSetContentEvent; +type EventTypes_d_SetContentEvent = SetContentEvent; +type EventTypes_d_SaveContentEvent = SaveContentEvent; +type EventTypes_d_NewBlockEvent = NewBlockEvent; +type EventTypes_d_NodeChangeEvent = NodeChangeEvent; +type EventTypes_d_FormatEvent = FormatEvent; +type EventTypes_d_ObjectResizeEvent = ObjectResizeEvent; +type EventTypes_d_ObjectSelectedEvent = ObjectSelectedEvent; +type EventTypes_d_ScrollIntoViewEvent = ScrollIntoViewEvent; +type EventTypes_d_SetSelectionRangeEvent = SetSelectionRangeEvent; +type EventTypes_d_ShowCaretEvent = ShowCaretEvent; +type EventTypes_d_SwitchModeEvent = SwitchModeEvent; +type EventTypes_d_ChangeEvent = ChangeEvent; +type EventTypes_d_AddUndoEvent = AddUndoEvent; +type EventTypes_d_UndoRedoEvent = UndoRedoEvent; +type EventTypes_d_WindowEvent = WindowEvent; +type EventTypes_d_ProgressStateEvent = ProgressStateEvent; +type EventTypes_d_AfterProgressStateEvent = AfterProgressStateEvent; +type EventTypes_d_PlaceholderToggleEvent = PlaceholderToggleEvent; +type EventTypes_d_LoadErrorEvent = LoadErrorEvent; +type EventTypes_d_PreProcessEvent = PreProcessEvent; +type EventTypes_d_PostProcessEvent = PostProcessEvent; +type EventTypes_d_PastePlainTextToggleEvent = PastePlainTextToggleEvent; +type EventTypes_d_PastePreProcessEvent = PastePreProcessEvent; +type EventTypes_d_PastePostProcessEvent = PastePostProcessEvent; +type EventTypes_d_EditableRootStateChangeEvent = EditableRootStateChangeEvent; +type EventTypes_d_NewTableRowEvent = NewTableRowEvent; +type EventTypes_d_NewTableCellEvent = NewTableCellEvent; +type EventTypes_d_TableEventData = TableEventData; +type EventTypes_d_TableModifiedEvent = TableModifiedEvent; +type EventTypes_d_BeforeOpenNotificationEvent = BeforeOpenNotificationEvent; +type EventTypes_d_OpenNotificationEvent = OpenNotificationEvent; +type EventTypes_d_DisabledStateChangeEvent = DisabledStateChangeEvent; +type EventTypes_d_EditorEventMap = EditorEventMap; +type EventTypes_d_EditorManagerEventMap = EditorManagerEventMap; +declare namespace EventTypes_d { + export { EventTypes_d_ExecCommandEvent as ExecCommandEvent, EventTypes_d_BeforeGetContentEvent as BeforeGetContentEvent, EventTypes_d_GetContentEvent as GetContentEvent, EventTypes_d_BeforeSetContentEvent as BeforeSetContentEvent, EventTypes_d_SetContentEvent as SetContentEvent, EventTypes_d_SaveContentEvent as SaveContentEvent, EventTypes_d_NewBlockEvent as NewBlockEvent, EventTypes_d_NodeChangeEvent as NodeChangeEvent, EventTypes_d_FormatEvent as FormatEvent, EventTypes_d_ObjectResizeEvent as ObjectResizeEvent, EventTypes_d_ObjectSelectedEvent as ObjectSelectedEvent, EventTypes_d_ScrollIntoViewEvent as ScrollIntoViewEvent, EventTypes_d_SetSelectionRangeEvent as SetSelectionRangeEvent, EventTypes_d_ShowCaretEvent as ShowCaretEvent, EventTypes_d_SwitchModeEvent as SwitchModeEvent, EventTypes_d_ChangeEvent as ChangeEvent, EventTypes_d_AddUndoEvent as AddUndoEvent, EventTypes_d_UndoRedoEvent as UndoRedoEvent, EventTypes_d_WindowEvent as WindowEvent, EventTypes_d_ProgressStateEvent as ProgressStateEvent, EventTypes_d_AfterProgressStateEvent as AfterProgressStateEvent, EventTypes_d_PlaceholderToggleEvent as PlaceholderToggleEvent, EventTypes_d_LoadErrorEvent as LoadErrorEvent, EventTypes_d_PreProcessEvent as PreProcessEvent, EventTypes_d_PostProcessEvent as PostProcessEvent, EventTypes_d_PastePlainTextToggleEvent as PastePlainTextToggleEvent, EventTypes_d_PastePreProcessEvent as PastePreProcessEvent, EventTypes_d_PastePostProcessEvent as PastePostProcessEvent, EventTypes_d_EditableRootStateChangeEvent as EditableRootStateChangeEvent, EventTypes_d_NewTableRowEvent as NewTableRowEvent, EventTypes_d_NewTableCellEvent as NewTableCellEvent, EventTypes_d_TableEventData as TableEventData, EventTypes_d_TableModifiedEvent as TableModifiedEvent, EventTypes_d_BeforeOpenNotificationEvent as BeforeOpenNotificationEvent, EventTypes_d_OpenNotificationEvent as OpenNotificationEvent, EventTypes_d_DisabledStateChangeEvent as DisabledStateChangeEvent, EventTypes_d_EditorEventMap as EditorEventMap, EventTypes_d_EditorManagerEventMap as EditorManagerEventMap, }; +} +type Format_d_Formats = Formats; +type Format_d_Format = Format; +type Format_d_ApplyFormat = ApplyFormat; +type Format_d_BlockFormat = BlockFormat; +type Format_d_InlineFormat = InlineFormat; +type Format_d_SelectorFormat = SelectorFormat; +type Format_d_RemoveFormat = RemoveFormat; +type Format_d_RemoveBlockFormat = RemoveBlockFormat; +type Format_d_RemoveInlineFormat = RemoveInlineFormat; +type Format_d_RemoveSelectorFormat = RemoveSelectorFormat; +declare namespace Format_d { + export { Format_d_Formats as Formats, Format_d_Format as Format, Format_d_ApplyFormat as ApplyFormat, Format_d_BlockFormat as BlockFormat, Format_d_InlineFormat as InlineFormat, Format_d_SelectorFormat as SelectorFormat, Format_d_RemoveFormat as RemoveFormat, Format_d_RemoveBlockFormat as RemoveBlockFormat, Format_d_RemoveInlineFormat as RemoveInlineFormat, Format_d_RemoveSelectorFormat as RemoveSelectorFormat, }; +} +type StyleFormat = BlockStyleFormat | InlineStyleFormat | SelectorStyleFormat; +type AllowedFormat = Separator | FormatReference | StyleFormat | NestedFormatting; +interface Separator { + title: string; +} +interface FormatReference { + title: string; + format: string; + icon?: string; +} +interface NestedFormatting { + title: string; + items: Array; +} +interface CommonStyleFormat { + name?: string; + title: string; + icon?: string; +} +interface BlockStyleFormat extends BlockFormat, CommonStyleFormat { +} +interface InlineStyleFormat extends InlineFormat, CommonStyleFormat { +} +interface SelectorStyleFormat extends SelectorFormat, CommonStyleFormat { +} +type EntityEncoding = 'named' | 'numeric' | 'raw' | 'named,numeric' | 'named+numeric' | 'numeric,named' | 'numeric+named'; +interface ContentLanguage { + readonly title: string; + readonly code: string; + readonly customCode?: string; +} +type ThemeInitFunc = (editor: Editor, elm: HTMLElement) => { + editorContainer: HTMLElement; + iframeContainer: HTMLElement; + height?: number; + iframeHeight?: number; + api?: EditorUiApi; +}; +type SetupCallback = (editor: Editor) => void; +type FilePickerCallback = (callback: (value: string, meta?: Record) => void, value: string, meta: Record) => void; +type FilePickerValidationStatus = 'valid' | 'unknown' | 'invalid' | 'none'; +type FilePickerValidationCallback = (info: { + type: string; + url: string; +}, callback: (validation: { + status: FilePickerValidationStatus; + message: string; +}) => void) => void; +type PastePreProcessFn = (editor: Editor, args: PastePreProcessEvent) => void; +type PastePostProcessFn = (editor: Editor, args: PastePostProcessEvent) => void; +type URLConverter = (url: string, name: string, elm?: string | Element) => string; +type URLConverterCallback = (url: string, node: Node | string | undefined, on_save: boolean, name: string) => string; +interface ToolbarGroup { + name?: string; + label?: string; + items: string[]; +} +type ToolbarMode = 'floating' | 'sliding' | 'scrolling' | 'wrap'; +type ToolbarLocation = 'top' | 'bottom' | 'auto'; +interface BaseEditorOptions { + a11y_advanced_options?: boolean; + add_form_submit_trigger?: boolean; + add_unload_trigger?: boolean; + allow_conditional_comments?: boolean; + allow_html_data_urls?: boolean; + allow_html_in_named_anchor?: boolean; + allow_script_urls?: boolean; + allow_svg_data_urls?: boolean; + allow_unsafe_link_target?: boolean; + anchor_bottom?: false | string; + anchor_top?: false | string; + auto_focus?: string | true; + automatic_uploads?: boolean; + base_url?: string; + block_formats?: string; + block_unsupported_drop?: boolean; + body_id?: string; + body_class?: string; + br_in_pre?: boolean; + br_newline_selector?: string; + browser_spellcheck?: boolean; + branding?: boolean; + cache_suffix?: string; + color_cols?: number; + color_cols_foreground?: number; + color_cols_background?: number; + color_map?: string[]; + color_map_foreground?: string[]; + color_map_background?: string[]; + color_default_foreground?: string; + color_default_background?: string; + content_css?: boolean | string | string[]; + content_css_cors?: boolean; + content_security_policy?: string; + content_style?: string; + content_langs?: ContentLanguage[]; + contextmenu?: string | string[] | false; + contextmenu_never_use_native?: boolean; + convert_fonts_to_spans?: boolean; + convert_unsafe_embeds?: boolean; + convert_urls?: boolean; + custom_colors?: boolean; + custom_elements?: string | Record; + custom_ui_selector?: string; + custom_undo_redo_levels?: number; + default_font_stack?: string[]; + deprecation_warnings?: boolean; + directionality?: 'ltr' | 'rtl'; + doctype?: string; + document_base_url?: string; + draggable_modal?: boolean; + editable_class?: string; + editable_root?: boolean; + element_format?: 'xhtml' | 'html'; + elementpath?: boolean; + encoding?: string; + end_container_on_empty_block?: boolean | string; + entities?: string; + entity_encoding?: EntityEncoding; + extended_valid_elements?: string; + event_root?: string; + file_picker_callback?: FilePickerCallback; + file_picker_types?: string; + file_picker_validator_handler?: FilePickerValidationCallback; + fix_list_elements?: boolean; + fixed_toolbar_container?: string; + fixed_toolbar_container_target?: HTMLElement; + font_css?: string | string[]; + font_family_formats?: string; + font_size_classes?: string; + font_size_legacy_values?: string; + font_size_style_values?: string; + font_size_formats?: string; + font_size_input_default_unit?: string; + forced_root_block?: string; + forced_root_block_attrs?: Record; + formats?: Formats; + format_noneditable_selector?: string; + height?: number | string; + help_accessibility?: boolean; + hidden_input?: boolean; + highlight_on_focus?: boolean; + icons?: string; + icons_url?: string; + id?: string; + iframe_aria_text?: string; + iframe_attrs?: Record; + images_file_types?: string; + images_replace_blob_uris?: boolean; + images_reuse_filename?: boolean; + images_upload_base_path?: string; + images_upload_credentials?: boolean; + images_upload_handler?: UploadHandler; + images_upload_url?: string; + indent?: boolean; + indent_after?: string; + indent_before?: string; + indent_use_margin?: boolean; + indentation?: string; + init_instance_callback?: SetupCallback; + inline?: boolean; + inline_boundaries?: boolean; + inline_boundaries_selector?: string; + inline_styles?: boolean; + invalid_elements?: string; + invalid_styles?: string | Record; + keep_styles?: boolean; + language?: string; + language_load?: boolean; + language_url?: string; + line_height_formats?: string; + max_height?: number; + max_width?: number; + menu?: Record; + menubar?: boolean | string; + min_height?: number; + min_width?: number; + model?: string; + model_url?: string; + newdocument_content?: string; + newline_behavior?: 'block' | 'linebreak' | 'invert' | 'default'; + no_newline_selector?: string; + noneditable_class?: string; + noneditable_regexp?: RegExp | RegExp[]; + nowrap?: boolean; + object_resizing?: boolean | string; + pad_empty_with_br?: boolean; + paste_as_text?: boolean; + paste_block_drop?: boolean; + paste_data_images?: boolean; + paste_merge_formats?: boolean; + paste_postprocess?: PastePostProcessFn; + paste_preprocess?: PastePreProcessFn; + paste_remove_styles_if_webkit?: boolean; + paste_tab_spaces?: number; + paste_webkit_styles?: string; + placeholder?: string; + preserve_cdata?: boolean; + preview_styles?: false | string; + promotion?: boolean; + protect?: RegExp[]; + readonly?: boolean; + referrer_policy?: ReferrerPolicy; + relative_urls?: boolean; + remove_script_host?: boolean; + remove_trailing_brs?: boolean; + removed_menuitems?: string; + resize?: boolean | 'both'; + resize_img_proportional?: boolean; + root_name?: string; + sandbox_iframes?: boolean; + sandbox_iframes_exclusions?: string[]; + schema?: SchemaType; + selector?: string; + setup?: SetupCallback; + sidebar_show?: string; + skin?: boolean | string; + skin_url?: string; + smart_paste?: boolean; + statusbar?: boolean; + style_formats?: AllowedFormat[]; + style_formats_autohide?: boolean; + style_formats_merge?: boolean; + submit_patch?: boolean; + suffix?: string; + table_tab_navigation?: boolean; + target?: HTMLElement; + text_patterns?: RawPattern[] | false; + text_patterns_lookup?: RawDynamicPatternsLookup; + theme?: string | ThemeInitFunc | false; + theme_url?: string; + toolbar?: boolean | string | string[] | Array; + toolbar1?: string; + toolbar2?: string; + toolbar3?: string; + toolbar4?: string; + toolbar5?: string; + toolbar6?: string; + toolbar7?: string; + toolbar8?: string; + toolbar9?: string; + toolbar_groups?: Record; + toolbar_location?: ToolbarLocation; + toolbar_mode?: ToolbarMode; + toolbar_sticky?: boolean; + toolbar_sticky_offset?: number; + typeahead_urls?: boolean; + ui_mode?: 'combined' | 'split'; + url_converter?: URLConverter; + url_converter_scope?: any; + urlconverter_callback?: URLConverterCallback; + valid_children?: string; + valid_classes?: string | Record; + valid_elements?: string; + valid_styles?: string | Record; + verify_html?: boolean; + visual?: boolean; + visual_anchor_class?: string; + visual_table_class?: string; + width?: number | string; + xss_sanitization?: boolean; + license_key?: string; + disabled?: boolean; + disable_nodechange?: boolean; + forced_plugins?: string | string[]; + plugin_base_urls?: Record; + service_message?: string; + [key: string]: any; +} +interface RawEditorOptions extends BaseEditorOptions { + external_plugins?: Record; + mobile?: RawEditorOptions; + plugins?: string | string[]; +} +interface NormalizedEditorOptions extends BaseEditorOptions { + external_plugins: Record; + forced_plugins: string[]; + plugins: string[]; +} +interface EditorOptions extends NormalizedEditorOptions { + a11y_advanced_options: boolean; + allow_unsafe_link_target: boolean; + anchor_bottom: string; + anchor_top: string; + automatic_uploads: boolean; + block_formats: string; + body_class: string; + body_id: string; + br_newline_selector: string; + color_map: string[]; + color_cols: number; + color_cols_foreground: number; + color_cols_background: number; + color_default_background: string; + color_default_foreground: string; + content_css: string[]; + contextmenu: string[]; + convert_unsafe_embeds: boolean; + custom_colors: boolean; + default_font_stack: string[]; + document_base_url: string; + init_content_sync: boolean; + draggable_modal: boolean; + editable_class: string; + editable_root: boolean; + font_css: string[]; + font_family_formats: string; + font_size_classes: string; + font_size_formats: string; + font_size_input_default_unit: string; + font_size_legacy_values: string; + font_size_style_values: string; + forced_root_block: string; + forced_root_block_attrs: Record; + format_noneditable_selector: string; + height: number | string; + highlight_on_focus: boolean; + iframe_attrs: Record; + images_file_types: string; + images_upload_base_path: string; + images_upload_credentials: boolean; + images_upload_url: string; + indent_use_margin: boolean; + indentation: string; + inline: boolean; + inline_boundaries_selector: string; + language: string; + language_load: boolean; + language_url: string; + line_height_formats: string; + menu: Record; + menubar: boolean | string; + model: string; + newdocument_content: string; + no_newline_selector: string; + noneditable_class: string; + noneditable_regexp: RegExp[]; + object_resizing: string; + pad_empty_with_br: boolean; + paste_as_text: boolean; + preview_styles: string; + promotion: boolean; + readonly: boolean; + removed_menuitems: string; + sandbox_iframes: boolean; + sandbox_iframes_exclusions: string[]; + toolbar: boolean | string | string[] | Array; + toolbar_groups: Record; + toolbar_location: ToolbarLocation; + toolbar_mode: ToolbarMode; + toolbar_persist: boolean; + toolbar_sticky: boolean; + toolbar_sticky_offset: number; + text_patterns: Pattern[]; + text_patterns_lookup: DynamicPatternsLookup; + visual: boolean; + visual_anchor_class: string; + visual_table_class: string; + width: number | string; + xss_sanitization: boolean; + disabled: boolean; +} +type StyleMap = Record; +interface StylesSettings { + allow_script_urls?: boolean; + allow_svg_data_urls?: boolean; + url_converter?: URLConverter; + url_converter_scope?: any; +} +interface Styles { + parse: (css: string | undefined) => Record; + serialize: (styles: StyleMap, elementName?: string) => string; +} +type EventUtilsCallback = (event: EventUtilsEvent) => void | boolean; +type EventUtilsEvent = NormalizedEvent & { + metaKey: boolean; +}; +interface Callback$1 { + func: EventUtilsCallback; + scope: any; +} +interface CallbackList extends Array> { + fakeName: string | false; + capture: boolean; + nativeHandler: EventListener; +} +interface EventUtilsConstructor { + readonly prototype: EventUtils; + new (): EventUtils; + Event: EventUtils; +} +declare class EventUtils { + static Event: EventUtils; + domLoaded: boolean; + events: Record>>; + private readonly expando; + private hasFocusIn; + private count; + constructor(); + bind(target: any, name: K, callback: EventUtilsCallback, scope?: any): EventUtilsCallback; + bind(target: any, names: string, callback: EventUtilsCallback, scope?: any): EventUtilsCallback; + unbind(target: any, name: K, callback?: EventUtilsCallback): this; + unbind(target: any, names: string, callback?: EventUtilsCallback): this; + unbind(target: any): this; + fire(target: any, name: string, args?: {}): this; + dispatch(target: any, name: string, args?: {}): this; + clean(target: any): this; + destroy(): void; + cancel(e: EventUtilsEvent): boolean; + private executeHandlers; +} +interface SetAttribEvent { + attrElm: HTMLElement; + attrName: string; + attrValue: string | boolean | number | null; +} +interface DOMUtilsSettings { + schema: Schema; + url_converter: URLConverter; + url_converter_scope: any; + ownEvents: boolean; + keep_values: boolean; + update_styles: boolean; + root_element: HTMLElement | null; + collect: boolean; + onSetAttrib: (event: SetAttribEvent) => void; + contentCssCors: boolean; + referrerPolicy: ReferrerPolicy; +} +type Target = Node | Window; +type RunArguments = string | T | Array | null; +type BoundEvent = [ + Target, + string, + EventUtilsCallback, + any +]; +type Callback = EventUtilsCallback>; +type RunResult = T extends Array ? R[] : false | R; +interface DOMUtils { + doc: Document; + settings: Partial; + win: Window; + files: Record; + stdMode: boolean; + boxModel: boolean; + styleSheetLoader: StyleSheetLoader; + boundEvents: BoundEvent[]; + styles: Styles; + schema: Schema; + events: EventUtils; + root: Node | null; + isBlock: { + (node: Node | null): node is HTMLElement; + (node: string): boolean; + }; + clone: (node: Node, deep: boolean) => Node; + getRoot: () => HTMLElement; + getViewPort: (argWin?: Window) => GeomRect; + getRect: (elm: string | HTMLElement) => GeomRect; + getSize: (elm: string | HTMLElement) => { + w: number; + h: number; + }; + getParent: { + (node: string | Node | null, selector: K, root?: Node): HTMLElementTagNameMap[K] | null; + (node: string | Node | null, selector: string | ((node: Node) => node is T), root?: Node): T | null; + (node: string | Node | null, selector?: string | ((node: Node) => boolean | void), root?: Node): Node | null; + }; + getParents: { + (elm: string | HTMLElementTagNameMap[K] | null, selector: K, root?: Node, collect?: boolean): Array; + (node: string | Node | null, selector: string | ((node: Node) => node is T), root?: Node, collect?: boolean): T[]; + (elm: string | Node | null, selector?: string | ((node: Node) => boolean | void), root?: Node, collect?: boolean): Node[]; + }; + get: { + (elm: T): T; + (elm: string): HTMLElement | null; + }; + getNext: (node: Node | null, selector: string | ((node: Node) => boolean)) => Node | null; + getPrev: (node: Node | null, selector: string | ((node: Node) => boolean)) => Node | null; + select: { + (selector: K, scope?: string | Node): Array; + (selector: string, scope?: string | Node): T[]; + }; + is: { + (elm: Node | Node[] | null, selector: string): elm is T; + (elm: Node | Node[] | null, selector: string): boolean; + }; + add: (parentElm: RunArguments, name: string | Element, attrs?: Record, html?: string | Node | null, create?: boolean) => HTMLElement; + create: { + (name: K, attrs?: Record, html?: string | Node | null): HTMLElementTagNameMap[K]; + (name: string, attrs?: Record, html?: string | Node | null): HTMLElement; + }; + createHTML: (name: string, attrs?: Record, html?: string) => string; + createFragment: (html?: string) => DocumentFragment; + remove: { + (node: T | T[], keepChildren?: boolean): typeof node extends Array ? T[] : T; + (node: string, keepChildren?: boolean): T | false; + }; + getStyle: { + (elm: Element, name: string, computed: true): string; + (elm: string | Element | null, name: string, computed?: boolean): string | undefined; + }; + setStyle: (elm: string | Element | Element[], name: string, value: string | number | null) => void; + setStyles: (elm: string | Element | Element[], stylesArg: StyleMap) => void; + removeAllAttribs: (e: RunArguments) => void; + setAttrib: (elm: RunArguments, name: string, value: string | boolean | number | null) => void; + setAttribs: (elm: RunArguments, attrs: Record) => void; + getAttrib: (elm: string | Element | null, name: string, defaultVal?: string) => string; + getAttribs: (elm: string | Element) => NamedNodeMap | Attr[]; + getPos: (elm: string | Element, rootElm?: Node) => { + x: number; + y: number; + }; + parseStyle: (cssText: string) => Record; + serializeStyle: (stylesArg: StyleMap, name?: string) => string; + addStyle: (cssText: string) => void; + loadCSS: (url: string) => void; + hasClass: (elm: string | Element, cls: string) => boolean; + addClass: (elm: RunArguments, cls: string) => void; + removeClass: (elm: RunArguments, cls: string) => void; + toggleClass: (elm: RunArguments, cls: string, state?: boolean) => void; + show: (elm: string | Node | Node[]) => void; + hide: (elm: string | Node | Node[]) => void; + isHidden: (elm: string | Node) => boolean; + uniqueId: (prefix?: string) => string; + setHTML: (elm: RunArguments, html: string) => void; + getOuterHTML: (elm: string | Node) => string; + setOuterHTML: (elm: string | Node | Node[], html: string) => void; + decode: (text: string) => string; + encode: (text: string) => string; + insertAfter: { + (node: T | T[], reference: string | Node): T; + (node: RunArguments, reference: string | Node): RunResult; + }; + replace: { + (newElm: Node, oldElm: T | T[], keepChildren?: boolean): T; + (newElm: Node, oldElm: RunArguments, keepChildren?: boolean): false | T; + }; + rename: { + (elm: Element, name: K): HTMLElementTagNameMap[K]; + (elm: Element, name: string): Element; + }; + findCommonAncestor: (a: Node, b: Node) => Node | null; + run(this: DOMUtils, elm: T | T[], func: (node: T) => R, scope?: any): typeof elm extends Array ? R[] : R; + run(this: DOMUtils, elm: RunArguments, func: (node: T) => R, scope?: any): RunResult; + isEmpty: (node: Node, elements?: Record, options?: IsEmptyOptions) => boolean; + createRng: () => Range; + nodeIndex: (node: Node, normalized?: boolean) => number; + split: { + (parentElm: Node, splitElm: Node, replacementElm: T): T | undefined; + (parentElm: Node, splitElm: T): T | undefined; + }; + bind: { + (target: Target, name: K, func: Callback, scope?: any): Callback; + (target: Target[], name: K, func: Callback, scope?: any): Callback[]; + }; + unbind: { + (target: Target, name?: K, func?: EventUtilsCallback>): EventUtils; + (target: Target[], name?: K, func?: EventUtilsCallback>): EventUtils[]; + }; + fire: (target: Node | Window, name: string, evt?: {}) => EventUtils; + dispatch: (target: Node | Window, name: string, evt?: {}) => EventUtils; + getContentEditable: (node: Node) => string | null; + getContentEditableParent: (node: Node) => string | null; + isEditable: (node: Node | null | undefined) => boolean; + destroy: () => void; + isChildOf: (node: Node, parent: Node) => boolean; + dumpRng: (r: Range) => string; +} +interface ClientRect { + left: number; + top: number; + bottom: number; + right: number; + width: number; + height: number; +} +interface BookmarkManager { + getBookmark: (type?: number, normalized?: boolean) => Bookmark; + moveToBookmark: (bookmark: Bookmark) => void; +} +interface ControlSelection { + isResizable: (elm: Element) => boolean; + showResizeRect: (elm: HTMLElement) => void; + hideResizeRect: () => void; + updateResizeRect: (evt: EditorEvent) => void; + destroy: () => void; +} +interface WriterSettings { + element_format?: 'xhtml' | 'html'; + entities?: string; + entity_encoding?: EntityEncoding; + indent?: boolean; + indent_after?: string; + indent_before?: string; +} +type Attributes = Array<{ + name: string; + value: string; +}>; +interface Writer { + cdata: (text: string) => void; + comment: (text: string) => void; + doctype: (text: string) => void; + end: (name: string) => void; + getContent: () => string; + pi: (name: string, text?: string) => void; + reset: () => void; + start: (name: string, attrs?: Attributes | null, empty?: boolean) => void; + text: (text: string, raw?: boolean) => void; +} +interface HtmlSerializerSettings extends WriterSettings { + inner?: boolean; + validate?: boolean; +} +interface HtmlSerializer { + serialize: (node: AstNode) => string; +} +interface DomSerializerSettings extends DomParserSettings, WriterSettings, SchemaSettings, HtmlSerializerSettings { + remove_trailing_brs?: boolean; + url_converter?: URLConverter; + url_converter_scope?: {}; +} +interface DomSerializerImpl { + schema: Schema; + addNodeFilter: (name: string, callback: ParserFilterCallback) => void; + addAttributeFilter: (name: string, callback: ParserFilterCallback) => void; + getNodeFilters: () => ParserFilter[]; + getAttributeFilters: () => ParserFilter[]; + removeNodeFilter: (name: string, callback?: ParserFilterCallback) => void; + removeAttributeFilter: (name: string, callback?: ParserFilterCallback) => void; + serialize: { + (node: Element, parserArgs: { + format: 'tree'; + } & ParserArgs): AstNode; + (node: Element, parserArgs?: ParserArgs): string; + }; + addRules: (rules: string) => void; + setRules: (rules: string) => void; + addTempAttr: (name: string) => void; + getTempAttrs: () => string[]; +} +interface DomSerializer extends DomSerializerImpl { +} +interface EditorSelection { + bookmarkManager: BookmarkManager; + controlSelection: ControlSelection; + dom: DOMUtils; + win: Window; + serializer: DomSerializer; + editor: Editor; + collapse: (toStart?: boolean) => void; + setCursorLocation: { + (node: Node, offset: number): void; + (): void; + }; + getContent: { + (args: { + format: 'tree'; + } & Partial): AstNode; + (args?: Partial): string; + }; + setContent: (content: string, args?: Partial) => void; + getBookmark: (type?: number, normalized?: boolean) => Bookmark; + moveToBookmark: (bookmark: Bookmark) => void; + select: (node: Node, content?: boolean) => Node; + isCollapsed: () => boolean; + isEditable: () => boolean; + isForward: () => boolean; + setNode: (elm: Element) => Element; + getNode: () => HTMLElement; + getSel: () => Selection | null; + setRng: (rng: Range, forward?: boolean) => void; + getRng: () => Range; + getStart: (real?: boolean) => Element; + getEnd: (real?: boolean) => Element; + getSelectedBlocks: (startElm?: Element, endElm?: Element) => Element[]; + normalize: () => Range; + selectorChanged: (selector: string, callback: (active: boolean, args: { + node: Node; + selector: String; + parents: Node[]; + }) => void) => EditorSelection; + selectorChangedWithUnbind: (selector: string, callback: (active: boolean, args: { + node: Node; + selector: String; + parents: Node[]; + }) => void) => { + unbind: () => void; + }; + getScrollContainer: () => HTMLElement | undefined; + scrollIntoView: (elm?: HTMLElement, alignToTop?: boolean) => void; + placeCaretAt: (clientX: number, clientY: number) => void; + getBoundingClientRect: () => ClientRect | DOMRect; + destroy: () => void; + expand: (options?: { + type: 'word'; + }) => void; +} +type EditorCommandCallback = (this: S, ui: boolean, value: any) => void; +type EditorCommandsCallback = (command: string, ui: boolean, value?: any) => void; +interface Commands { + state: Record boolean>; + exec: Record; + value: Record string>; +} +interface ExecCommandArgs { + skip_focus?: boolean; +} +interface EditorCommandsConstructor { + readonly prototype: EditorCommands; + new (editor: Editor): EditorCommands; +} +declare class EditorCommands { + private readonly editor; + private commands; + constructor(editor: Editor); + execCommand(command: string, ui?: boolean, value?: any, args?: ExecCommandArgs): boolean; + queryCommandState(command: string): boolean; + queryCommandValue(command: string): string; + addCommands(commandList: Commands[K], type: K): void; + addCommands(commandList: Record): void; + addCommand(command: string, callback: EditorCommandCallback, scope: S): void; + addCommand(command: string, callback: EditorCommandCallback): void; + queryCommandSupported(command: string): boolean; + addQueryStateHandler(command: string, callback: (this: S) => boolean, scope: S): void; + addQueryStateHandler(command: string, callback: (this: Editor) => boolean): void; + addQueryValueHandler(command: string, callback: (this: S) => string, scope: S): void; + addQueryValueHandler(command: string, callback: (this: Editor) => string): void; +} +interface RawString { + raw: string; +} +type Primitive = string | number | boolean | Record | Function; +type TokenisedString = [ + string, + ...Primitive[] +]; +type Untranslated = Primitive | TokenisedString | RawString | null | undefined; +type TranslatedString = string; +interface I18n { + getData: () => Record>; + setCode: (newCode: string) => void; + getCode: () => string; + add: (code: string, items: Record) => void; + translate: (text: Untranslated) => TranslatedString; + isRtl: () => boolean; + hasCode: (code: string) => boolean; +} +interface Observable { + fire>(name: K, args?: U, bubble?: boolean): EditorEvent; + dispatch>(name: K, args?: U, bubble?: boolean): EditorEvent; + on(name: K, callback: (event: EditorEvent>) => void, prepend?: boolean): EventDispatcher; + off(name?: K, callback?: (event: EditorEvent>) => void): EventDispatcher; + once(name: K, callback: (event: EditorEvent>) => void): EventDispatcher; + hasEventListeners(name: string): boolean; +} +interface URISettings { + base_uri?: URI; +} +interface URIConstructor { + readonly prototype: URI; + new (url: string, settings?: URISettings): URI; + getDocumentBaseUrl: (loc: { + protocol: string; + host?: string; + href?: string; + pathname?: string; + }) => string; + parseDataUri: (uri: string) => { + type: string; + data: string; + }; +} +interface SafeUriOptions { + readonly allow_html_data_urls?: boolean; + readonly allow_script_urls?: boolean; + readonly allow_svg_data_urls?: boolean; +} +declare class URI { + static parseDataUri(uri: string): { + type: string | undefined; + data: string; + }; + static isDomSafe(uri: string, context?: string, options?: SafeUriOptions): boolean; + static getDocumentBaseUrl(loc: { + protocol: string; + host?: string; + href?: string; + pathname?: string; + }): string; + source: string; + protocol: string | undefined; + authority: string | undefined; + userInfo: string | undefined; + user: string | undefined; + password: string | undefined; + host: string | undefined; + port: string | undefined; + relative: string | undefined; + path: string; + directory: string; + file: string | undefined; + query: string | undefined; + anchor: string | undefined; + settings: URISettings; + constructor(url: string, settings?: URISettings); + setPath(path: string): void; + toRelative(uri: string): string; + toAbsolute(uri: string, noHost?: boolean): string; + isSameOrigin(uri: URI): boolean; + toRelPath(base: string, path: string): string; + toAbsPath(base: string, path: string): string; + getURI(noProtoHost?: boolean): string; +} +interface EditorManager extends Observable { + defaultOptions: RawEditorOptions; + majorVersion: string; + minorVersion: string; + releaseDate: string; + activeEditor: Editor | null; + focusedEditor: Editor | null; + baseURI: URI; + baseURL: string; + documentBaseURL: string; + i18n: I18n; + suffix: string; + add(this: EditorManager, editor: Editor): Editor; + addI18n: (code: string, item: Record) => void; + createEditor(this: EditorManager, id: string, options: RawEditorOptions): Editor; + execCommand(this: EditorManager, cmd: string, ui: boolean, value: any): boolean; + get(this: EditorManager): Editor[]; + get(this: EditorManager, id: number | string): Editor | null; + init(this: EditorManager, options: RawEditorOptions): Promise; + overrideDefaults(this: EditorManager, defaultOptions: Partial): void; + remove(this: EditorManager): void; + remove(this: EditorManager, selector: string): void; + remove(this: EditorManager, editor: Editor): Editor | null; + setActive(this: EditorManager, editor: Editor): void; + setup(this: EditorManager): void; + translate: (text: Untranslated) => TranslatedString; + triggerSave: () => void; + _setBaseUrl(this: EditorManager, baseUrl: string): void; +} +interface EditorObservable extends Observable { + bindPendingEventDelegates(this: Editor): void; + toggleNativeEvent(this: Editor, name: string, state: boolean): void; + unbindAllNativeEvents(this: Editor): void; +} +interface ProcessorSuccess { + valid: true; + value: T; +} +interface ProcessorError { + valid: false; + message: string; +} +type SimpleProcessor = (value: unknown) => boolean; +type Processor = (value: unknown) => ProcessorSuccess | ProcessorError; +interface BuiltInOptionTypeMap { + 'string': string; + 'number': number; + 'boolean': boolean; + 'array': any[]; + 'function': Function; + 'object': any; + 'string[]': string[]; + 'object[]': any[]; + 'regexp': RegExp; +} +type BuiltInOptionType = keyof BuiltInOptionTypeMap; +interface BaseOptionSpec { + immutable?: boolean; + deprecated?: boolean; + docsUrl?: string; +} +interface BuiltInOptionSpec extends BaseOptionSpec { + processor: K; + default?: BuiltInOptionTypeMap[K]; +} +interface SimpleOptionSpec extends BaseOptionSpec { + processor: SimpleProcessor; + default?: T; +} +interface OptionSpec extends BaseOptionSpec { + processor: Processor; + default?: T; +} +interface Options { + register: { + (name: string, spec: BuiltInOptionSpec): void; + (name: K, spec: OptionSpec | SimpleOptionSpec): void; + (name: string, spec: OptionSpec): void; + (name: string, spec: SimpleOptionSpec): void; + }; + isRegistered: (name: string) => boolean; + get: { + (name: K): EditorOptions[K]; + (name: string): T | undefined; + }; + set: (name: K, value: K extends keyof NormalizedEditorOptions ? NormalizedEditorOptions[K] : T) => boolean; + unset: (name: string) => boolean; + isSet: (name: string) => boolean; + debug: () => void; +} +interface UploadResult$1 { + element: HTMLImageElement; + status: boolean; + blobInfo: BlobInfo; + uploadUri: string; + removed: boolean; +} +interface EditorUpload { + blobCache: BlobCache; + addFilter: (filter: (img: HTMLImageElement) => boolean) => void; + uploadImages: () => Promise; + uploadImagesAuto: () => Promise; + scanForImages: () => Promise; + destroy: () => void; +} +type FormatChangeCallback = (state: boolean, data: { + node: Node; + format: string; + parents: Element[]; +}) => void; +interface FormatRegistry { + get: { + (name: string): Format[] | undefined; + (): Record; + }; + has: (name: string) => boolean; + register: (name: string | Formats, format?: Format[] | Format) => void; + unregister: (name: string) => Formats; +} +interface Formatter extends FormatRegistry { + apply: (name: string, vars?: FormatVars, node?: Node | RangeLikeObject | null) => void; + remove: (name: string, vars?: FormatVars, node?: Node | Range, similar?: boolean) => void; + toggle: (name: string, vars?: FormatVars, node?: Node) => void; + match: (name: string, vars?: FormatVars, node?: Node, similar?: boolean) => boolean; + closest: (names: string[]) => string | null; + matchAll: (names: string[], vars?: FormatVars) => string[]; + matchNode: (node: Node | null, name: string, vars?: FormatVars, similar?: boolean) => Format | undefined; + canApply: (name: string) => boolean; + formatChanged: (names: string, callback: FormatChangeCallback, similar?: boolean, vars?: FormatVars) => { + unbind: () => void; + }; + getCssText: (format: string | ApplyFormat) => string; +} +interface EditorMode { + isReadOnly: () => boolean; + set: (mode: string) => void; + get: () => string; + register: (mode: string, api: EditorModeApi) => void; +} +interface EditorModeApi { + activate: () => void; + deactivate: () => void; + editorReadOnly: boolean; +} +interface Model { + readonly table: { + readonly getSelectedCells: () => HTMLTableCellElement[]; + readonly clearSelectedCells: (container: Node) => void; + }; +} +type ModelManager = AddOnManager; +interface Plugin { + getMetadata?: () => { + name: string; + url: string; + }; + init?: (editor: Editor, url: string) => void; + [key: string]: any; +} +type PluginManager = AddOnManager; +interface ShortcutsConstructor { + readonly prototype: Shortcuts; + new (editor: Editor): Shortcuts; +} +type CommandFunc = string | [ + string, + boolean, + any +] | (() => void); +declare class Shortcuts { + private readonly editor; + private readonly shortcuts; + private pendingPatterns; + constructor(editor: Editor); + add(pattern: string, desc: string | null, cmdFunc: CommandFunc, scope?: any): boolean; + remove(pattern: string): boolean; + private normalizeCommandFunc; + private createShortcut; + private hasModifier; + private isFunctionKey; + private matchShortcut; + private executeShortcutAction; +} +interface RenderResult { + iframeContainer?: HTMLElement; + editorContainer: HTMLElement; + api?: Partial; +} +interface Theme { + ui?: any; + inline?: any; + execCommand?: (command: string, ui?: boolean, value?: any) => boolean; + destroy?: () => void; + init?: (editor: Editor, url: string) => void; + renderUI?: () => Promise | RenderResult; + getNotificationManagerImpl?: () => NotificationManagerImpl; + getWindowManagerImpl?: () => WindowManagerImpl; +} +type ThemeManager = AddOnManager; +interface EditorConstructor { + readonly prototype: Editor; + new (id: string, options: RawEditorOptions, editorManager: EditorManager): Editor; +} +declare class Editor implements EditorObservable { + documentBaseUrl: string; + baseUri: URI; + id: string; + plugins: Record; + documentBaseURI: URI; + baseURI: URI; + contentCSS: string[]; + contentStyles: string[]; + ui: EditorUi; + mode: EditorMode; + options: Options; + editorUpload: EditorUpload; + shortcuts: Shortcuts; + loadedCSS: Record; + editorCommands: EditorCommands; + suffix: string; + editorManager: EditorManager; + hidden: boolean; + inline: boolean; + hasVisual: boolean; + isNotDirty: boolean; + annotator: Annotator; + bodyElement: HTMLElement | undefined; + bookmark: any; + composing: boolean; + container: HTMLElement; + contentAreaContainer: HTMLElement; + contentDocument: Document; + contentWindow: Window; + delegates: Record> | undefined; + destroyed: boolean; + dom: DOMUtils; + editorContainer: HTMLElement; + eventRoot: Element | undefined; + formatter: Formatter; + formElement: HTMLElement | undefined; + formEventDelegate: ((e: Event) => void) | undefined; + hasHiddenInput: boolean; + iframeElement: HTMLIFrameElement | null; + iframeHTML: string | undefined; + initialized: boolean; + notificationManager: NotificationManager; + orgDisplay: string; + orgVisibility: string | undefined; + parser: DomParser; + quirks: Quirks; + readonly: boolean; + removed: boolean; + schema: Schema; + selection: EditorSelection; + serializer: DomSerializer; + startContent: string; + targetElm: HTMLElement; + theme: Theme; + model: Model; + undoManager: UndoManager; + windowManager: WindowManager; + _beforeUnload: (() => void) | undefined; + _eventDispatcher: EventDispatcher | undefined; + _nodeChangeDispatcher: NodeChange; + _pendingNativeEvents: string[]; + _selectionOverrides: SelectionOverrides; + _skinLoaded: boolean; + _editableRoot: boolean; + bindPendingEventDelegates: EditorObservable['bindPendingEventDelegates']; + toggleNativeEvent: EditorObservable['toggleNativeEvent']; + unbindAllNativeEvents: EditorObservable['unbindAllNativeEvents']; + fire: EditorObservable['fire']; + dispatch: EditorObservable['dispatch']; + on: EditorObservable['on']; + off: EditorObservable['off']; + once: EditorObservable['once']; + hasEventListeners: EditorObservable['hasEventListeners']; + constructor(id: string, options: RawEditorOptions, editorManager: EditorManager); + render(): void; + focus(skipFocus?: boolean): void; + hasFocus(): boolean; + translate(text: Untranslated): TranslatedString; + getParam(name: string, defaultVal: BuiltInOptionTypeMap[K], type: K): BuiltInOptionTypeMap[K]; + getParam(name: K, defaultVal?: NormalizedEditorOptions[K], type?: BuiltInOptionType): NormalizedEditorOptions[K]; + getParam(name: string, defaultVal: T, type?: BuiltInOptionType): T; + hasPlugin(name: string, loaded?: boolean): boolean; + nodeChanged(args?: any): void; + addCommand(name: string, callback: EditorCommandCallback, scope: S): void; + addCommand(name: string, callback: EditorCommandCallback): void; + addQueryStateHandler(name: string, callback: (this: S) => boolean, scope?: S): void; + addQueryStateHandler(name: string, callback: (this: Editor) => boolean): void; + addQueryValueHandler(name: string, callback: (this: S) => string, scope: S): void; + addQueryValueHandler(name: string, callback: (this: Editor) => string): void; + addShortcut(pattern: string, desc: string, cmdFunc: string | [ + string, + boolean, + any + ] | (() => void), scope?: any): void; + execCommand(cmd: string, ui?: boolean, value?: any, args?: ExecCommandArgs): boolean; + queryCommandState(cmd: string): boolean; + queryCommandValue(cmd: string): string; + queryCommandSupported(cmd: string): boolean; + show(): void; + hide(): void; + isHidden(): boolean; + setProgressState(state: boolean, time?: number): void; + load(args?: Partial): string; + save(args?: Partial): string; + setContent(content: string, args?: Partial): string; + setContent(content: AstNode, args?: Partial): AstNode; + setContent(content: Content, args?: Partial): Content; + getContent(args: { + format: 'tree'; + } & Partial): AstNode; + getContent(args?: Partial): string; + insertContent(content: string, args?: any): void; + resetContent(initialContent?: string): void; + isDirty(): boolean; + setDirty(state: boolean): void; + getContainer(): HTMLElement; + getContentAreaContainer(): HTMLElement; + getElement(): HTMLElement; + getWin(): Window; + getDoc(): Document; + getBody(): HTMLElement; + convertURL(url: string, name: string, elm?: string | Element): string; + addVisual(elm?: HTMLElement): void; + setEditableRoot(state: boolean): void; + hasEditableRoot(): boolean; + remove(): void; + destroy(automatic?: boolean): void; + uploadImages(): Promise; + _scanForImages(): Promise; +} +interface UrlObject { + prefix: string; + resource: string; + suffix: string; +} +type WaitState = 'added' | 'loaded'; +type AddOnConstructor = (editor: Editor, url: string) => T; +interface AddOnManager { + items: AddOnConstructor[]; + urls: Record; + lookup: Record; + }>; + get: (name: string) => AddOnConstructor | undefined; + requireLangPack: (name: string, languages?: string) => void; + add: (id: string, addOn: AddOnConstructor) => AddOnConstructor; + remove: (name: string) => void; + createUrl: (baseUrl: UrlObject, dep: string | UrlObject) => UrlObject; + load: (name: string, addOnUrl: string | UrlObject) => Promise; + waitFor: (name: string, state?: WaitState) => Promise; +} +interface RangeUtils { + walk: (rng: Range, callback: (nodes: Node[]) => void) => void; + split: (rng: Range) => RangeLikeObject; + normalize: (rng: Range) => boolean; + expand: (rng: Range, options?: { + type: 'word'; + }) => Range; +} +interface ScriptLoaderSettings { + referrerPolicy?: ReferrerPolicy; +} +interface ScriptLoaderConstructor { + readonly prototype: ScriptLoader; + new (): ScriptLoader; + ScriptLoader: ScriptLoader; +} +declare class ScriptLoader { + static ScriptLoader: ScriptLoader; + private settings; + private states; + private queue; + private scriptLoadedCallbacks; + private queueLoadedCallbacks; + private loading; + constructor(settings?: ScriptLoaderSettings); + _setReferrerPolicy(referrerPolicy: ReferrerPolicy): void; + loadScript(url: string): Promise; + isDone(url: string): boolean; + markDone(url: string): void; + add(url: string): Promise; + load(url: string): Promise; + remove(url: string): void; + loadQueue(): Promise; + loadScripts(scripts: string[]): Promise; +} +type TextProcessCallback = (node: Text, offset: number, text: string) => number; +interface Spot { + container: Text; + offset: number; +} +interface TextSeeker { + backwards: (node: Node, offset: number, process: TextProcessCallback, root?: Node) => Spot | null; + forwards: (node: Node, offset: number, process: TextProcessCallback, root?: Node) => Spot | null; +} +interface DomTreeWalkerConstructor { + readonly prototype: DomTreeWalker; + new (startNode: Node, rootNode: Node): DomTreeWalker; +} +declare class DomTreeWalker { + private readonly rootNode; + private node; + constructor(startNode: Node, rootNode: Node); + current(): Node | null | undefined; + next(shallow?: boolean): Node | null | undefined; + prev(shallow?: boolean): Node | null | undefined; + prev2(shallow?: boolean): Node | null | undefined; + private findSibling; + private findPreviousNode; +} +interface Version { + major: number; + minor: number; +} +interface Env { + transparentSrc: string; + documentMode: number; + cacheSuffix: any; + container: any; + canHaveCSP: boolean; + windowsPhone: boolean; + browser: { + current: string | undefined; + version: Version; + isEdge: () => boolean; + isChromium: () => boolean; + isIE: () => boolean; + isOpera: () => boolean; + isFirefox: () => boolean; + isSafari: () => boolean; + }; + os: { + current: string | undefined; + version: Version; + isWindows: () => boolean; + isiOS: () => boolean; + isAndroid: () => boolean; + isMacOS: () => boolean; + isLinux: () => boolean; + isSolaris: () => boolean; + isFreeBSD: () => boolean; + isChromeOS: () => boolean; + }; + deviceType: { + isiPad: () => boolean; + isiPhone: () => boolean; + isTablet: () => boolean; + isPhone: () => boolean; + isTouch: () => boolean; + isWebView: () => boolean; + isDesktop: () => boolean; + }; +} +interface FakeClipboardItem { + readonly items: Record; + readonly types: ReadonlyArray; + readonly getType: (type: string) => D | undefined; +} +interface FakeClipboard { + readonly FakeClipboardItem: (items: Record) => FakeClipboardItem; + readonly write: (data: FakeClipboardItem[]) => void; + readonly read: () => FakeClipboardItem[] | undefined; + readonly clear: () => void; +} +interface FocusManager { + isEditorUIElement: (elm: Element) => boolean; +} +interface EntitiesMap { + [name: string]: string; +} +interface Entities { + encodeRaw: (text: string, attr?: boolean) => string; + encodeAllRaw: (text: string) => string; + encodeNumeric: (text: string, attr?: boolean) => string; + encodeNamed: (text: string, attr?: boolean, entities?: EntitiesMap) => string; + getEncodeFunc: (name: string, entities?: string) => (text: string, attr?: boolean) => string; + decode: (text: string) => string; +} +interface IconPack { + icons: Record; +} +interface IconManager { + add: (id: string, iconPack: IconPack) => void; + get: (id: string) => IconPack; + has: (id: string) => boolean; +} +interface Resource { + load: (id: string, url: string) => Promise; + add: (id: string, data: any) => void; + has: (id: string) => boolean; + get: (id: string) => any; + unload: (id: string) => void; +} +type TextPatterns_d_Pattern = Pattern; +type TextPatterns_d_RawPattern = RawPattern; +type TextPatterns_d_DynamicPatternsLookup = DynamicPatternsLookup; +type TextPatterns_d_RawDynamicPatternsLookup = RawDynamicPatternsLookup; +type TextPatterns_d_DynamicPatternContext = DynamicPatternContext; +type TextPatterns_d_BlockCmdPattern = BlockCmdPattern; +type TextPatterns_d_BlockPattern = BlockPattern; +type TextPatterns_d_BlockFormatPattern = BlockFormatPattern; +type TextPatterns_d_InlineCmdPattern = InlineCmdPattern; +type TextPatterns_d_InlinePattern = InlinePattern; +type TextPatterns_d_InlineFormatPattern = InlineFormatPattern; +declare namespace TextPatterns_d { + export { TextPatterns_d_Pattern as Pattern, TextPatterns_d_RawPattern as RawPattern, TextPatterns_d_DynamicPatternsLookup as DynamicPatternsLookup, TextPatterns_d_RawDynamicPatternsLookup as RawDynamicPatternsLookup, TextPatterns_d_DynamicPatternContext as DynamicPatternContext, TextPatterns_d_BlockCmdPattern as BlockCmdPattern, TextPatterns_d_BlockPattern as BlockPattern, TextPatterns_d_BlockFormatPattern as BlockFormatPattern, TextPatterns_d_InlineCmdPattern as InlineCmdPattern, TextPatterns_d_InlinePattern as InlinePattern, TextPatterns_d_InlineFormatPattern as InlineFormatPattern, }; +} +interface Delay { + setEditorInterval: (editor: Editor, callback: () => void, time?: number) => number; + setEditorTimeout: (editor: Editor, callback: () => void, time?: number) => number; +} +type UploadResult = UploadResult$2; +interface ImageUploader { + upload: (blobInfos: BlobInfo[], showNotification?: boolean) => Promise; +} +type ArrayCallback$1 = (this: any, x: T, i: number, xs: ArrayLike) => R; +type ObjCallback$1 = (this: any, value: T, key: string, obj: Record) => R; +type ArrayCallback = ArrayCallback$1; +type ObjCallback = ObjCallback$1; +type WalkCallback = (this: any, o: T, i: string, n: keyof T | undefined) => boolean | void; +interface Tools { + is: (obj: any, type?: string) => boolean; + isArray: (arr: any) => arr is Array; + inArray: (arr: ArrayLike, value: T) => number; + grep: { + (arr: ArrayLike | null | undefined, pred?: ArrayCallback): T[]; + (arr: Record | null | undefined, pred?: ObjCallback): T[]; + }; + trim: (str: string | null | undefined) => string; + toArray: (obj: ArrayLike) => T[]; + hasOwn: (obj: any, name: string) => boolean; + makeMap: (items: ArrayLike | string | undefined, delim?: string | RegExp, map?: Record) => Record; + each: { + (arr: ArrayLike | null | undefined, cb: ArrayCallback, scope?: any): boolean; + (obj: Record | null | undefined, cb: ObjCallback, scope?: any): boolean; + }; + map: { + (arr: ArrayLike | null | undefined, cb: ArrayCallback): R[]; + (obj: Record | null | undefined, cb: ObjCallback): R[]; + }; + extend: (obj: Object, ext: Object, ...objs: Object[]) => any; + walk: >(obj: T, f: WalkCallback, n?: keyof T, scope?: any) => void; + resolve: (path: string, o?: Object) => any; + explode: (s: string | string[], d?: string | RegExp) => string[]; + _addCacheSuffix: (url: string) => string; +} +interface KeyboardLikeEvent { + shiftKey: boolean; + ctrlKey: boolean; + altKey: boolean; + metaKey: boolean; +} +interface VK { + BACKSPACE: number; + DELETE: number; + DOWN: number; + ENTER: number; + ESC: number; + LEFT: number; + RIGHT: number; + SPACEBAR: number; + TAB: number; + UP: number; + PAGE_UP: number; + PAGE_DOWN: number; + END: number; + HOME: number; + modifierPressed: (e: KeyboardLikeEvent) => boolean; + metaKeyPressed: (e: KeyboardLikeEvent) => boolean; +} +interface DOMUtilsNamespace { + (doc: Document, settings: Partial): DOMUtils; + DOM: DOMUtils; + nodeIndex: (node: Node, normalized?: boolean) => number; +} +interface RangeUtilsNamespace { + (dom: DOMUtils): RangeUtils; + compareRanges: (rng1: RangeLikeObject, rng2: RangeLikeObject) => boolean; + getCaretRangeFromPoint: (clientX: number, clientY: number, doc: Document) => Range; + getSelectedNode: (range: Range) => Node; + getNode: (container: Node, offset: number) => Node; +} +interface AddOnManagerNamespace { + (): AddOnManager; + language: string | undefined; + languageLoad: boolean; + baseURL: string; + PluginManager: PluginManager; + ThemeManager: ThemeManager; + ModelManager: ModelManager; +} +interface BookmarkManagerNamespace { + (selection: EditorSelection): BookmarkManager; + isBookmarkNode: (node: Node) => boolean; +} +interface TinyMCE extends EditorManager { + geom: { + Rect: Rect; + }; + util: { + Delay: Delay; + Tools: Tools; + VK: VK; + URI: URIConstructor; + EventDispatcher: EventDispatcherConstructor; + Observable: Observable; + I18n: I18n; + LocalStorage: Storage; + ImageUploader: ImageUploader; + }; + dom: { + EventUtils: EventUtilsConstructor; + TreeWalker: DomTreeWalkerConstructor; + TextSeeker: (dom: DOMUtils, isBlockBoundary?: (node: Node) => boolean) => TextSeeker; + DOMUtils: DOMUtilsNamespace; + ScriptLoader: ScriptLoaderConstructor; + RangeUtils: RangeUtilsNamespace; + Serializer: (settings: DomSerializerSettings, editor?: Editor) => DomSerializer; + ControlSelection: (selection: EditorSelection, editor: Editor) => ControlSelection; + BookmarkManager: BookmarkManagerNamespace; + Selection: (dom: DOMUtils, win: Window, serializer: DomSerializer, editor: Editor) => EditorSelection; + StyleSheetLoader: (documentOrShadowRoot: Document | ShadowRoot, settings: StyleSheetLoaderSettings) => StyleSheetLoader; + Event: EventUtils; + }; + html: { + Styles: (settings?: StylesSettings, schema?: Schema) => Styles; + Entities: Entities; + Node: AstNodeConstructor; + Schema: (settings?: SchemaSettings) => Schema; + DomParser: (settings?: DomParserSettings, schema?: Schema) => DomParser; + Writer: (settings?: WriterSettings) => Writer; + Serializer: (settings?: HtmlSerializerSettings, schema?: Schema) => HtmlSerializer; + }; + AddOnManager: AddOnManagerNamespace; + Annotator: (editor: Editor) => Annotator; + Editor: EditorConstructor; + EditorCommands: EditorCommandsConstructor; + EditorManager: EditorManager; + EditorObservable: EditorObservable; + Env: Env; + FocusManager: FocusManager; + Formatter: (editor: Editor) => Formatter; + NotificationManager: (editor: Editor) => NotificationManager; + Shortcuts: ShortcutsConstructor; + UndoManager: (editor: Editor) => UndoManager; + WindowManager: (editor: Editor) => WindowManager; + DOM: DOMUtils; + ScriptLoader: ScriptLoader; + PluginManager: PluginManager; + ThemeManager: ThemeManager; + ModelManager: ModelManager; + IconManager: IconManager; + Resource: Resource; + FakeClipboard: FakeClipboard; + trim: Tools['trim']; + isArray: Tools['isArray']; + is: Tools['is']; + toArray: Tools['toArray']; + makeMap: Tools['makeMap']; + each: Tools['each']; + map: Tools['map']; + grep: Tools['grep']; + inArray: Tools['inArray']; + extend: Tools['extend']; + walk: Tools['walk']; + resolve: Tools['resolve']; + explode: Tools['explode']; + _addCacheSuffix: Tools['_addCacheSuffix']; +} +declare const tinymce: TinyMCE; +export { AddOnManager, Annotator, AstNode, Bookmark, BookmarkManager, ControlSelection, DOMUtils, Delay, DomParser, DomParserSettings, DomSerializer, DomSerializerSettings, DomTreeWalker, Editor, EditorCommands, EditorEvent, EditorManager, EditorModeApi, EditorObservable, EditorOptions, EditorSelection, Entities, Env, EventDispatcher, EventUtils, EventTypes_d as Events, FakeClipboard, FocusManager, Format_d as Formats, Formatter, GeomRect, HtmlSerializer, HtmlSerializerSettings, I18n, IconManager, Model, ModelManager, NotificationApi, NotificationManager, NotificationSpec, Observable, Plugin, PluginManager, RangeUtils, RawEditorOptions, Rect, Resource, Schema, SchemaSettings, ScriptLoader, Shortcuts, StyleSheetLoader, Styles, TextPatterns_d as TextPatterns, TextSeeker, Theme, ThemeManager, TinyMCE, Tools, URI, Ui_d as Ui, UndoManager, VK, WindowManager, Writer, WriterSettings, tinymce as default }; diff --git a/components/lib/editors/TinyMCE/useTinyMCE.tsx b/components/lib/editors/TinyMCE/useTinyMCE.tsx new file mode 100644 index 0000000..a368470 --- /dev/null +++ b/components/lib/editors/TinyMCE/useTinyMCE.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import { TinyMCE } from "./tinymce"; + +let interval: any; + +export default function useTinyMCE() { + const [tinyMCE, setTinyMCE] = React.useState(null); + + React.useEffect(() => { + // @ts-ignore + if (window.tinymce) { + console.log("Tinymce already exists"); + // @ts-ignore + setTinyMCE(window.tinymce); + return; + } + + const script = document.createElement("script"); + script.src = "https://datasquirel.com/tinymce-public/tinymce.min.js"; + script.async = true; + + document.head.appendChild(script); + + script.onload = () => { + // @ts-ignore + if (window.tinymce) { + // @ts-ignore + setTinyMCE(window.tinymce); + } + }; + }, []); + + return { tinyMCE }; +} diff --git a/components/lib/elements/Border.tsx b/components/lib/elements/Border.tsx index 0e98ff4..88290fe 100644 --- a/components/lib/elements/Border.tsx +++ b/components/lib/elements/Border.tsx @@ -18,7 +18,7 @@ export default function Border({ spacing, ...props }: TWUI_BORDER_PROPS) { {...props} className={twMerge( "relative flex items-center gap-2 border rounded", - "border-slate-300 dark:border-white/20", + "border-slate-300 dark:border-white/10", spacing ? spacing == "normal" ? "px-3 py-2" diff --git a/components/lib/elements/Breadcrumbs.tsx b/components/lib/elements/Breadcrumbs.tsx index 75021f9..2bd6084 100755 --- a/components/lib/elements/Breadcrumbs.tsx +++ b/components/lib/elements/Breadcrumbs.tsx @@ -23,7 +23,7 @@ export default function Breadcrumbs() { }); pathLinks.forEach((linkText, index, array) => { - if (!linkText?.match(/./) || index == 1) { + if (!linkText?.match(/./)) { return; } @@ -56,7 +56,7 @@ export default function Breadcrumbs() { } return ( - + {links.map((linkObject, index, array) => { if (index === links.length - 1) { return ( diff --git a/components/lib/elements/Card.tsx b/components/lib/elements/Card.tsx index 7e4996e..ee12445 100644 --- a/components/lib/elements/Card.tsx +++ b/components/lib/elements/Card.tsx @@ -3,7 +3,11 @@ import { twMerge } from "tailwind-merge"; /** * # General Card - * @className_wrapper twui-card + * @className twui-card + * @className twui-card-link + * + * @info use the classname `nested-link` to prevent the card from being clickable when + * a link (or the target element with this calss) inside the card is clicked. */ export default function Card({ href, @@ -24,7 +28,9 @@ export default function Card({ className={twMerge( "flex flex-row items-center p-4 rounded bg-white dark:bg-white/10", "border border-slate-200 dark:border-white/10 border-solid", - href ? "hover:bg-slate-100 dark:hover:bg-white/30" : "", + href + ? "hover:bg-slate-100 dark:hover:bg-white/30 hover:border-slate-400 dark:hover:border-white/20" + : "", "twui-card", props.className )} @@ -35,7 +41,26 @@ export default function Card({ if (href) { return ( - + { + const targetEl = e.target as HTMLElement; + if (targetEl.closest(".nested-link")) { + e.preventDefault(); + } else if (e.ctrlKey) { + window.open(href, "_blank"); + } else { + window.location.href = href; + } + linkProps?.onClick?.(e); + }} + className={twMerge( + "cursor-pointer", + "twui-card-link", + linkProps?.className + )} + > {component} ); diff --git a/components/lib/elements/Dropdown.tsx b/components/lib/elements/Dropdown.tsx new file mode 100644 index 0000000..f92e5e9 --- /dev/null +++ b/components/lib/elements/Dropdown.tsx @@ -0,0 +1,146 @@ +import React, { + DetailedHTMLProps, + HTMLAttributes, + PropsWithChildren, +} from "react"; +import { twMerge } from "tailwind-merge"; + +export const TWUIDropdownContentPositions = [ + "left", + "right", + "center", +] as const; + +export type TWUI_DROPDOWN_PROPS = PropsWithChildren & + DetailedHTMLProps, HTMLDivElement> & { + target: React.ReactNode; + contentWrapperProps?: DetailedHTMLProps< + HTMLAttributes, + HTMLDivElement + >; + targetWrapperProps?: DetailedHTMLProps< + HTMLAttributes, + HTMLDivElement + >; + debounce?: number; + hoverOpen?: boolean; + position?: (typeof TWUIDropdownContentPositions)[number]; + topOffset?: number; + externalSetOpen?: React.Dispatch>; + }; + +let timeout: any; + +/** + * # Toggle Component + * @className_wrapper twui-dropdown-wrapper + * @className_wrapper twui-dropdown-target + * @className_wrapper twui-dropdown-content + */ +export default function Dropdown({ + contentWrapperProps, + targetWrapperProps, + hoverOpen, + debounce = 500, + target, + position = "center", + topOffset, + externalSetOpen, + ...props +}: TWUI_DROPDOWN_PROPS) { + const [open, setOpen] = React.useState(false); + + const dropdownRef = React.useRef(null); + + const handleClickOutside = React.useCallback((e: MouseEvent) => { + const targetEl = e.target as HTMLElement; + const closestWrapper = targetEl.closest(".twui-dropdown-wrapper"); + + if (!closestWrapper) { + externalSetOpen?.(false); + return setOpen(false); + } + if (closestWrapper && closestWrapper !== dropdownRef.current) { + externalSetOpen?.(false); + return setOpen(false); + } + }, []); + + React.useEffect(() => { + document.addEventListener("click", handleClickOutside); + return () => { + document.removeEventListener("click", handleClickOutside); + }; + }, []); + + return ( +
{ + if (!hoverOpen) return; + window.clearTimeout(timeout); + externalSetOpen?.(true); + setOpen(true); + }} + onMouseLeave={() => { + if (!hoverOpen) return; + timeout = setTimeout(() => { + externalSetOpen?.(false); + setOpen(false); + }, debounce); + }} + onBlur={() => { + window.clearTimeout(timeout); + }} + ref={dropdownRef} + > +
{ + externalSetOpen?.(!open); + setOpen(!open); + }} + className={twMerge( + "cursor-pointer", + "twui-dropdown-target", + targetWrapperProps?.className + )} + > + {target} +
+ +
{ + if (!hoverOpen) return; + window.clearTimeout(timeout); + }} + onBlur={() => { + if (!hoverOpen) return; + window.clearTimeout(timeout); + }} + style={{ + top: `calc(100% + ${topOffset || 0}px)`, + ...contentWrapperProps?.style, + }} + > + {props.children} +
+
+ ); +} diff --git a/components/lib/elements/Modal.tsx b/components/lib/elements/Modal.tsx index f48277d..eb9b0e0 100644 --- a/components/lib/elements/Modal.tsx +++ b/components/lib/elements/Modal.tsx @@ -8,6 +8,7 @@ type Props = DetailedHTMLProps< HTMLDivElement > & { target: React.ReactNode; + targetRef?: React.MutableRefObject; }; /** @@ -15,11 +16,12 @@ type Props = DetailedHTMLProps< * @className_wrapper twui-modal-root * @className_wrapper twui-modal */ -export default function Modal({ target, ...props }: Props) { +export default function Modal({ target, targetRef, ...props }: Props) { const [wrapper, setWrapper] = React.useState(null); React.useEffect(() => { const wrapperEl = document.createElement("div"); + wrapperEl.className = twMerge( "fixed z-[200000] top-0 left-0 w-screen h-screen", "flex flex-col items-center justify-center", @@ -57,6 +59,7 @@ export default function Modal({ target, ...props }: Props) { const root = createRoot(wrapper); root.render(modalEl); }} + ref={targetRef as any} > {target}
diff --git a/components/lib/elements/Paper.tsx b/components/lib/elements/Paper.tsx index 3346ba0..da526ca 100644 --- a/components/lib/elements/Paper.tsx +++ b/components/lib/elements/Paper.tsx @@ -20,7 +20,7 @@ export default function Paper({
= DetailedHTMLProps< React.HTMLAttributes, HTMLDivElement > & { dispatch?: (value?: string) => void; delay?: number; - inputProps?: DetailedHTMLProps< - InputHTMLAttributes, - HTMLInputElement - > & - DetailedHTMLProps< - TextareaHTMLAttributes, - HTMLTextAreaElement - >; + inputProps?: InputProps; buttonProps?: DetailedHTMLProps< React.ButtonHTMLAttributes, HTMLButtonElement @@ -37,13 +30,13 @@ export type SearchProps = DetailedHTMLProps< * @className_circle twui-search-input * @className_circle twui-search-button */ -export default function Search({ +export default function Search({ dispatch, delay = 500, inputProps, buttonProps, ...props -}: SearchProps) { +}: SearchProps) { const [input, setInput] = React.useState(""); React.useEffect(() => { diff --git a/components/lib/elements/StarRating.tsx b/components/lib/elements/StarRating.tsx new file mode 100644 index 0000000..0dfab43 --- /dev/null +++ b/components/lib/elements/StarRating.tsx @@ -0,0 +1,164 @@ +import { LucideProps, Star } from "lucide-react"; +import React, { + DetailedHTMLProps, + ForwardRefExoticComponent, + HTMLAttributes, + RefAttributes, +} from "react"; +import { twMerge } from "tailwind-merge"; + +type StarProps = { + total?: number; + value?: number; + size?: number; + starProps?: LucideProps; + allowRating?: boolean; + setValueExternal?: React.Dispatch>; +}; + +export type TWUI_STAR_RATING_PROPS = DetailedHTMLProps< + HTMLAttributes, + HTMLDivElement +> & + StarProps; + +let timeout: any; + +/** + * # Star Rating Component + * @className_wrapper twui-star-rating + */ +export default function StarRating({ + total = 5, + value = 0, + size, + starProps, + allowRating, + setValueExternal, + ...props +}: TWUI_STAR_RATING_PROPS) { + const totalArray = Array(total).fill(null); + + const [finalValue, setFinalValue] = React.useState(value); + const [selectedStarValue, setSelectedStarValue] = React.useState(value); + + const starClicked = React.useRef(false); + const sectionHovered = React.useRef(false); + + React.useEffect(() => { + window.clearTimeout(timeout); + timeout = setTimeout(() => { + setValueExternal?.(finalValue); + }, 500); + }, [selectedStarValue]); + + return ( +
{ + sectionHovered.current = true; + }} + onMouseLeave={() => { + sectionHovered.current = false; + }} + > + {totalArray.map((_, index) => { + return ( + + ); + })} +
+ ); +} + +function StarComponent({ + value = 0, + size = 20, + starProps, + index, + allowRating, + finalValue, + setFinalValue, + starClicked, + sectionHovered, + setSelectedStarValue, + selectedStarValue, +}: StarProps & { + index: number; + finalValue: number; + setFinalValue: React.Dispatch>; + setSelectedStarValue: React.Dispatch>; + starClicked: React.MutableRefObject; + sectionHovered: React.MutableRefObject; + selectedStarValue: number; +}) { + const isActive = index < finalValue; + + return ( +
{ + if (!allowRating) return; + + setFinalValue(index + 1); + }} + onMouseLeave={() => { + if (!allowRating) return; + + setTimeout(() => { + if (sectionHovered.current) { + return; + } + + if (!starClicked.current) { + setFinalValue(0); + } + + if (selectedStarValue) { + setFinalValue(selectedStarValue); + } + }, 200); + }} + onClick={() => { + if (!allowRating) return; + + starClicked.current = true; + setSelectedStarValue(index + 1); + }} + > + +
+ ); +} diff --git a/components/lib/elements/Tabs.tsx b/components/lib/elements/Tabs.tsx new file mode 100644 index 0000000..f2e3f78 --- /dev/null +++ b/components/lib/elements/Tabs.tsx @@ -0,0 +1,108 @@ +import React, { DetailedHTMLProps, HTMLAttributes } from "react"; +import { twMerge } from "tailwind-merge"; +import Border from "./Border"; +import Stack from "../layout/Stack"; +import Row from "../layout/Row"; +import Span from "../layout/Span"; + +export type TWUITabsObject = { + title: string; + value: string; + content: React.ReactNode; + defaultActive?: boolean; +}; + +export type TWUI_TOGGLE_PROPS = React.ComponentProps & { + tabsContentArray: TWUITabsObject[]; + tabsBorderProps?: React.ComponentProps; + tabsButtonsWrapperProps?: React.DetailedHTMLProps< + React.HTMLAttributes, + HTMLDivElement + >; + centered?: boolean; + debounce?: number; +}; + +/** + * # Tabs Component + * @className twui-tabs-wrapper + * @className twui-tab-buttons + * @className twui-tab-button-active + * @className twui-tab-buttons-wrapper + */ +export default function Tabs({ + tabsContentArray, + tabsBorderProps, + tabsButtonsWrapperProps, + centered, + debounce = 100, + ...props +}: TWUI_TOGGLE_PROPS) { + const values = tabsContentArray.map((obj) => obj.value); + + const [activeValue, setActiveValue] = React.useState( + tabsContentArray.find((ctn) => ctn.defaultActive)?.value || + values[0] || + undefined + ); + + const targetContent = tabsContentArray.find( + (ctn) => ctn.value == activeValue + ); + + return ( + +
+ + + {values.map((value, index) => { + const targetObject = tabsContentArray.find( + (ctn) => ctn.value == value + ); + + const isActive = value == activeValue; + + return ( + { + setActiveValue(undefined); + setTimeout(() => { + setActiveValue(value); + }, debounce); + }} + key={index} + > + {targetObject?.title} + + ); + })} + + +
+ {targetContent?.content} +
+ ); +} diff --git a/components/lib/elements/Tag.tsx b/components/lib/elements/Tag.tsx new file mode 100644 index 0000000..fae2eff --- /dev/null +++ b/components/lib/elements/Tag.tsx @@ -0,0 +1,75 @@ +import React, { PropsWithChildren } from "react"; +import { twMerge } from "tailwind-merge"; + +export type TWUITabsObject = { + title: string; + value: string; + content: React.ReactNode; + defaultActive?: boolean; +}; + +export type TWUI_TOGGLE_PROPS = PropsWithChildren & + React.DetailedHTMLProps< + React.HTMLAttributes, + HTMLDivElement + > & { + color?: "normal" | "secondary" | "error" | "success" | "gray"; + variant?: "normal" | "outlined" | "ghost"; + }; + +/** + * # Tabs Component + * @className twui-tag + */ +export default function Tag({ + color, + variant, + children, + ...props +}: TWUI_TOGGLE_PROPS) { + return ( +
+ {children} +
+ ); +} diff --git a/components/lib/elements/Toast.tsx b/components/lib/elements/Toast.tsx new file mode 100644 index 0000000..1fb481b --- /dev/null +++ b/components/lib/elements/Toast.tsx @@ -0,0 +1,100 @@ +import React, { DetailedHTMLProps, HTMLAttributes } from "react"; +import { twMerge } from "tailwind-merge"; +import { createRoot } from "react-dom/client"; +import Card from "./Card"; +import { X } from "lucide-react"; +import Span from "../layout/Span"; + +export const ToastStyles = ["normal", "success", "error"] as const; +export const ToastColors = ToastStyles; + +type Props = DetailedHTMLProps< + HTMLAttributes, + HTMLDivElement +> & { + open?: boolean; + setOpen?: React.Dispatch>; + closeDelay?: number; + color?: (typeof ToastStyles)[number]; +}; + +/** + * # Toast Component + * @className twui-toast-root + * @className twui-toast + * @className twui-toast-success + * @className twui-toast-error + */ +export default function Toast({ + open, + setOpen, + closeDelay = 4000, + color, + ...props +}: Props) { + if (!open) return null; + + const toastEl = ( + + { + const targetEl = e.target as HTMLElement; + const rootWrapperEl = targetEl.closest(".twui-toast-root"); + + if (rootWrapperEl) { + rootWrapperEl.parentElement?.removeChild(rootWrapperEl); + setOpen?.(false); + } + }} + > + + + {props.children} + + ); + + React.useEffect(() => { + const wrapperEl = document.createElement("div"); + + wrapperEl.className = twMerge( + "fixed z-[200000] bottom-10 right-10", + "flex flex-col items-center justify-center", + "twui-toast-root" + ); + + document.body.appendChild(wrapperEl); + const root = createRoot(wrapperEl); + root.render(toastEl); + + setTimeout(() => { + closeToast({ wrapperEl }); + setOpen?.(false); + }, closeDelay); + + return function () { + closeToast({ wrapperEl }); + }; + }, []); + + return null; +} + +function closeToast({ wrapperEl }: { wrapperEl: HTMLDivElement | null }) { + if (!wrapperEl) return; + wrapperEl.parentElement?.removeChild(wrapperEl); +} diff --git a/components/lib/form/Checkbox.tsx b/components/lib/form/Checkbox.tsx new file mode 100644 index 0000000..7819ae6 --- /dev/null +++ b/components/lib/form/Checkbox.tsx @@ -0,0 +1,98 @@ +import React, { + DetailedHTMLProps, + HTMLAttributes, + InputHTMLAttributes, + ReactNode, +} from "react"; +import { twMerge } from "tailwind-merge"; +import CheckMarkSVG from "../svgs/CheckMarkSVG"; + +export type CheckboxProps = DetailedHTMLProps< + InputHTMLAttributes, + HTMLInputElement +> & { + name: string; + wrapperProps?: DetailedHTMLProps< + HTMLAttributes, + HTMLDivElement + >; + label?: string | ReactNode; + labelProps?: DetailedHTMLProps< + HTMLAttributes, + HTMLLabelElement + >; + defaultChecked?: boolean; + wrapperClassName?: string; + setChecked?: React.Dispatch>; +}; + +/** + * # Checkbox Component + * @className twui-checkbox + * @className twui-checkbox-checked + * @className twui-checkbox-unchecked + */ +export default function Checkbox({ + wrapperProps, + label, + labelProps, + size, + name, + wrapperClassName, + defaultChecked, + setChecked, + ...props +}: CheckboxProps) { + const finalSize = size || 20; + + const [internalChecked, setInternalChecked] = React.useState( + defaultChecked || false + ); + + const checkMarkRef = React.useRef(); + + return ( +
{ + checkMarkRef.current?.click(); + wrapperProps?.onClick?.(e); + }} + className={twMerge( + "flex items-center gap-2", + wrapperClassName, + wrapperProps?.className + )} + > + { + setInternalChecked(e.target.checked); + setChecked?.(e.target.checked); + }} + ref={checkMarkRef as any} + /> +
+ {internalChecked && } +
+ {label && } +
+ ); +} diff --git a/components/lib/form/Form.tsx b/components/lib/form/Form.tsx index b0d92eb..4baecd1 100644 --- a/components/lib/form/Form.tsx +++ b/components/lib/form/Form.tsx @@ -1,3 +1,4 @@ +import _ from "lodash"; import { DetailedHTMLProps, FormHTMLAttributes } from "react"; import { twMerge } from "tailwind-merge"; @@ -5,17 +6,28 @@ import { twMerge } from "tailwind-merge"; * # Form Element * @className twui-form */ -export default function Form({ +export default function Form({ ...props -}: DetailedHTMLProps, HTMLFormElement>) { +}: DetailedHTMLProps, HTMLFormElement> & { + submitHandler?: (e: React.FormEvent, data: T) => void; +}) { + const finalProps = _.omit(props, "submitHandler"); + return (
{ + e.preventDefault(); + const formEl = e.target as HTMLFormElement; + const formData = new FormData(formEl); + const data = Object.fromEntries(formData.entries()) as T; + props.submitHandler?.(e, data); + }} > {props.children}
diff --git a/components/lib/form/ImageUpload.tsx b/components/lib/form/ImageUpload.tsx index 9869aad..f87f096 100644 --- a/components/lib/form/ImageUpload.tsx +++ b/components/lib/form/ImageUpload.tsx @@ -1,25 +1,24 @@ -import Button from "@/components/lib/layout/Button"; -import Stack from "@/components/lib/layout/Stack"; +import Button from "../layout/Button"; +import Stack from "../layout/Stack"; import { ImagePlus, X } from "lucide-react"; import React, { DetailedHTMLProps } from "react"; -import Card from "@/components/lib/elements/Card"; -import Span from "@/components/lib/layout/Span"; -import Center from "@/components/lib/layout/Center"; +import Card from "../elements/Card"; +import Span from "../layout/Span"; +import Center from "../layout/Center"; import imageInputToBase64, { ImageInputToBase64FunctionReturn, } from "../utils/form/imageInputToBase64"; import { twMerge } from "tailwind-merge"; -type ImageUploadProps = { +type ImageUploadProps = DetailedHTMLProps< + React.HTMLAttributes, + HTMLDivElement +> & { onChange?: (imgData: ImageInputToBase64FunctionReturn | undefined) => any; fileInputProps?: DetailedHTMLProps< React.InputHTMLAttributes, HTMLInputElement >; - wrapperProps?: DetailedHTMLProps< - React.HTMLAttributes, - HTMLDivElement - >; placeHolderWrapper?: DetailedHTMLProps< React.HTMLAttributes, HTMLDivElement @@ -32,23 +31,27 @@ type ImageUploadProps = { React.ImgHTMLAttributes, HTMLImageElement >; + label?: string; + disablePreview?: boolean; }; export default function ImageUpload({ onChange, fileInputProps, - wrapperProps, placeHolderWrapper, previewImageWrapperProps, previewImageProps, + label, + disablePreview, + ...props }: ImageUploadProps) { const [src, setSrc] = React.useState(undefined); const inputRef = React.useRef(); return ( {src ? ( - - + + {disablePreview ? ( + + Image Uploaded! + + ) : ( + + )} ) : ( { @@ -98,7 +110,7 @@ export default function ImageUpload({ - Click to Upload Image + {label || "Click to Upload Image"} diff --git a/components/lib/form/Input.tsx b/components/lib/form/Input.tsx index e02050f..7e145de 100644 --- a/components/lib/form/Input.tsx +++ b/components/lib/form/Input.tsx @@ -6,8 +6,79 @@ import React, { TextareaHTMLAttributes, } from "react"; import { twMerge } from "tailwind-merge"; +import Span from "../layout/Span"; -export type InputProps = DetailedHTMLProps< +let timeout: any; + +const autocompleteOptions = [ + // Personal Information + "name", + "honorific-prefix", + "given-name", + "additional-name", + "family-name", + "honorific-suffix", + "nickname", + + // Contact Information + "email", + "username", + "new-password", + "current-password", + "one-time-code", + "organization-title", + "organization", + + // Address Fields + "street-address", + "address-line1", + "address-line2", + "address-line3", + "address-level4", + "address-level3", + "address-level2", + "address-level1", + "country", + "country-name", + "postal-code", + + // Phone Numbers + "tel", + "tel-country-code", + "tel-national", + "tel-area-code", + "tel-local", + "tel-extension", + + // Dates + "bday", + "bday-day", + "bday-month", + "bday-year", + + // Payment Information + "cc-name", + "cc-given-name", + "cc-additional-name", + "cc-family-name", + "cc-number", + "cc-exp", + "cc-exp-month", + "cc-exp-year", + "cc-csc", + "cc-type", + + // Additional Options + "sex", + "url", + "photo", + + // Special Values + "on", // Enables autofill (default) + "off", // Disables autofill +] as const; + +export type InputProps = DetailedHTMLProps< InputHTMLAttributes, HTMLInputElement > & @@ -30,13 +101,21 @@ export type InputProps = DetailedHTMLProps< HTMLLabelElement >; componentRef?: RefObject; + validationRegex?: RegExp; + debounce?: number; + invalidMessage?: string; + validationFunction?: (value: string) => Promise; + autoComplete?: (typeof autocompleteOptions)[number]; + name?: KeyType; }; /** * # Input Element * @className twui-input + * @className twui-input-wrapper + * @className twui-input-invalid */ -export default function Input({ +export default function Input({ label, variant, prefix, @@ -46,9 +125,43 @@ export default function Input({ wrapperProps, showLabel, istextarea, + debounce, + invalidMessage, + autoComplete, + validationFunction, + validationRegex, ...props -}: InputProps) { +}: InputProps) { const [focus, setFocus] = React.useState(false); + const [value, setValue] = React.useState( + props.defaultValue ? String(props.defaultValue) : "" + ); + + delete props.defaultValue; + + const [isValid, setIsValid] = React.useState(true); + + const DEFAULT_DEBOUNCE = 500; + const finalDebounce = debounce || DEFAULT_DEBOUNCE; + + React.useEffect(() => { + if (!value.match(/./)) return setIsValid(true); + window.clearTimeout(timeout); + + if (validationRegex) { + timeout = setTimeout(() => { + setIsValid(validationRegex.test(value)); + }, finalDebounce); + } + + if (validationFunction) { + timeout = setTimeout(() => { + validationFunction(value).then((res) => { + setIsValid(res); + }); + }, finalDebounce); + } + }, [value]); const targetComponent = istextarea ? (