tldraw/packages/ui/api-report.md
Steve Ruiz a1e72014c6
[improvement] refactor paste to support multi-line text (#1398)
This PR refactors our clipboard handlers. It should simplify the way
that things work and better handle the difference between how the native
API events are handled vs. the browser's clipboard API events.

![Kapture 2023-05-17 at 13 26
34](https://github.com/tldraw/tldraw/assets/23072548/5dedcc25-a1d2-423f-8bc2-415f761b643b)

Everything that used to be supported now also still works.

In addition, we now have several useful features:

### Multiline text can be pasted into the app

When pasting text that contains more than one line, the text is pasted
correctly; even if the clipboard also includes HTML data. Previously, we
would try to paste HTML data if we found it, because that data might
contain tldraw's own content as a comment; but if that failed, we would
paste the data as text instead. This led to pasting text that lost lots
of information from that text, such as line breaks and indentations.

### Multiline text shapes are aligned correctly

When pasting raw text that has more than one line, the text will be left
aligned—or right aligned if the text is likely from a RTL language.

![Kapture 2023-05-17 at 13 42
54](https://github.com/tldraw/tldraw/assets/23072548/f705acd5-136c-4144-80da-6e97ff766a58)

### Common minimum indentation is removed from each line

![Kapture 2023-05-17 at 13 56
28](https://github.com/tldraw/tldraw/assets/23072548/d45c95f6-6d28-4c9f-8cd3-8078700ce928)

This is something that absolutely every app should implement, but here
we go. When multiline text has "common indentation" on each line, which
is often the case when pasting text from code, then that indentation is
removed from each line.

### Auto wrapping for big pastes

When a line has no text breaks but a lot of text, we now set the width
of the text shape.

![Kapture 2023-05-17 at 14 00
04](https://github.com/tldraw/tldraw/assets/23072548/0b7f69c3-bcf9-42e9-a1ed-df026f868793)

## How it works

A `ClipboardThing` is the common interface for things that we found on
the clipboard, native or otherwise. Both `handlePasteFromClipboardApi`
and `handlePasteFromEventClipboardData` parse out `ClipboardThing`s and
pass them to `handleClipboardThings`.

<img width="905" alt="image"
src="https://github.com/tldraw/tldraw/assets/23072548/fd087539-edbb-4527-b5ff-ca7d7c1726b2">

A `ClipboardResult` is the result of processing a `ClipboardThing`, and
usually contains text and other information about that text. We make
decisions on what to create based on which `ClipboardResult`s we find.

When pasting text, we check to see whether the result would be bigger
than the viewport, or if the text is multiline, or if the text is of an
RTL language by testing certain common RTL characters. We make some
adjustments based on those factors, ensuring that the top-left corner of
the text is on screen and reasonably positioned within the viewport if
possible.

### Change Type

- [x] `minor` — New Feature

### Test Plan

1. Copy and paste shapes
2. Copy and paste text from elsewhere into the app
3. Copy and paste images from elsewhere into the app
4. Try on different browsers

### Release Notes

- Improves clipboard logic when pasting text
- Adds support for pasting multi-line text
- Adds maximum widths when pasting single-line text
- Adds support for RTL languages when pasting multi-line or wrapped text
- Strips leading indentation when pasting text
2023-05-17 16:32:25 +00:00

42 KiB

API Report File for "@tldraw/ui"

Do not edit this file. It is a report generated by API Extractor.


/// <reference types="react" />

import { App } from '@tldraw/editor';
import { Context } from 'react';
import { EditorAssetUrls } from '@tldraw/editor';
import { EMBED_DEFINITIONS } from '@tldraw/editor';
import { MemoExoticComponent } from 'react';
import { NamedExoticComponent } from 'react';
import { default as React_2 } from 'react';
import * as React_3 from 'react';
import { ReactNode } from 'react';
import { TLCopyType } from '@tldraw/editor';
import { TLExportType } from '@tldraw/editor';
import { TLShapeId } from '@tldraw/editor';
import { TLStyleItem } from '@tldraw/editor';
import { TLStyleType } from '@tldraw/editor';
import { VecLike } from '@tldraw/primitives';

// @public (undocumented)
export interface ActionItem {
    // (undocumented)
    checkbox?: boolean;
    // (undocumented)
    contextMenuLabel?: TLTranslationKey;
    // (undocumented)
    icon?: TLUiIconType;
    // (undocumented)
    id: string;
    // (undocumented)
    kbd?: string;
    // (undocumented)
    label?: TLTranslationKey;
    // (undocumented)
    menuLabel?: TLTranslationKey;
    // (undocumented)
    onSelect: (source: TLUiEventSource) => Promise<void> | void;
    // (undocumented)
    readonlyOk: boolean;
    // (undocumented)
    shortcutsLabel?: TLTranslationKey;
    // (undocumented)
    title?: string;
}

// @public (undocumented)
export const ActionsContext: React_3.Context<ActionsContextType>;

// @public (undocumented)
export type ActionsContextType = Record<string, ActionItem>;

// @public (undocumented)
export const ActionsMenuSchemaContext: React_2.Context<MenuSchema>;

// @public (undocumented)
export type ActionsMenuSchemaContextType = MenuSchema;

// @public (undocumented)
export const ActionsMenuSchemaProvider: MemoExoticComponent<({ overrides, children, }: ActionsMenuSchemaProviderProps) => JSX.Element>;

// @public (undocumented)
export type ActionsMenuSchemaProviderProps = {
    overrides?: (app: App, schema: ActionsMenuSchemaContextType, helpers: {
        actions: ReturnType<typeof useActions>;
        oneSelected: boolean;
        twoSelected: boolean;
        threeSelected: boolean;
    }) => ActionsMenuSchemaContextType;
    children: any;
};

// @public (undocumented)
export function ActionsProvider({ overrides, children }: ActionsProviderProps): JSX.Element;

// @public (undocumented)
export type ActionsProviderProps = {
    overrides?: (app: App, actions: ActionsContextType, helpers: undefined) => ActionsContextType;
    children: any;
};

// @public (undocumented)
export function AssetUrlsProvider({ assetUrls, children, }: {
    assetUrls: UiAssetUrls;
    children: React.ReactNode;
}): JSX.Element;

// @public (undocumented)
export const BASE_URL: string;

// @public (undocumented)
function Body_2({ className, children, style, }: {
    className?: string;
    children: any;
    style?: React.CSSProperties;
}): JSX.Element;

// @public (undocumented)
export function BreakPointProvider({ children }: {
    children: any;
}): JSX.Element;

// @public (undocumented)
export const Button: React_3.ForwardRefExoticComponent<ButtonProps & React_3.RefAttributes<HTMLButtonElement>>;

// @public (undocumented)
export const ButtonPicker: React_3.MemoExoticComponent<typeof _ButtonPicker>;

// @public (undocumented)
export interface ButtonPickerProps<T extends TLStyleItem> {
    // (undocumented)
    'data-wd'?: string;
    // (undocumented)
    columns?: 2 | 3 | 4;
    // (undocumented)
    items: T[];
    // (undocumented)
    onValueChange: (item: T, squashing: boolean) => void;
    // (undocumented)
    styleType: TLStyleType;
    // (undocumented)
    title: string;
    // (undocumented)
    value?: null | number | string;
}

// @public (undocumented)
export interface ButtonProps extends React_3.HTMLAttributes<HTMLButtonElement> {
    // (undocumented)
    disabled?: boolean;
    // (undocumented)
    icon?: TLUiIconType;
    // (undocumented)
    iconLeft?: TLUiIconType;
    // (undocumented)
    invertIcon?: boolean;
    // (undocumented)
    isChecked?: boolean;
    // (undocumented)
    kbd?: string;
    // (undocumented)
    label?: TLTranslationKey;
    // (undocumented)
    loading?: boolean;
    // (undocumented)
    smallIcon?: boolean;
    // (undocumented)
    spinner?: boolean;
    // (undocumented)
    type?: 'danger' | 'normal' | 'primary';
}

// @public (undocumented)
function CheckboxItem({ children, onSelect, ...rest }: DropdownMenuCheckboxItemProps): JSX.Element;

// @public (undocumented)
function CloseButton(): JSX.Element;

// @public (undocumented)
export function compactMenuItems<T>(arr: T[]): Exclude<T, false | null | undefined>[];

// @public (undocumented)
function Content({ side, align, sideOffset, alignOffset, children, }: {
    children: any;
    alignOffset?: number;
    sideOffset?: number;
    align?: 'center' | 'end' | 'start';
    side?: 'bottom' | 'left' | 'right' | 'top';
}): JSX.Element;

// @public (undocumented)
export const ContextMenu: ({ children }: {
    children: any;
}) => JSX.Element;

// @public (undocumented)
export interface ContextMenuProps {
    // (undocumented)
    children: any;
}

// @public (undocumented)
export const ContextMenuSchemaContext: React_2.Context<MenuSchema>;

// @public (undocumented)
export type ContextMenuSchemaContextType = MenuSchema;

// @public (undocumented)
export const ContextMenuSchemaProvider: MemoExoticComponent<({ overrides, children, }: ContextMenuSchemaProviderProps) => JSX.Element>;

// @public (undocumented)
export type ContextMenuSchemaProviderProps = {
    overrides?: (app: App, schema: ContextMenuSchemaContextType, helpers: {
        actions: ReturnType<typeof useActions>;
        oneSelected: boolean;
        twoSelected: boolean;
        threeSelected: boolean;
        showAutoSizeToggle: boolean;
        showUngroup: boolean;
        onlyFlippableShapeSelected: boolean;
    }) => ContextMenuSchemaContextType;
    children: any;
};

// @public (undocumented)
export type CustomMenuItem = {
    id: string;
    type: 'custom';
    disabled: boolean;
    readonlyOk: boolean;
};

// @public (undocumented)
export const DebugPanel: React_3.NamedExoticComponent<{
    renderDebugMenuItems: (() => React_3.ReactNode) | null;
}>;

declare namespace Dialog {
    export {
        Header,
        Title,
        CloseButton,
        Body_2 as Body,
        Footer
    }
}
export { Dialog }

// @public (undocumented)
export interface DialogProps {
    // (undocumented)
    onClose: () => void;
}

// @public (undocumented)
export const DialogsContext: Context<DialogsContextType>;

// @public (undocumented)
export type DialogsContextType = {
    addDialog: (dialog: Omit<TLDialog, 'id'> & {
        id?: string;
    }) => string;
    removeDialog: (id: string) => string;
    updateDialog: (id: string, newDialogData: Partial<TLDialog>) => string;
    clearDialogs: () => void;
    dialogs: TLDialog[];
};

// @public (undocumented)
export function DialogsProvider({ children }: DialogsProviderProps): JSX.Element;

// @public (undocumented)
export type DialogsProviderProps = {
    overrides?: (app: App) => DialogsContextType;
    children: any;
};

declare namespace DropdownMenu {
    export {
        Root,
        Trigger,
        Content,
        Sub,
        SubTrigger,
        SubContent,
        Group,
        Indicator,
        Item,
        CheckboxItem,
        RadioItem,
        DropdownMenuItemProps,
        DropdownMenuCheckboxItemProps
    }
}
export { DropdownMenu }

// @public (undocumented)
interface DropdownMenuCheckboxItemProps {
    // (undocumented)
    checked?: boolean;
    // (undocumented)
    children: any;
    // (undocumented)
    disabled?: boolean;
    // (undocumented)
    onSelect?: (e: Event) => void;
    // (undocumented)
    title: string;
}

// @public (undocumented)
interface DropdownMenuItemProps extends ButtonProps {
    // (undocumented)
    noClose?: boolean;
}

// @public (undocumented)
export const EN_TRANSLATION: TLTranslation;

// @public (undocumented)
export type EventsProviderProps = {
    onEvent?: TLUiEventHandler;
    children: any;
};

// @public (undocumented)
export function fetchTranslation(locale: TLTranslationLocale, assetUrls: UiAssetUrls): Promise<TLTranslation>;

// @public (undocumented)
export function findMenuItem(menu: MenuSchema, path: string[]): MenuChild;

// @public (undocumented)
function Footer({ className, children }: {
    className?: string;
    children: any;
}): JSX.Element;

// @public (undocumented)
export const getBaseUrl: () => string;

// @public (undocumented)
export function getTranslation(locale: TLTranslationLocale, assetUrls: UiAssetUrls): Promise<TLTranslation>;

// @public (undocumented)
function Group({ children, size, }: {
    children: any;
    size?: 'medium' | 'small' | 'tiny' | 'wide';
}): JSX.Element;

// @public (undocumented)
function Header({ className, children }: {
    className?: string;
    children: any;
}): JSX.Element;

// @public (undocumented)
export const HelpMenu: React_3.NamedExoticComponent<object>;

// @public (undocumented)
export interface HelpMenuProps {
    // (undocumented)
    links?: HelpMenuLink[];
}

// @internal (undocumented)
export const HelpMenuSchemaContext: React_2.Context<MenuSchema>;

// @public (undocumented)
export const HelpMenuSchemaProvider: MemoExoticComponent<({ overrides, children, }: HelpMenuSchemaProviderProps) => JSX.Element>;

// @public (undocumented)
export type HelpMenuSchemaProviderProps = {
    overrides?: (app: App, schema: HelpMenuSchemaProviderType, helpers: {
        actions: ReturnType<typeof useActions>;
        languages: TLListedTranslations;
        currentLanguage: string;
        oneSelected: boolean;
        twoSelected: boolean;
        threeSelected: boolean;
    }) => HelpMenuSchemaProviderType;
    children: any;
};

// @public (undocumented)
export type HelpMenuSchemaProviderType = MenuSchema;

// @public (undocumented)
export const HTMLCanvas: MemoExoticComponent<() => JSX.Element>;

// @public (undocumented)
export const Icon: NamedExoticComponent<IconProps>;

// @public (undocumented)
export interface IconProps extends React.HTMLProps<HTMLDivElement> {
    // (undocumented)
    children?: undefined;
    // (undocumented)
    color?: string;
    // (undocumented)
    crossOrigin?: 'anonymous' | 'use-credentials';
    // (undocumented)
    icon: TLUiIconType;
    // (undocumented)
    invertIcon?: boolean;
    // (undocumented)
    small?: boolean;
}

// @public (undocumented)
function Indicator(): JSX.Element;

// @public (undocumented)
export const Input: React_3.ForwardRefExoticComponent<InputProps & React_3.RefAttributes<HTMLInputElement>>;

// @public (undocumented)
export interface InputProps {
    // (undocumented)
    autofocus?: boolean;
    // (undocumented)
    autoselect?: boolean;
    // (undocumented)
    children?: any;
    // (undocumented)
    className?: string;
    // (undocumented)
    defaultValue?: string;
    // (undocumented)
    disabled?: boolean;
    // (undocumented)
    icon?: TLUiIconType;
    // (undocumented)
    iconLeft?: TLUiIconType;
    // (undocumented)
    label?: TLTranslationKey;
    // (undocumented)
    onCancel?: (value: string) => void;
    // (undocumented)
    onComplete?: (value: string) => void;
    // (undocumented)
    onValueChange?: (value: string) => void;
    // (undocumented)
    placeholder?: string;
    shouldManuallyMaintainScrollPositionWhenFocused?: boolean;
    // (undocumented)
    value?: string;
}

// @public (undocumented)
function Item({ noClose, ...props }: DropdownMenuItemProps): JSX.Element;

// @public (undocumented)
export function Kbd({ children }: KbdProps): JSX.Element;

// @public (undocumented)
export function kbd(str: string): string[];

// @public (undocumented)
export interface KbdProps {
    // (undocumented)
    children: string;
}

// @public (undocumented)
export function kbdStr(str: string): string;

// @public (undocumented)
export const KeyboardShortcutsSchemaContext: React_2.Context<MenuSchema>;

// @public (undocumented)
export type KeyboardShortcutsSchemaContextType = MenuSchema;

// @public (undocumented)
export const KeyboardShortcutsSchemaProvider: MemoExoticComponent<({ overrides, children, }: KeyboardShortcutsSchemaProviderProps) => JSX.Element>;

// @public (undocumented)
export type KeyboardShortcutsSchemaProviderProps = {
    overrides?: (app: App, schema: KeyboardShortcutsSchemaContextType, more: {
        tools: ToolsContextType;
        actions: ActionsContextType;
    }) => KeyboardShortcutsSchemaContextType;
    children: any;
};

// @public (undocumented)
export type MenuChild = CustomMenuItem | MenuGroup | MenuItem | SubMenu;

// @public (undocumented)
export function menuCustom(id: string, opts?: Partial<{
    readonlyOk: boolean;
    disabled: boolean;
}>): {
    id: string;
    type: "custom";
    disabled: boolean;
    readonlyOk: boolean;
};

// @public (undocumented)
export type MenuGroup = {
    id: string;
    type: 'group';
    checkbox: boolean;
    disabled: boolean;
    readonlyOk: boolean;
    children: MenuChild[];
};

// @public (undocumented)
export function menuGroup(id: string, ...children: (false | MenuChild | null)[]): MenuGroup | null;

// @public (undocumented)
export type MenuItem = {
    id: string;
    type: 'item';
    readonlyOk: boolean;
    actionItem: ActionItem;
    disabled: boolean;
    checked: boolean;
};

// @public (undocumented)
export function menuItem(actionItem: ActionItem | ToolItem, opts?: Partial<{
    checked: boolean;
    disabled: boolean;
}>): MenuItem;

// @public (undocumented)
export type MenuSchema = (CustomMenuItem | MenuGroup | MenuItem)[];

// @public (undocumented)
export const MenuSchemaContext: React_2.Context<MenuSchema>;

// @public (undocumented)
export type MenuSchemaContextType = MenuSchema;

// @public (undocumented)
export function MenuSchemaProvider({ overrides, children }: MenuSchemaProviderProps): JSX.Element;

// @public (undocumented)
export type MenuSchemaProviderProps = {
    overrides?: (app: App, schema: MenuSchemaContextType, helpers: {
        actions: ReturnType<typeof useActions>;
        noneSelected: boolean;
        oneSelected: boolean;
        twoSelected: boolean;
        threeSelected: boolean;
    }) => MenuSchemaContextType;
    children: any;
};

// @public (undocumented)
export function menuSubmenu(id: string, label: TLTranslationKey, ...children: (false | MenuChild | null)[]): null | SubMenu;

// @public (undocumented)
export const NavigationZone: NamedExoticComponent<object>;

// @public (undocumented)
function RadioItem({ children, onSelect, ...rest }: DropdownMenuCheckboxItemProps): JSX.Element;

// @public (undocumented)
function Root({ id, children, modal, }: {
    id: string;
    children: any;
    modal?: boolean;
}): JSX.Element;

// @internal (undocumented)
export function setDefaultUiAssetUrls(urls: UiAssetUrls): void;

// @public (undocumented)
export function Slider(props: SliderProps): JSX.Element;

// @public (undocumented)
export interface SliderProps {
    // (undocumented)
    'data-wd'?: string;
    // (undocumented)
    label: string;
    // (undocumented)
    onValueChange: (value: number, emphemeral: boolean) => void;
    // (undocumented)
    steps: number;
    // (undocumented)
    title: string;
    // (undocumented)
    value: null | number;
}

// @public (undocumented)
export const StylePanel: ({ isMobile }: StylePanelProps) => JSX.Element | null;

// @public (undocumented)
function Sub({ id, children }: {
    id: string;
    children: any;
}): JSX.Element;

// @public (undocumented)
function SubContent({ alignOffset, sideOffset, children, }: {
    alignOffset?: number;
    sideOffset?: number;
    children: any;
}): JSX.Element;

// @public (undocumented)
export type SubMenu = {
    id: string;
    type: 'submenu';
    label: TLTranslationKey;
    disabled: boolean;
    readonlyOk: boolean;
    children: MenuChild[];
};

// @public (undocumented)
function SubTrigger({ label, 'data-wd': dataWd, 'data-direction': dataDirection, }: {
    label: TLTranslationKey;
    'data-wd'?: string;
    'data-direction'?: 'left' | 'right';
}): JSX.Element;

// @public (undocumented)
function Title({ className, children }: {
    className?: string;
    children: any;
}): JSX.Element;

// @public (undocumented)
export interface TLDialog {
    // (undocumented)
    component: (props: DialogProps) => any;
    // (undocumented)
    id: string;
    // (undocumented)
    onClose?: () => void;
}

// @public (undocumented)
export const TldrawUi: React_2.NamedExoticComponent<{
    shareZone?: ReactNode;
    renderDebugMenuItems?: (() => React_2.ReactNode) | undefined;
    children?: ReactNode;
    hideUi?: boolean | undefined;
} & TldrawUiContextProviderProps>;

// @public (undocumented)
export const TldrawUiContent: React_2.NamedExoticComponent<TldrawUiContentProps>;

// @public (undocumented)
export function TldrawUiContextProvider({ overrides, assetUrls, onUiEvent, children, }: TldrawUiContextProviderProps): JSX.Element;

// @public (undocumented)
export interface TldrawUiContextProviderProps {
    // (undocumented)
    assetUrls?: UiAssetUrls;
    // (undocumented)
    children?: any;
    // (undocumented)
    onUiEvent?: TLUiEventHandler;
    // (undocumented)
    overrides?: TldrawUiOverrides | TldrawUiOverrides[];
}

// @public (undocumented)
export interface TldrawUiOverrides {
    // (undocumented)
    actions?: WithDefaultHelpers<NonNullable<ActionsProviderProps['overrides']>>;
    // (undocumented)
    actionsMenu?: WithDefaultHelpers<NonNullable<ActionsMenuSchemaProviderProps['overrides']>>;
    // (undocumented)
    contextMenu?: WithDefaultHelpers<NonNullable<ContextMenuSchemaProviderProps['overrides']>>;
    // (undocumented)
    helpMenu?: WithDefaultHelpers<NonNullable<HelpMenuSchemaProviderProps['overrides']>>;
    // (undocumented)
    keyboardShortcutsMenu?: WithDefaultHelpers<NonNullable<KeyboardShortcutsSchemaProviderProps['overrides']>>;
    // (undocumented)
    menu?: WithDefaultHelpers<NonNullable<MenuSchemaProviderProps['overrides']>>;
    // (undocumented)
    toolbar?: WithDefaultHelpers<NonNullable<ToolbarSchemaProviderProps['overrides']>>;
    // (undocumented)
    tools?: WithDefaultHelpers<NonNullable<ToolsProviderProps['overrides']>>;
    // (undocumented)
    translations?: TranslationProviderProps['overrides'];
}

// @public (undocumented)
export type TLListedTranslation = {
    readonly locale: string;
    readonly label: string;
};

// @public (undocumented)
export type TLListedTranslations = readonly TLListedTranslation[];

// @public (undocumented)
export interface TLToast {
    // (undocumented)
    actions?: TLToastAction[];
    // (undocumented)
    closeLabel?: string;
    // (undocumented)
    description?: string;
    // (undocumented)
    icon?: string;
    // (undocumented)
    id: string;
    // (undocumented)
    keepOpen?: boolean;
    // (undocumented)
    title?: string;
}

// @public (undocumented)
export interface TLToastAction {
    // (undocumented)
    label: string;
    // (undocumented)
    onClick: () => void;
    // (undocumented)
    type: 'primary' | 'secondary' | 'warn';
}

// @public (undocumented)
export type TLTranslation = {
    readonly locale: string;
    readonly label: string;
    readonly messages: TLTranslationMessages;
};

// @public (undocumented)
export type TLTranslationKey = 'action.align-bottom' | 'action.align-center-horizontal.short' | 'action.align-center-horizontal' | 'action.align-center-vertical.short' | 'action.align-center-vertical' | 'action.align-left' | 'action.align-right' | 'action.align-top' | 'action.back-to-content' | 'action.bring-forward' | 'action.bring-to-front' | 'action.convert-to-bookmark' | 'action.convert-to-embed' | 'action.copy-as-json.short' | 'action.copy-as-json' | 'action.copy-as-png.short' | 'action.copy-as-png' | 'action.copy-as-svg.short' | 'action.copy-as-svg' | 'action.copy' | 'action.cut' | 'action.delete' | 'action.distribute-horizontal.short' | 'action.distribute-horizontal' | 'action.distribute-vertical.short' | 'action.distribute-vertical' | 'action.duplicate' | 'action.edit-link' | 'action.exit-pen-mode' | 'action.export-as-json.short' | 'action.export-as-json' | 'action.export-as-png.short' | 'action.export-as-png' | 'action.export-as-svg.short' | 'action.export-as-svg' | 'action.flip-horizontal.short' | 'action.flip-horizontal' | 'action.flip-vertical.short' | 'action.flip-vertical' | 'action.group' | 'action.insert-embed' | 'action.insert-media' | 'action.new-project' | 'action.new-shared-project' | 'action.open-embed-link' | 'action.open-file' | 'action.pack' | 'action.paste' | 'action.print' | 'action.redo' | 'action.rotate-ccw' | 'action.rotate-cw' | 'action.save-copy' | 'action.select-all' | 'action.select-none' | 'action.send-backward' | 'action.send-to-back' | 'action.share-project' | 'action.stack-horizontal.short' | 'action.stack-horizontal' | 'action.stack-vertical.short' | 'action.stack-vertical' | 'action.stop-following' | 'action.stretch-horizontal.short' | 'action.stretch-horizontal' | 'action.stretch-vertical.short' | 'action.stretch-vertical' | 'action.toggle-auto-size' | 'action.toggle-dark-mode.menu' | 'action.toggle-dark-mode' | 'action.toggle-debug-mode.menu' | 'action.toggle-debug-mode' | 'action.toggle-focus-mode.menu' | 'action.toggle-focus-mode' | 'action.toggle-grid.menu' | 'action.toggle-grid' | 'action.toggle-snap-mode.menu' | 'action.toggle-snap-mode' | 'action.toggle-tool-lock.menu' | 'action.toggle-tool-lock' | 'action.toggle-transparent.context-menu' | 'action.toggle-transparent.menu' | 'action.toggle-transparent' | 'action.undo' | 'action.ungroup' | 'action.zoom-in' | 'action.zoom-out' | 'action.zoom-to-100' | 'action.zoom-to-fit' | 'action.zoom-to-selection' | 'actions-menu.title' | 'align-style.end' | 'align-style.justify' | 'align-style.middle' | 'align-style.start' | 'arrowheadEnd-style.arrow' | 'arrowheadEnd-style.bar' | 'arrowheadEnd-style.diamond' | 'arrowheadEnd-style.dot' | 'arrowheadEnd-style.inverted' | 'arrowheadEnd-style.none' | 'arrowheadEnd-style.pipe' | 'arrowheadEnd-style.square' | 'arrowheadEnd-style.triangle' | 'arrowheadStart-style.arrow' | 'arrowheadStart-style.bar' | 'arrowheadStart-style.diamond' | 'arrowheadStart-style.dot' | 'arrowheadStart-style.inverted' | 'arrowheadStart-style.none' | 'arrowheadStart-style.pipe' | 'arrowheadStart-style.square' | 'arrowheadStart-style.triangle' | 'color-style.black' | 'color-style.blue' | 'color-style.green' | 'color-style.grey' | 'color-style.light-blue' | 'color-style.light-green' | 'color-style.light-red' | 'color-style.light-violet' | 'color-style.orange' | 'color-style.red' | 'color-style.violet' | 'color-style.yellow' | 'context-menu.arrange' | 'context-menu.copy-as' | 'context-menu.export-as' | 'context-menu.move-to-page' | 'context-menu.reorder' | 'context.pages.new-page' | 'dash-style.dashed' | 'dash-style.dotted' | 'dash-style.draw' | 'dash-style.solid' | 'debug-panel.more' | 'edit-link-dialog.cancel' | 'edit-link-dialog.clear' | 'edit-link-dialog.detail' | 'edit-link-dialog.invalid-url' | 'edit-link-dialog.save' | 'edit-link-dialog.title' | 'edit-link-dialog.url' | 'edit-pages-dialog.move-down' | 'edit-pages-dialog.move-up' | 'embed-dialog.back' | 'embed-dialog.cancel' | 'embed-dialog.create' | 'embed-dialog.instruction' | 'embed-dialog.invalid-url' | 'embed-dialog.title' | 'embed-dialog.url' | 'file-system.confirm-clear.cancel' | 'file-system.confirm-clear.continue' | 'file-system.confirm-clear.description' | 'file-system.confirm-clear.dont-show-again' | 'file-system.confirm-clear.title' | 'file-system.confirm-open.cancel' | 'file-system.confirm-open.description' | 'file-system.confirm-open.dont-show-again' | 'file-system.confirm-open.open' | 'file-system.confirm-open.title' | 'file-system.file-open-error.file-format-version-too-new' | 'file-system.file-open-error.generic-corrupted-file' | 'file-system.file-open-error.not-a-tldraw-file' | 'file-system.file-open-error.title' | 'file-system.shared-document-file-open-error.description' | 'file-system.shared-document-file-open-error.title' | 'fill-style.none' | 'fill-style.pattern' | 'fill-style.semi' | 'fill-style.solid' | 'focus-mode.toggle-focus-mode' | 'font-style.draw' | 'font-style.mono' | 'font-style.sans' | 'font-style.serif' | 'geo-style.arrow-down' | 'geo-style.arrow-left' | 'geo-style.arrow-right' | 'geo-style.arrow-up' | 'geo-style.check-box' | 'geo-style.diamond' | 'geo-style.ellipse' | 'geo-style.hexagon' | 'geo-style.octagon' | 'geo-style.oval' | 'geo-style.pentagon' | 'geo-style.rectangle' | 'geo-style.rhombus-2' | 'geo-style.rhombus' | 'geo-style.star' | 'geo-style.trapezoid' | 'geo-style.triangle' | 'geo-style.x-box' | 'help-menu.about' | 'help-menu.discord' | 'help-menu.github' | 'help-menu.keyboard-shortcuts' | 'help-menu.title' | 'help-menu.twitter' | 'menu.copy-as' | 'menu.edit' | 'menu.export-as' | 'menu.file' | 'menu.language' | 'menu.preferences' | 'menu.title' | 'menu.view' | 'navigation-zone.toggle-minimap' | 'navigation-zone.zoom' | 'opacity-style.0.1' | 'opacity-style.0.25' | 'opacity-style.0.5' | 'opacity-style.0.75' | 'opacity-style.1' | 'page-menu.create-new-page' | 'page-menu.edit-done' | 'page-menu.edit-start' | 'page-menu.go-to-page' | 'page-menu.max-page-count-reached' | 'page-menu.new-page-initial-name' | 'page-menu.submenu.delete' | 'page-menu.submenu.duplicate-page' | 'page-menu.submenu.move-down' | 'page-menu.submenu.move-up' | 'page-menu.submenu.rename' | 'page-menu.submenu.title' | 'page-menu.title' | 'people-menu.change-color' | 'people-menu.change-name' | 'people-menu.follow' | 'people-menu.following' | 'people-menu.invite' | 'people-menu.leading' | 'people-menu.title' | 'people-menu.user' | 'share-menu.copy-link-note' | 'share-menu.copy-link' | 'share-menu.copy-readonly-link-note' | 'share-menu.copy-readonly-link' | 'share-menu.create-snapshot-link' | 'share-menu.fork-note' | 'share-menu.offline-note' | 'share-menu.project-too-large' | 'share-menu.readonly-link' | 'share-menu.save-note' | 'share-menu.share-project' | 'share-menu.snapshot-link-note' | 'share-menu.title' | 'share-menu.upload-failed' | 'shortcuts-dialog.edit' | 'shortcuts-dialog.file' | 'shortcuts-dialog.preferences' | 'shortcuts-dialog.title' | 'shortcuts-dialog.tools' | 'shortcuts-dialog.transform' | 'shortcuts-dialog.view' | 'size-style.l' | 'size-style.m' | 'size-style.s' | 'size-style.xl' | 'spline-style.cubic' | 'spline-style.line' | 'style-panel.align' | 'style-panel.arrowhead-end' | 'style-panel.arrowhead-start' | 'style-panel.arrowheads' | 'style-panel.color' | 'style-panel.dash' | 'style-panel.fill' | 'style-panel.font' | 'style-panel.geo' | 'style-panel.mixed' | 'style-panel.opacity' | 'style-panel.position' | 'style-panel.size' | 'style-panel.spline' | 'style-panel.title' | 'toast.close' | 'toast.error.copy-fail.desc' | 'toast.error.copy-fail.title' | 'toast.error.export-fail.desc' | 'toast.error.export-fail.title' | 'tool-panel.drawing' | 'tool-panel.more' | 'tool-panel.shapes' | 'tool.arrow-down' | 'tool.arrow-left' | 'tool.arrow-right' | 'tool.arrow-up' | 'tool.arrow' | 'tool.asset' | 'tool.check-box' | 'tool.diamond' | 'tool.draw' | 'tool.ellipse' | 'tool.embed' | 'tool.eraser' | 'tool.frame' | 'tool.hand' | 'tool.hexagon' | 'tool.line' | 'tool.note' | 'tool.octagon' | 'tool.oval' | 'tool.pentagon' | 'tool.rectangle' | 'tool.rhombus' | 'tool.select' | 'tool.star' | 'tool.text' | 'tool.trapezoid' | 'tool.triangle' | 'tool.x-box' | 'vscode.file-open.backup-failed' | 'vscode.file-open.backup-saved' | 'vscode.file-open.backup' | 'vscode.file-open.desc' | 'vscode.file-open.dont-show-again' | 'vscode.file-open.open';

// @public (undocumented)
export type TLTranslationLocale = TLTranslations[number]['locale'];

// @public (undocumented)
export type TLTranslationMessages = Record<TLTranslationKey, string>;

// @public (undocumented)
export type TLTranslations = TLTranslation[];

// @public (undocumented)
export type TLUiEventHandler<T extends keyof TLUiEventMap = keyof TLUiEventMap> = (name: T, data: Join<{
    source: TLUiEventSource;
}, TLUiEventMap[T]>) => void;

// @public (undocumented)
export type TLUiEventSource = 'actions-menu' | 'context-menu' | 'debug-panel' | 'dialog' | 'export-menu' | 'help-menu' | 'helper-buttons' | 'kbd' | 'menu' | 'navigation-zone' | 'page-menu' | 'people-menu' | 'quick-actions' | 'share-menu' | 'toolbar' | 'unknown' | 'zoom-menu';

// @public (undocumented)
export type TLUiIconType = 'align-bottom-center' | 'align-bottom-left' | 'align-bottom-right' | 'align-bottom' | 'align-center-center' | 'align-center-horizontal' | 'align-center-left' | 'align-center-right' | 'align-center-vertical' | 'align-left' | 'align-right' | 'align-top-center' | 'align-top-left' | 'align-top-right' | 'align-top' | 'arrow-left' | 'arrowhead-arrow' | 'arrowhead-bar' | 'arrowhead-diamond' | 'arrowhead-dot' | 'arrowhead-none' | 'arrowhead-square' | 'arrowhead-triangle-inverted' | 'arrowhead-triangle' | 'aspect-ratio' | 'avatar' | 'blob' | 'bring-forward' | 'bring-to-front' | 'check' | 'checkbox-checked' | 'checkbox-empty' | 'chevron-down' | 'chevron-left' | 'chevron-right' | 'chevron-up' | 'chevrons-ne' | 'chevrons-sw' | 'clipboard-copied' | 'clipboard-copy' | 'code' | 'collab' | 'color' | 'comment' | 'cross-2' | 'cross' | 'dash-dashed' | 'dash-dotted' | 'dash-draw' | 'dash-solid' | 'discord' | 'distribute-horizontal' | 'distribute-vertical' | 'dot' | 'dots-horizontal' | 'dots-vertical' | 'drag-handle-dots' | 'duplicate' | 'edit' | 'external-link' | 'file' | 'fill-none' | 'fill-pattern' | 'fill-semi' | 'fill-solid' | 'follow' | 'following' | 'font-draw' | 'font-mono' | 'font-sans' | 'font-serif' | 'geo-arrow-down' | 'geo-arrow-left' | 'geo-arrow-right' | 'geo-arrow-up' | 'geo-check-box' | 'geo-diamond' | 'geo-ellipse' | 'geo-hexagon' | 'geo-octagon' | 'geo-oval' | 'geo-pentagon' | 'geo-rectangle' | 'geo-rhombus-2' | 'geo-rhombus' | 'geo-star' | 'geo-trapezoid' | 'geo-triangle' | 'geo-x-box' | 'github' | 'group' | 'hidden' | 'image' | 'info-circle' | 'leading' | 'link' | 'lock-small' | 'lock' | 'menu' | 'minus' | 'mixed' | 'pack' | 'page' | 'plus' | 'question-mark-circle' | 'question-mark' | 'redo' | 'reset-zoom' | 'rotate-ccw' | 'rotate-cw' | 'ruler' | 'search' | 'send-backward' | 'send-to-back' | 'settings-horizontal' | 'settings-vertical-1' | 'settings-vertical' | 'share-1' | 'share-2' | 'size-extra-large' | 'size-large' | 'size-medium' | 'size-small' | 'spline-cubic' | 'spline-line' | 'stack-horizontal' | 'stack-vertical' | 'stretch-horizontal' | 'stretch-vertical' | 'text-align-center' | 'text-align-justify' | 'text-align-left' | 'text-align-right' | 'tool-arrow' | 'tool-embed' | 'tool-eraser' | 'tool-frame' | 'tool-hand' | 'tool-highlighter' | 'tool-line' | 'tool-media' | 'tool-note' | 'tool-pencil' | 'tool-pointer' | 'tool-text' | 'trash' | 'triangle-down' | 'triangle-up' | 'twitter' | 'undo' | 'ungroup' | 'unlock-small' | 'unlock' | 'visible' | 'warning-triangle' | 'zoom-in' | 'zoom-out';

// @public (undocumented)
export const TLUiIconTypes: readonly ["align-bottom-center", "align-bottom-left", "align-bottom-right", "align-bottom", "align-center-center", "align-center-horizontal", "align-center-left", "align-center-right", "align-center-vertical", "align-left", "align-right", "align-top-center", "align-top-left", "align-top-right", "align-top", "arrow-left", "arrowhead-arrow", "arrowhead-bar", "arrowhead-diamond", "arrowhead-dot", "arrowhead-none", "arrowhead-square", "arrowhead-triangle-inverted", "arrowhead-triangle", "aspect-ratio", "avatar", "blob", "bring-forward", "bring-to-front", "check", "checkbox-checked", "checkbox-empty", "chevron-down", "chevron-left", "chevron-right", "chevron-up", "chevrons-ne", "chevrons-sw", "clipboard-copied", "clipboard-copy", "code", "collab", "color", "comment", "cross-2", "cross", "dash-dashed", "dash-dotted", "dash-draw", "dash-solid", "discord", "distribute-horizontal", "distribute-vertical", "dot", "dots-horizontal", "dots-vertical", "drag-handle-dots", "duplicate", "edit", "external-link", "file", "fill-none", "fill-pattern", "fill-semi", "fill-solid", "follow", "following", "font-draw", "font-mono", "font-sans", "font-serif", "geo-arrow-down", "geo-arrow-left", "geo-arrow-right", "geo-arrow-up", "geo-check-box", "geo-diamond", "geo-ellipse", "geo-hexagon", "geo-octagon", "geo-oval", "geo-pentagon", "geo-rectangle", "geo-rhombus-2", "geo-rhombus", "geo-star", "geo-trapezoid", "geo-triangle", "geo-x-box", "github", "group", "hidden", "image", "info-circle", "leading", "link", "lock-small", "lock", "menu", "minus", "mixed", "pack", "page", "plus", "question-mark-circle", "question-mark", "redo", "reset-zoom", "rotate-ccw", "rotate-cw", "ruler", "search", "send-backward", "send-to-back", "settings-horizontal", "settings-vertical-1", "settings-vertical", "share-1", "share-2", "size-extra-large", "size-large", "size-medium", "size-small", "spline-cubic", "spline-line", "stack-horizontal", "stack-vertical", "stretch-horizontal", "stretch-vertical", "text-align-center", "text-align-justify", "text-align-left", "text-align-right", "tool-arrow", "tool-embed", "tool-eraser", "tool-frame", "tool-hand", "tool-highlighter", "tool-line", "tool-media", "tool-note", "tool-pencil", "tool-pointer", "tool-text", "trash", "triangle-down", "triangle-up", "twitter", "undo", "ungroup", "unlock-small", "unlock", "visible", "warning-triangle", "zoom-in", "zoom-out"];

// @public (undocumented)
export const ToastsContext: Context<ToastsContextType>;

// @public (undocumented)
export type ToastsContextType = {
    addToast: (toast: Omit<TLToast, 'id'> & {
        id?: string;
    }) => string;
    removeToast: (id: TLToast['id']) => string;
    clearToasts: () => void;
    toasts: TLToast[];
};

// @public (undocumented)
export function ToastsProvider({ children }: ToastsProviderProps): JSX.Element;

// @public (undocumented)
export type ToastsProviderProps = {
    overrides?: (app: App) => ToastsContextType;
    children: any;
};

// @public (undocumented)
export type ToolbarItem = {
    id: string;
    type: 'item';
    readonlyOk: boolean;
    toolItem: ToolItem;
};

// @public (undocumented)
export function toolbarItem(toolItem: ToolItem): ToolbarItem;

// @public (undocumented)
export const ToolbarSchemaContext: React_2.Context<ToolbarSchemaContextType>;

// @public (undocumented)
export type ToolbarSchemaContextType = ToolbarItem[];

// @public (undocumented)
export function ToolbarSchemaProvider({ overrides, children }: ToolbarSchemaProviderProps): JSX.Element;

// @public (undocumented)
export type ToolbarSchemaProviderProps = {
    overrides?: (app: App, schema: ToolbarSchemaContextType, more: {
        tools: ToolsContextType;
    }) => ToolbarSchemaContextType;
    children: any;
};

// @public (undocumented)
export interface ToolItem {
    // (undocumented)
    icon: TLUiIconType;
    // (undocumented)
    id: string;
    // (undocumented)
    kbd?: string;
    // (undocumented)
    label: TLTranslationKey;
    // (undocumented)
    meta?: {
        [key: string]: any;
    };
    // (undocumented)
    onSelect: (source: TLUiEventSource) => void;
    // (undocumented)
    readonlyOk: boolean;
    // (undocumented)
    shortcutsLabel?: TLTranslationKey;
}

// @public (undocumented)
export const ToolsContext: React_3.Context<ToolsContextType>;

// @public (undocumented)
export type ToolsContextType = Record<string, ToolItem>;

// @public (undocumented)
export function ToolsProvider({ overrides, children }: ToolsProviderProps): JSX.Element;

// @public (undocumented)
export type ToolsProviderProps = {
    overrides?: (app: App, tools: ToolsContextType, helpers: {
        insertMedia: () => void;
    }) => ToolsContextType;
    children: any;
};

// @public (undocumented)
export function toStartCase(str: string): string;

// @public
export const TranslationProvider: MemoExoticComponent<({ overrides, children, }: TranslationProviderProps) => JSX.Element>;

// @public (undocumented)
export interface TranslationProviderProps {
    // (undocumented)
    children: any;
    overrides?: Record<string, Record<string, string>>;
}

// @public (undocumented)
function Trigger({ children, 'data-wd': dataWd }: {
    children: any;
    'data-wd'?: string;
}): JSX.Element;

// @public (undocumented)
export function useActions(): ActionsContextType;

// @public (undocumented)
export function useActionsMenuSchema(): MenuSchema;

// @public (undocumented)
export const useAllowGroup: () => boolean;

// @public (undocumented)
export const useAllowUngroup: () => boolean;

// @public (undocumented)
export function useAppEvents(): void;

// @public (undocumented)
export function useAssetUrls(): UiAssetUrls;

// @public (undocumented)
export function useBreakpoint(): number;

// @public (undocumented)
export function useCanRedo(): boolean;

// @public (undocumented)
export function useCanUndo(): boolean;

// @public (undocumented)
export function useContextMenuSchema(): MenuSchema;

// @public (undocumented)
export function useCopyAs(): (ids?: TLShapeId[], format?: TLCopyType) => void;

// @public (undocumented)
export function useDefaultHelpers(): {
    addToast: (toast: Omit<TLToast, "id"> & {
        id?: string | undefined;
    }) => string;
    removeToast: (id: string) => string;
    clearToasts: () => void;
    addDialog: (dialog: Omit<TLDialog, "id"> & {
        id?: string | undefined;
    }) => string;
    clearDialogs: () => void;
    removeDialog: (id: string) => string;
    updateDialog: (id: string, newDialogData: Partial<TLDialog>) => string;
    msg: (id: TLTranslationKey) => string;
    isMobile: boolean;
};

// @public (undocumented)
export function useDialogs(): DialogsContextType;

// @public (undocumented)
export function useEvents(): TLUiEventHandler<keyof TLUiEventMap>;

// @public (undocumented)
export function useExportAs(): (ids?: TLShapeId[], format?: TLExportType) => Promise<void>;

// @public (undocumented)
export function useHelpMenuSchema(): MenuSchema;

// @public (undocumented)
export function useHighDpiCanvas(ref: React.RefObject<HTMLCanvasElement>, dpr: number): void;

// @public (undocumented)
export function useKeyboardShortcuts(): void;

// @public (undocumented)
export function useKeyboardShortcutsSchema(): KeyboardShortcutsSchemaContextType;

// @public (undocumented)
export function useLanguages(): {
    languages: readonly [{
        readonly locale: "ar";
        readonly label: "عربي";
    }, {
        readonly locale: "ca";
        readonly label: "Català";
    }, {
        readonly locale: "da";
        readonly label: "Danish";
    }, {
        readonly locale: "de";
        readonly label: "Deutsch";
    }, {
        readonly locale: "en";
        readonly label: "English";
    }, {
        readonly locale: "es";
        readonly label: "Español";
    }, {
        readonly locale: "fa";
        readonly label: "فارسی";
    }, {
        readonly locale: "fi";
        readonly label: "Suomi";
    }, {
        readonly locale: "fr";
        readonly label: "Français";
    }, {
        readonly locale: "gl";
        readonly label: "Galego";
    }, {
        readonly locale: "he";
        readonly label: "עברית";
    }, {
        readonly locale: "it";
        readonly label: "Italiano";
    }, {
        readonly locale: "ja";
        readonly label: "日本語";
    }, {
        readonly locale: "ko-kr";
        readonly label: "한국어";
    }, {
        readonly locale: "ku";
        readonly label: "کوردی";
    }, {
        readonly locale: "hi-in";
        readonly label: "हिन्दी";
    }, {
        readonly locale: "hu";
        readonly label: "Magyar";
    }, {
        readonly locale: "my";
        readonly label: "မြန်မာစာ";
    }, {
        readonly locale: "ne";
        readonly label: "नेपाली";
    }, {
        readonly locale: "no";
        readonly label: "Norwegian";
    }, {
        readonly locale: "pl";
        readonly label: "Polski";
    }, {
        readonly locale: "pt-br";
        readonly label: "Português - Brasil";
    }, {
        readonly locale: "pt-pt";
        readonly label: "Português - Europeu";
    }, {
        readonly locale: "ro";
        readonly label: "Română";
    }, {
        readonly locale: "ru";
        readonly label: "Russian";
    }, {
        readonly locale: "sv";
        readonly label: "Svenska";
    }, {
        readonly locale: "te";
        readonly label: "తెలుగు";
    }, {
        readonly locale: "th";
        readonly label: "ภาษาไทย";
    }, {
        readonly locale: "tr";
        readonly label: "Türkçe";
    }, {
        readonly locale: "uk";
        readonly label: "Ukrainian";
    }, {
        readonly locale: "vi";
        readonly label: "Tiếng Việt";
    }, {
        readonly locale: "zh-cn";
        readonly label: "Chinese - Simplified";
    }, {
        readonly locale: "zh-tw";
        readonly label: "繁體中文 (台灣)";
    }];
    currentLanguage: string;
};

// @public (undocumented)
export function useLocalStorageState<T = any>(key: string, defaultValue: T): readonly [T, (setter: ((value: T) => T) | T) => void];

// @public (undocumented)
export function useMenuClipboardEvents(source: TLUiEventSource): {
    copy: () => void;
    cut: () => void;
    paste: (data: ClipboardItem[] | DataTransfer, point?: VecLike) => Promise<void>;
};

// @public (undocumented)
export function useMenuIsOpen(id: string, cb?: (isOpen: boolean) => void): readonly [boolean, (isOpen: boolean) => void];

// @public (undocumented)
export function useMenuSchema(): MenuSchema;

// @public (undocumented)
export function useNativeClipboardEvents(): void;

// @public (undocumented)
export function usePrint(): () => Promise<void>;

// @public (undocumented)
export function useReadonly(): boolean;

// @public (undocumented)
export const useThreeStackableItems: () => boolean;

// @public (undocumented)
export function useToasts(): ToastsContextType;

// @public (undocumented)
export function useToolbarSchema(): ToolbarSchemaContextType;

// @public (undocumented)
export function useTools(): ToolsContextType;

// @public
export function useTranslation(): (id: TLTranslationKey) => string;

// (No @packageDocumentation comment for this package)