Cleanup @tldraw/ui types / exports (#1504)

This PR cleans up exports from TldrawUi, unifying types under `TLUi` and
removing many items from exports / marking others as internal.

### Change Type

- [x] `major` — Breaking Change

### Release Notes

- [editor] clean up / unify types
This commit is contained in:
Steve Ruiz 2023-06-02 22:16:09 +01:00 committed by GitHub
parent 735f1c41b7
commit a5e653b225
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
61 changed files with 807 additions and 1255 deletions

View file

@ -1,4 +1,4 @@
import { MenuGroup, Tldraw, menuItem, toolbarItem } from '@tldraw/tldraw'
import { TLUiMenuGroup, Tldraw, menuItem, toolbarItem } from '@tldraw/tldraw'
import '@tldraw/tldraw/editor.css'
import '@tldraw/tldraw/ui.css'
import { CardTool } from './CardTool'
@ -44,7 +44,7 @@ export default function CustomConfigExample() {
// add it to that before returning the array.
const toolsGroup = keyboardShortcutsMenu.find(
(group) => group.id === 'shortcuts-dialog.tools'
) as MenuGroup
) as TLUiMenuGroup
toolsGroup.children.push(menuItem(tools.card))
return keyboardShortcutsMenu
},

View file

@ -9,7 +9,7 @@ import {
import { linksUiOverrides } from './utils/links'
// eslint-disable-next-line import/no-internal-modules
import '@tldraw/editor/editor.css'
import { ContextMenu, MenuSchema, TldrawUi } from '@tldraw/ui'
import { ContextMenu, TLUiMenuSchema, TldrawUi } from '@tldraw/ui'
// eslint-disable-next-line import/no-internal-modules
import '@tldraw/ui/ui.css'
// eslint-disable-next-line import/no-internal-modules
@ -64,7 +64,7 @@ export function WrappedTldrawEditor() {
}
const menuOverrides = {
menu: (_editor: Editor, schema: MenuSchema, _helpers: any) => {
menu: (_editor: Editor, schema: TLUiMenuSchema, _helpers: any) => {
schema.forEach((item) => {
if (item.id === 'menu' && item.type === 'group') {
item.children = item.children.filter((menuItem) => {

View file

@ -1,4 +1,4 @@
import { menuGroup, menuItem, TldrawUiOverrides } from '@tldraw/ui'
import { menuGroup, menuItem, TLUiOverrides } from '@tldraw/ui'
import { openUrl } from './openUrl'
export const GITHUB_URL = 'https://github.com/tldraw/tldraw'
@ -43,7 +43,7 @@ const linksMenuGroup = menuGroup(
})
)!
export const linksUiOverrides: TldrawUiOverrides = {
export const linksUiOverrides: TLUiOverrides = {
helpMenu(editor, schema) {
schema.push(linksMenuGroup)
return schema

View file

@ -10,8 +10,8 @@ import { Result } from '@tldraw/utils';
import { SerializedSchema } from '@tldraw/tlstore';
import { TLInstanceId } from '@tldraw/editor';
import { TLStore } from '@tldraw/editor';
import { TLTranslationKey } from '@tldraw/ui';
import { ToastsContextType } from '@tldraw/ui';
import { TLUiToastsContextType } from '@tldraw/ui';
import { TLUiTranslationKey } from '@tldraw/ui';
import { UnknownRecord } from '@tldraw/tlstore';
// @internal (undocumented)
@ -37,7 +37,7 @@ export interface LegacyTldrawDocument {
}
// @internal (undocumented)
export function parseAndLoadDocument(editor: Editor, document: string, msg: (id: TLTranslationKey) => string, addToast: ToastsContextType['addToast'], onV1FileLoad?: () => void, forceDarkMode?: boolean): Promise<void>;
export function parseAndLoadDocument(editor: Editor, document: string, msg: (id: TLUiTranslationKey) => string, addToast: TLUiToastsContextType['addToast'], onV1FileLoad?: () => void, forceDarkMode?: boolean): Promise<void>;
// @public (undocumented)
export function parseTldrawJsonFile({ json, instanceId, store, }: {

View file

@ -16,7 +16,7 @@ import {
UnknownRecord,
} from '@tldraw/tlstore'
import { T } from '@tldraw/tlvalidate'
import { TLTranslationKey, ToastsContextType } from '@tldraw/ui'
import { TLUiToastsContextType, TLUiTranslationKey } from '@tldraw/ui'
import { exhaustiveSwitchError, Result } from '@tldraw/utils'
import { buildFromV1Document } from './buildFromV1Document'
@ -204,8 +204,8 @@ export async function serializeTldrawJsonBlob(store: TLStore): Promise<Blob> {
export async function parseAndLoadDocument(
editor: Editor,
document: string,
msg: (id: TLTranslationKey) => string,
addToast: ToastsContextType['addToast'],
msg: (id: TLUiTranslationKey) => string,
addToast: TLUiToastsContextType['addToast'],
onV1FileLoad?: () => void,
forceDarkMode?: boolean
) {

View file

@ -364,7 +364,7 @@ export const geoShapeTypeValidator: T.Validator<TLGeoShape>;
export const geoValidator: T.Validator<"arrow-down" | "arrow-left" | "arrow-right" | "arrow-up" | "check-box" | "diamond" | "ellipse" | "hexagon" | "octagon" | "oval" | "pentagon" | "rectangle" | "rhombus-2" | "rhombus" | "star" | "trapezoid" | "triangle" | "x-box">;
// @public (undocumented)
export function getDefaultTranslationLocale(): TLTranslationLocale;
export function getDefaultTranslationLocale(): TLUiTranslationLocale;
// @public (undocumented)
export const groupShapeTypeMigrations: Migrations;

View file

@ -1,21 +1,21 @@
import { LANGUAGES } from './languages'
type TLListedTranslation = {
/** @public */
export type TLUiLanguage = {
readonly locale: string
readonly label: string
}
type TLListedTranslations = TLListedTranslation[]
type TLTranslationLocale = TLListedTranslations[number]['locale']
type TLUiTranslationLocale = TLUiLanguage['locale']
/** @public */
export function getDefaultTranslationLocale(): TLTranslationLocale {
export function getDefaultTranslationLocale(): TLUiTranslationLocale {
const locales = typeof window !== 'undefined' ? window.navigator.languages ?? ['en'] : ['en']
return _getDefaultTranslationLocale(locales)
}
/** @internal */
export function _getDefaultTranslationLocale(locales: readonly string[]): TLTranslationLocale {
export function _getDefaultTranslationLocale(locales: readonly string[]): TLUiTranslationLocale {
for (const locale of locales) {
const supportedLocale = getSupportedLocale(locale)
if (supportedLocale) {
@ -26,7 +26,7 @@ export function _getDefaultTranslationLocale(locales: readonly string[]): TLTran
}
/** @public */
const DEFAULT_LOCALE_REGIONS: { [locale: string]: TLTranslationLocale } = {
const DEFAULT_LOCALE_REGIONS: { [locale: string]: TLUiTranslationLocale } = {
zh: 'zh-cn',
pt: 'pt-br',
ko: 'ko-kr',
@ -34,7 +34,7 @@ const DEFAULT_LOCALE_REGIONS: { [locale: string]: TLTranslationLocale } = {
}
/** @public */
function getSupportedLocale(locale: string): TLTranslationLocale | null {
function getSupportedLocale(locale: string): TLUiTranslationLocale | null {
// If we have an exact match, return it!
// (e.g. if the user has 'fr' and we have 'fr')
// (or if the user has 'pt-BR' and we have 'pt-br')

File diff suppressed because one or more lines are too long

View file

@ -1,25 +1,16 @@
import * as Dialog from './lib/components/primitives/Dialog'
import * as DropdownMenu from './lib/components/primitives/DropdownMenu'
export { TldrawUi, TldrawUiContent, type TldrawUiProps } from './lib/TldrawUi'
export { TldrawUi, type TldrawUiProps } from './lib/TldrawUi'
export {
TldrawUiContextProvider,
type TldrawUiContextProviderProps,
} from './lib/TldrawUiContextProvider'
export { setDefaultUiAssetUrls } from './lib/assetUrls'
export { ContextMenu, type ContextMenuProps } from './lib/components/ContextMenu'
export { DebugPanel } from './lib/components/DebugPanel'
export { HTMLCanvas } from './lib/components/HTMLCanvas'
export { HelpMenu, type HelpMenuProps } from './lib/components/HelpMenu'
export { NavigationZone } from './lib/components/NavigationZone/NavigationZone'
export { StylePanel } from './lib/components/StylePanel/StylePanel'
export { Button, type ButtonProps } from './lib/components/primitives/Button'
export { ButtonPicker, type ButtonPickerProps } from './lib/components/primitives/ButtonPicker'
export { Icon, type IconProps } from './lib/components/primitives/Icon'
export { Input, type InputProps } from './lib/components/primitives/Input'
export { Kbd, type KbdProps } from './lib/components/primitives/Kbd'
export { Slider, type SliderProps } from './lib/components/primitives/Slider'
export { BASE_URL, getBaseUrl, kbd, kbdStr, toStartCase } from './lib/components/primitives/shared'
export { ContextMenu, type TLUiContextMenuProps } from './lib/components/ContextMenu'
export { Button, type TLUiButtonProps } from './lib/components/primitives/Button'
export { Icon, type TLUiIconProps } from './lib/components/primitives/Icon'
export { Input, type TLUiInputProps } from './lib/components/primitives/Input'
export {
compactMenuItems,
findMenuItem,
@ -27,30 +18,21 @@ export {
menuGroup,
menuItem,
menuSubmenu,
useAllowGroup,
useAllowUngroup,
useThreeStackableItems,
type CustomMenuItem,
type MenuChild,
type MenuGroup,
type MenuItem,
type MenuSchema,
type SubMenu,
type TLUiCustomMenuItem,
type TLUiMenuChild,
type TLUiMenuGroup,
type TLUiMenuItem,
type TLUiMenuSchema,
type TLUiSubMenu,
} from './lib/hooks/menuHelpers'
export {
ActionsContext,
ActionsProvider,
useActions,
type ActionItem,
type ActionsContextType,
type ActionsProviderProps,
type TLUiActionItem,
type TLUiActionsContextType,
} from './lib/hooks/useActions'
export {
ActionsMenuSchemaContext,
ActionsMenuSchemaProvider,
useActionsMenuSchema,
type ActionsMenuSchemaContextType,
type ActionsMenuSchemaProviderProps,
type TLUiActionsMenuSchemaContextType,
} from './lib/hooks/useActionsMenuSchema'
export { AssetUrlsProvider, useAssetUrls } from './lib/hooks/useAssetUrls'
export { BreakPointProvider, useBreakpoint } from './lib/hooks/useBreakpoint'
@ -58,101 +40,65 @@ export { useCanRedo } from './lib/hooks/useCanRedo'
export { useCanUndo } from './lib/hooks/useCanUndo'
export { useMenuClipboardEvents, useNativeClipboardEvents } from './lib/hooks/useClipboardEvents'
export {
ContextMenuSchemaContext,
ContextMenuSchemaProvider,
useContextMenuSchema,
type ContextMenuSchemaContextType,
type ContextMenuSchemaProviderProps,
type TLUiContextTTLUiMenuSchemaContextType,
} from './lib/hooks/useContextMenuSchema'
export { useCopyAs } from './lib/hooks/useCopyAs'
export {
DialogsContext,
DialogsProvider,
useDialogs,
type DialogProps,
type DialogsContextType,
type DialogsProviderProps,
type TLDialog,
type TLUiDialog,
type TLUiDialogProps,
type TLUiDialogsContextType,
} from './lib/hooks/useDialogsProvider'
export { useEditorEvents } from './lib/hooks/useEditorEvents'
export {
useEvents,
type EventsProviderProps,
type TLUiEventContextType,
type TLUiEventHandler,
type TLUiEventSource,
} from './lib/hooks/useEventsProvider'
export { useExportAs } from './lib/hooks/useExportAs'
export {
HelpMenuSchemaContext,
HelpMenuSchemaProvider,
useHelpMenuSchema,
type HelpMenuSchemaProviderProps,
type HelpMenuSchemaProviderType,
type TLUiHelpMenuSchemaContextType,
} from './lib/hooks/useHelpMenuSchema'
export { useHighDpiCanvas } from './lib/hooks/useHighDpiCanvas'
export { useKeyboardShortcuts } from './lib/hooks/useKeyboardShortcuts'
export {
KeyboardShortcutsSchemaContext,
KeyboardShortcutsSchemaProvider,
useKeyboardShortcutsSchema,
type KeyboardShortcutsSchemaContextType,
type KeyboardShortcutsSchemaProviderProps,
type TLUiKeyboardShortcutsSchemaContextType,
type TLUiKeyboardShortcutsSchemaProviderProps,
} from './lib/hooks/useKeyboardShortcutsSchema'
export { useLocalStorageState } from './lib/hooks/useLocalStorageState'
export { useMenuIsOpen } from './lib/hooks/useMenuIsOpen'
export {
MenuSchemaContext,
MenuSchemaProvider,
useMenuSchema,
type MenuSchemaContextType,
type MenuSchemaProviderProps,
type TLUiMenuSchemaContextType,
type TLUiMenuSchemaProviderProps,
} from './lib/hooks/useMenuSchema'
export { usePrint } from './lib/hooks/usePrint'
export { useReadonly } from './lib/hooks/useReadonly'
export {
ToastsContext,
ToastsProvider,
useToasts,
type TLToast,
type TLToastAction,
type ToastsContextType,
type ToastsProviderProps,
type TLUiToast,
type TLUiToastAction,
type TLUiToastsContextType,
} from './lib/hooks/useToastsProvider'
export {
ToolbarSchemaContext,
ToolbarSchemaProvider,
toolbarItem,
useToolbarSchema,
type ToolbarItem,
type ToolbarSchemaContextType,
type ToolbarSchemaProviderProps,
type TLUiToolbarItem,
type TLUiToolbarSchemaContextType,
} from './lib/hooks/useToolbarSchema'
export {
ToolsContext,
ToolsProvider,
useTools,
type ToolItem,
type ToolsContextType,
type ToolsProviderProps,
type TLUiToolItem,
type TLUiToolsContextType,
type TLUiToolsProviderProps,
} from './lib/hooks/useTools'
export type { TLTranslationKey } from './lib/hooks/useTranslation/TLTranslationKey'
export { type TLUiTranslationKey } from './lib/hooks/useTranslation/TLUiTranslationKey'
export { type TLUiLanguage, type TLUiTranslation } from './lib/hooks/useTranslation/translations'
export {
EN_TRANSLATION,
fetchTranslation,
getTranslation,
type TLListedTranslation,
type TLListedTranslations,
type TLTranslation,
type TLTranslationLocale,
type TLTranslationMessages,
type TLTranslations,
} from './lib/hooks/useTranslation/translations'
export { useLanguages } from './lib/hooks/useTranslation/useLanguages'
export {
TranslationProvider,
useTranslation,
type TranslationProviderProps,
useTranslation as useTranslation,
type TLUiTranslationContextType,
} from './lib/hooks/useTranslation/useTranslation'
export { TLUiIconTypes, type TLUiIconType } from './lib/icon-types'
export { useDefaultHelpers, type TldrawUiOverrides } from './lib/overrides'
export { type TLUiIconType } from './lib/icon-types'
export { useDefaultHelpers, type TLUiOverrides } from './lib/overrides'
export { Dialog, DropdownMenu }

View file

@ -85,8 +85,7 @@ const TldrawUiInner = React.memo(function TldrawUiInner({
)
})
/** @public */
export const TldrawUiContent = React.memo(function TldrawUI({
const TldrawUiContent = React.memo(function TldrawUI({
shareZone,
topZone,
renderDebugMenuItems,

View file

@ -1,24 +1,24 @@
import { defaultUiAssetUrls, UiAssetUrls } from './assetUrls'
import { defaultUiAssetUrls, TLUiAssetUrls } from './assetUrls'
import { ActionsProvider } from './hooks/useActions'
import { ActionsMenuSchemaProvider } from './hooks/useActionsMenuSchema'
import { AssetUrlsProvider } from './hooks/useAssetUrls'
import { BreakPointProvider } from './hooks/useBreakpoint'
import { ContextMenuSchemaProvider } from './hooks/useContextMenuSchema'
import { TLUiContextMenuSchemaProvider } from './hooks/useContextMenuSchema'
import { DialogsProvider } from './hooks/useDialogsProvider'
import { EventsProvider, TLUiEventHandler } from './hooks/useEventsProvider'
import { HelpMenuSchemaProvider } from './hooks/useHelpMenuSchema'
import { KeyboardShortcutsSchemaProvider } from './hooks/useKeyboardShortcutsSchema'
import { MenuSchemaProvider } from './hooks/useMenuSchema'
import { TLUiMenuSchemaProvider } from './hooks/useMenuSchema'
import { ToastsProvider } from './hooks/useToastsProvider'
import { ToolbarSchemaProvider } from './hooks/useToolbarSchema'
import { ToolsProvider } from './hooks/useTools'
import { TranslationProvider } from './hooks/useTranslation/useTranslation'
import { TldrawUiOverrides, useMergedOverrides, useMergedTranslationOverrides } from './overrides'
import { TLUiOverrides, useMergedOverrides, useMergedTranslationOverrides } from './overrides'
/** @public */
export interface TldrawUiContextProviderProps {
assetUrls?: UiAssetUrls
overrides?: TldrawUiOverrides | TldrawUiOverrides[]
assetUrls?: TLUiAssetUrls
overrides?: TLUiOverrides | TLUiOverrides[]
onUiEvent?: TLUiEventHandler
children?: any
}
@ -57,13 +57,13 @@ function InternalProviders({
<ToolbarSchemaProvider overrides={mergedOverrides.toolbar}>
<ActionsMenuSchemaProvider overrides={mergedOverrides.actionsMenu}>
<KeyboardShortcutsSchemaProvider overrides={mergedOverrides.keyboardShortcutsMenu}>
<ContextMenuSchemaProvider overrides={mergedOverrides.contextMenu}>
<TLUiContextMenuSchemaProvider overrides={mergedOverrides.contextMenu}>
<HelpMenuSchemaProvider overrides={mergedOverrides.helpMenu}>
<MenuSchemaProvider overrides={mergedOverrides.menu}>
<TLUiMenuSchemaProvider overrides={mergedOverrides.menu}>
{children}
</MenuSchemaProvider>
</TLUiMenuSchemaProvider>
</HelpMenuSchemaProvider>
</ContextMenuSchemaProvider>
</TLUiContextMenuSchemaProvider>
</KeyboardShortcutsSchemaProvider>
</ActionsMenuSchemaProvider>
</ToolbarSchemaProvider>

View file

@ -1,18 +1,19 @@
import { defaultEditorAssetUrls, EditorAssetUrls, EMBED_DEFINITIONS } from '@tldraw/editor'
import { LANGUAGES } from './hooks/useTranslation/languages'
import { TLUiIconType, TLUiIconTypes } from './icon-types'
import { iconTypes, TLUiIconType } from './icon-types'
export type UiAssetUrls = EditorAssetUrls & {
export type TLUiAssetUrls = EditorAssetUrls & {
icons: Record<TLUiIconType, string>
translations: Record<(typeof LANGUAGES)[number]['locale'], string>
embedIcons: Record<(typeof EMBED_DEFINITIONS)[number]['type'], string>
}
export let defaultUiAssetUrls: UiAssetUrls = {
export let defaultUiAssetUrls: TLUiAssetUrls = {
...defaultEditorAssetUrls,
icons: Object.fromEntries(
TLUiIconTypes.map((name) => [name, `/icons/icon/${name}.svg`])
) as Record<TLUiIconType, string>,
icons: Object.fromEntries(iconTypes.map((name) => [name, `/icons/icon/${name}.svg`])) as Record<
TLUiIconType,
string
>,
translations: Object.fromEntries(
LANGUAGES.map((lang) => [lang.locale, `/translations/${lang.locale}.json`])
) as Record<(typeof LANGUAGES)[number]['locale'], string>,
@ -22,6 +23,6 @@ export let defaultUiAssetUrls: UiAssetUrls = {
}
/** @internal */
export function setDefaultUiAssetUrls(urls: UiAssetUrls) {
export function setDefaultUiAssetUrls(urls: TLUiAssetUrls) {
defaultUiAssetUrls = urls
}

View file

@ -1,7 +1,7 @@
import * as PopoverPrimitive from '@radix-ui/react-popover'
import { useContainer } from '@tldraw/editor'
import { memo } from 'react'
import { MenuChild } from '../hooks/menuHelpers'
import { TLUiMenuChild } from '../hooks/menuHelpers'
import { useActionsMenuSchema } from '../hooks/useActionsMenuSchema'
import { useReadonly } from '../hooks/useReadonly'
import { useTranslation } from '../hooks/useTranslation/useTranslation'
@ -15,7 +15,7 @@ export const ActionsMenu = memo(function ActionsMenu() {
const menuSchema = useActionsMenuSchema()
const isReadonly = useReadonly()
function getActionMenuItem(item: MenuChild) {
function getActionMenuItem(item: TLUiMenuChild) {
if (isReadonly && !item.readonlyOk) return null
switch (item.type) {

View file

@ -3,7 +3,7 @@ import { Editor, preventDefault, useContainer, useEditor } from '@tldraw/editor'
import classNames from 'classnames'
import * as React from 'react'
import { useValue } from 'signia-react'
import { MenuChild } from '../hooks/menuHelpers'
import { TLUiMenuChild } from '../hooks/menuHelpers'
import { useBreakpoint } from '../hooks/useBreakpoint'
import { useContextMenuSchema } from '../hooks/useContextMenuSchema'
import { useMenuIsOpen } from '../hooks/useMenuIsOpen'
@ -15,7 +15,7 @@ import { Icon } from './primitives/Icon'
import { Kbd } from './primitives/Kbd'
/** @public */
export interface ContextMenuProps {
export interface TLUiContextMenuProps {
children: any
}
@ -23,7 +23,7 @@ export interface ContextMenuProps {
export const ContextMenu = function ContextMenu({ children }: { children: any }) {
const editor = useEditor()
const contextMenuSchema = useContextMenuSchema()
const contextTLUiMenuSchema = useContextMenuSchema()
const cb = (isOpen: boolean) => {
if (isOpen) return
if (shouldDeselect(editor)) {
@ -37,8 +37,8 @@ export const ContextMenu = function ContextMenu({ children }: { children: any })
const isReadonly = useReadonly()
const noItemsToShow =
contextMenuSchema.length === 0 ||
(isReadonly && contextMenuSchema.every((item) => !item.readonlyOk))
contextTLUiMenuSchema.length === 0 ||
(isReadonly && contextTLUiMenuSchema.every((item) => !item.readonlyOk))
const selectToolActive = useValue('isSelectToolActive', () => editor.currentToolId === 'select', [
editor,
@ -80,8 +80,8 @@ function ContextMenuContent() {
function getContextMenuItem(
editor: Editor,
item: MenuChild,
parent: MenuChild | null,
item: TLUiMenuChild,
parent: TLUiMenuChild | null,
depth: number
) {
if (isReadonly && !item.readonlyOk) return null

View file

@ -38,7 +38,7 @@ function createNShapes(editor: Editor, n: number) {
})
}
/** @public */
/** @internal */
export const DebugPanel = React.memo(function DebugPanel({
renderDebugMenuItems,
}: {
@ -96,7 +96,7 @@ const DebugMenuContent = track(function DebugMenuContent({
// icon?: string
// title?: string
// description?: string
// actions?: TLToastAction[]
// actions?: TLUiToastAction[]
})
}}
>

View file

@ -1,9 +1,9 @@
import * as _Dialog from '@radix-ui/react-dialog'
import { useContainer } from '@tldraw/editor'
import React, { useCallback } from 'react'
import { TLDialog, useDialogs } from '../hooks/useDialogsProvider'
import { TLUiDialog, useDialogs } from '../hooks/useDialogsProvider'
const Dialog = ({ id, component: ModalContent, onClose }: TLDialog) => {
const Dialog = ({ id, component: ModalContent, onClose }: TLUiDialog) => {
const { removeDialog } = useDialogs()
const container = useContainer()
@ -42,7 +42,7 @@ function _Dialogs() {
return (
<>
{dialogs.map((dialog: TLDialog) => (
{dialogs.map((dialog: TLUiDialog) => (
<Dialog key={dialog.id} {...dialog} />
))}
</>

View file

@ -1,7 +1,7 @@
import { TLBaseShape, TLBookmarkUtil, useEditor } from '@tldraw/editor'
import { useCallback, useRef, useState } from 'react'
import { track } from 'signia-react'
import { DialogProps } from '../hooks/useDialogsProvider'
import { TLUiDialogProps } from '../hooks/useDialogsProvider'
import { useTranslation } from '../hooks/useTranslation/useTranslation'
import { Button } from './primitives/Button'
import * as Dialog from './primitives/Dialog'
@ -21,7 +21,7 @@ function validateUrl(url: string) {
type ShapeWithUrl = TLBaseShape<string, { url: string }>
export const EditLinkDialog = track(function EditLinkDialog({ onClose }: DialogProps) {
export const EditLinkDialog = track(function EditLinkDialog({ onClose }: TLUiDialogProps) {
const editor = useEditor()
const selectedShape = editor.onlySelectedShape
@ -38,7 +38,7 @@ export const EditLinkDialog = track(function EditLinkDialog({ onClose }: DialogP
export const EditLinkDialogInner = track(function EditLinkDialogInner({
onClose,
selectedShape,
}: DialogProps & { selectedShape: ShapeWithUrl }) {
}: TLUiDialogProps & { selectedShape: ShapeWithUrl }) {
const editor = useEditor()
const msg = useTranslation()

View file

@ -3,14 +3,14 @@ import { EMBED_DEFINITIONS, EmbedDefinition } from '@tldraw/tlschema'
import { useRef, useState } from 'react'
import { track } from 'signia-react'
import { useAssetUrls } from '../hooks/useAssetUrls'
import { DialogProps } from '../hooks/useDialogsProvider'
import { TLUiDialogProps } from '../hooks/useDialogsProvider'
import { useTranslation } from '../hooks/useTranslation/useTranslation'
import { Button } from './primitives/Button'
import * as Dialog from './primitives/Dialog'
import { Icon } from './primitives/Icon'
import { Input } from './primitives/Input'
export const EmbedDialog = track(function EmbedDialog({ onClose }: DialogProps) {
export const EmbedDialog = track(function EmbedDialog({ onClose }: TLUiDialogProps) {
const editor = useEditor()
const msg = useTranslation()
const assetUrls = useAssetUrls()

View file

@ -2,7 +2,7 @@ import { useEditor } from '@tldraw/editor'
import * as React from 'react'
import { track } from 'signia-react'
/** @public */
/** @internal */
export const HTMLCanvas = track(function HTMLCanvas() {
const editor = useEditor()
const rCanvas = React.useRef<HTMLCanvasElement>(null)

View file

@ -1,11 +1,11 @@
import { Content, Portal, Root, Trigger } from '@radix-ui/react-dropdown-menu'
import { useContainer } from '@tldraw/editor'
import * as React from 'react'
import { MenuChild } from '../hooks/menuHelpers'
import { TLUiMenuChild } from '../hooks/menuHelpers'
import { useHelpMenuSchema } from '../hooks/useHelpMenuSchema'
import { useMenuIsOpen } from '../hooks/useMenuIsOpen'
import { useReadonly } from '../hooks/useReadonly'
import { TLTranslationKey } from '../hooks/useTranslation/TLTranslationKey'
import { TLUiTranslationKey } from '../hooks/useTranslation/TLUiTranslationKey'
import { useTranslation } from '../hooks/useTranslation/useTranslation'
import { TLUiIconType } from '../icon-types'
import { LanguageMenu } from './LanguageMenu'
@ -13,17 +13,17 @@ import * as M from './primitives/DropdownMenu'
import { Icon } from './primitives/Icon'
interface HelpMenuLink {
label: TLTranslationKey
label: TLUiTranslationKey
icon: TLUiIconType
url: string
}
/** @public */
/** @internal */
export interface HelpMenuProps {
links?: HelpMenuLink[]
}
/** @public */
/** @internal */
export const HelpMenu = React.memo(function HelpMenu() {
const container = useContainer()
const msg = useTranslation()
@ -61,7 +61,7 @@ function HelpMenuContent() {
const isReadonly = useReadonly()
function getHelpMenuItem(item: MenuChild) {
function getHelpMenuItem(item: TLUiMenuChild) {
if (isReadonly && !item.readonlyOk) return null
switch (item.type) {

View file

@ -1,7 +1,7 @@
import { MenuChild } from '../hooks/menuHelpers'
import { TLUiMenuChild } from '../hooks/menuHelpers'
import { useKeyboardShortcutsSchema } from '../hooks/useKeyboardShortcutsSchema'
import { useReadonly } from '../hooks/useReadonly'
import { TLTranslationKey } from '../hooks/useTranslation/TLTranslationKey'
import { TLUiTranslationKey } from '../hooks/useTranslation/TLUiTranslationKey'
import { useTranslation } from '../hooks/useTranslation/useTranslation'
import * as Dialog from './primitives/Dialog'
import { Kbd } from './primitives/Kbd'
@ -11,7 +11,7 @@ export const KeyboardShortcutsDialog = () => {
const isReadonly = useReadonly()
const shortcutsItems = useKeyboardShortcutsSchema()
function getKeyboardShortcutItem(item: MenuChild) {
function getKeyboardShortcutItem(item: TLUiMenuChild) {
if (isReadonly && !item.readonlyOk) return null
switch (item.type) {
@ -19,7 +19,7 @@ export const KeyboardShortcutsDialog = () => {
return (
<div className="tlui-shortcuts-dialog__group" key={item.id}>
<h2 className="tlui-shortcuts-dialog__group__title">
{msg(item.id as TLTranslationKey)}
{msg(item.id as TLUiTranslationKey)}
</h2>
<div className="tlui-shortcuts-dialog__group__content">
{item.children

View file

@ -1,6 +1,6 @@
import { useEditor } from '@tldraw/editor'
import { useCallback } from 'react'
import { TLTranslationLocale } from '../hooks/useTranslation/translations'
import { TLUiTranslation } from '../hooks/useTranslation/translations'
import { useLanguages } from '../hooks/useTranslation/useLanguages'
import * as D from './primitives/DropdownMenu'
@ -9,7 +9,7 @@ export function LanguageMenu() {
const { languages, currentLanguage } = useLanguages()
const handleLanguageSelect = useCallback(
(locale: TLTranslationLocale) => editor.setLocale(locale),
(locale: TLUiTranslation['locale']) => editor.setLocale(locale),
[editor]
)

View file

@ -1,6 +1,6 @@
import { Editor, useEditor } from '@tldraw/editor'
import * as React from 'react'
import { MenuChild } from '../hooks/menuHelpers'
import { TLUiMenuChild } from '../hooks/menuHelpers'
import { useBreakpoint } from '../hooks/useBreakpoint'
import { useMenuSchema } from '../hooks/useMenuSchema'
import { useReadonly } from '../hooks/useReadonly'
@ -37,7 +37,12 @@ function MenuContent() {
const breakpoint = useBreakpoint()
const isReadonly = useReadonly()
function getMenuItem(editor: Editor, item: MenuChild, parent: MenuChild | null, depth: number) {
function getMenuItem(
editor: Editor,
item: TLUiMenuChild,
parent: TLUiMenuChild | null,
depth: number
) {
switch (item.type) {
case 'custom': {
if (isReadonly && !item.readonlyOk) return null

View file

@ -8,7 +8,7 @@ import { Button } from '../primitives/Button'
import { kbdStr } from '../primitives/shared'
import { ZoomMenu } from './ZoomMenu'
/** @public */
/** @internal */
export const NavigationZone = memo(function NavigationZone() {
const actions = useActions()
const msg = useTranslation()

View file

@ -2,7 +2,7 @@ import { Trigger } from '@radix-ui/react-dropdown-menu'
import { Editor, TLStyleItem, TLStyleType } from '@tldraw/editor'
import classNames from 'classnames'
import * as React from 'react'
import { TLTranslationKey } from '../../hooks/useTranslation/TLTranslationKey'
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
import { TLUiIconType } from '../../icon-types'
import { Button } from '../primitives/Button'
@ -11,9 +11,9 @@ import * as DropdownMenu from '../primitives/DropdownMenu'
type AllStyles = typeof Editor.styles
interface DoubleDropdownPickerProps<T extends AllStyles[keyof AllStyles][number]> {
label: TLTranslationKey
labelA: TLTranslationKey
labelB: TLTranslationKey
label: TLUiTranslationKey
labelA: TLUiTranslationKey
labelB: TLUiTranslationKey
itemsA: T[]
itemsB: T[]
styleTypeA: TLStyleType
@ -69,7 +69,7 @@ export const DoubleDropdownPicker = React.memo(function DoubleDropdownPicker<
' — ' +
(valueA === null
? msg('style-panel.mixed')
: msg(`${styleTypeA}-style.${valueA}` as TLTranslationKey))
: msg(`${styleTypeA}-style.${valueA}` as TLUiTranslationKey))
}
icon={iconA as any}
invertIcon
@ -88,7 +88,9 @@ export const DoubleDropdownPicker = React.memo(function DoubleDropdownPicker<
<DropdownMenu.Item
className="tlui-button-grid__button"
title={
msg(labelA) + ' — ' + msg(`${styleTypeA}-style.${item.id}` as TLTranslationKey)
msg(labelA) +
' — ' +
msg(`${styleTypeA}-style.${item.id}` as TLUiTranslationKey)
}
data-testid={`${startWdPrefix}.${item.id}`}
key={item.id}
@ -110,7 +112,7 @@ export const DoubleDropdownPicker = React.memo(function DoubleDropdownPicker<
' — ' +
(valueB === null
? msg('style-panel.mixed')
: msg(`${styleTypeB}-style.${valueB}` as TLTranslationKey))
: msg(`${styleTypeB}-style.${valueB}` as TLUiTranslationKey))
}
icon={iconB as any}
smallIcon
@ -128,7 +130,9 @@ export const DoubleDropdownPicker = React.memo(function DoubleDropdownPicker<
<DropdownMenu.Item
className="tlui-button-grid__button"
title={
msg(labelB) + ' — ' + msg(`${styleTypeB}-style.${item.id}` as TLTranslationKey)
msg(labelB) +
' — ' +
msg(`${styleTypeB}-style.${item.id}` as TLUiTranslationKey)
}
data-testid={`${endWdPrefix}.${item.id}`}
key={item.id}

View file

@ -2,7 +2,7 @@ import { Trigger } from '@radix-ui/react-dropdown-menu'
import { Editor, TLStyleItem, TLStyleType } from '@tldraw/editor'
import classNames from 'classnames'
import * as React from 'react'
import { TLTranslationKey } from '../../hooks/useTranslation/TLTranslationKey'
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
import { TLUiIconType } from '../../icon-types'
import { Button } from '../primitives/Button'
@ -12,7 +12,7 @@ type AllStyles = typeof Editor.styles
interface DropdownPickerProps<T extends AllStyles[keyof AllStyles][number]> {
id: string
label?: TLTranslationKey
label?: TLUiTranslationKey
items: T[]
styleType: TLStyleType
value: T['id'] | null
@ -43,7 +43,7 @@ export const DropdownPicker = React.memo(function DropdownPicker<
title={
value === null
? msg('style-panel.mixed')
: msg(`${styleType}-style.${value}` as TLTranslationKey)
: msg(`${styleType}-style.${value}` as TLUiTranslationKey)
}
label={label}
icon={(icon as TLUiIconType) ?? 'mixed'}
@ -62,7 +62,7 @@ export const DropdownPicker = React.memo(function DropdownPicker<
<DropdownMenu.Item
className="tlui-button-grid__button"
data-testid={`${testId}.${item.id}`}
title={msg(`${styleType}-style.${item.id}` as TLTranslationKey)}
title={msg(`${styleType}-style.${item.id}` as TLUiTranslationKey)}
key={item.id}
icon={item.icon as TLUiIconType}
onClick={() => onValueChange(item as TLStyleItem, false)}

View file

@ -13,7 +13,7 @@ interface StylePanelProps {
isMobile?: boolean
}
/** @public */
/** @internal */
export const StylePanel = function StylePanel({ isMobile }: StylePanelProps) {
const editor = useEditor()

View file

@ -1,12 +1,12 @@
import * as T from '@radix-ui/react-toast'
import * as React from 'react'
import { TLToast, useToasts } from '../hooks/useToastsProvider'
import { TLUiToast, useToasts } from '../hooks/useToastsProvider'
import { useTranslation } from '../hooks/useTranslation/useTranslation'
import { TLUiIconType } from '../icon-types'
import { Button } from './primitives/Button'
import { Icon } from './primitives/Icon'
function Toast({ toast }: { toast: TLToast }) {
function Toast({ toast }: { toast: TLUiToast }) {
const { removeToast } = useToasts()
const msg = useTranslation()

View file

@ -4,8 +4,8 @@ import React from 'react'
import { track, useValue } from 'signia-react'
import { useBreakpoint } from '../../hooks/useBreakpoint'
import { useReadonly } from '../../hooks/useReadonly'
import { ToolbarItem, useToolbarSchema } from '../../hooks/useToolbarSchema'
import { ToolItem } from '../../hooks/useTools'
import { TLUiToolbarItem, useToolbarSchema } from '../../hooks/useToolbarSchema'
import { TLUiToolItem } from '../../hooks/useTools'
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
import { ActionsMenu } from '../ActionsMenu'
import { DuplicateButton } from '../DuplicateButton'
@ -24,7 +24,7 @@ export const Toolbar = function Toolbar() {
const msg = useTranslation()
const breakpoint = useBreakpoint()
const rMostRecentlyActiveDropdownItem = React.useRef<ToolbarItem | undefined>(undefined)
const rMostRecentlyActiveDropdownItem = React.useRef<TLUiToolbarItem | undefined>(undefined)
const isReadOnly = useReadonly()
const toolbarItems = useToolbarSchema()
@ -38,17 +38,17 @@ export const Toolbar = function Toolbar() {
const showEditingTools = !isReadOnly
const showExtraActions = !(isReadOnly || isHandTool)
const getTitle = (item: ToolItem) =>
const getTitle = (item: TLUiToolItem) =>
item.label ? `${msg(item.label)} ${item.kbd ? kbdStr(item.kbd) : ''}` : ''
const activeToolbarItem = toolbarItems.find((item) => {
return isActiveToolItem(item.toolItem, activeToolId, geoState)
const activeTLUiToolbarItem = toolbarItems.find((item) => {
return isActiveTLUiToolItem(item.toolItem, activeToolId, geoState)
})
const { itemsInPanel, itemsInDropdown, dropdownFirstItem } = React.useMemo(() => {
const itemsInPanel: ToolbarItem[] = []
const itemsInDropdown: ToolbarItem[] = []
let dropdownFirstItem: ToolbarItem | undefined
const itemsInPanel: TLUiToolbarItem[] = []
const itemsInDropdown: TLUiToolbarItem[] = []
let dropdownFirstItem: TLUiToolbarItem | undefined
const overflowIndex = Math.min(8, 5 + breakpoint)
@ -60,7 +60,7 @@ export const Toolbar = function Toolbar() {
} else {
// Items above will be in the dropdown menu unless the item
// is active (or was the most recently selected active item)
if (item === activeToolbarItem) {
if (item === activeTLUiToolbarItem) {
// If the dropdown item is active, make it the dropdownFirstItem
dropdownFirstItem = item
}
@ -103,7 +103,7 @@ export const Toolbar = function Toolbar() {
}
return { itemsInPanel, itemsInDropdown, dropdownFirstItem }
}, [toolbarItems, activeToolbarItem, breakpoint])
}, [toolbarItems, activeTLUiToolbarItem, breakpoint])
return (
<div className="tlui-toolbar">
@ -139,7 +139,7 @@ export const Toolbar = function Toolbar() {
key={toolItem.id}
item={toolItem}
title={getTitle(toolItem)}
isSelected={isActiveToolItem(toolItem, activeToolId, geoState)}
isSelected={isActiveTLUiToolItem(toolItem, activeToolId, geoState)}
/>
)
})}
@ -148,7 +148,7 @@ export const Toolbar = function Toolbar() {
key={laserTool.toolItem.id}
item={laserTool.toolItem}
title={getTitle(laserTool.toolItem)}
isSelected={isActiveToolItem(laserTool.toolItem, activeToolId, geoState)}
isSelected={isActiveTLUiToolItem(laserTool.toolItem, activeToolId, geoState)}
/>
)}
{showEditingTools && (
@ -160,7 +160,7 @@ export const Toolbar = function Toolbar() {
key={toolItem.id}
item={toolItem}
title={getTitle(toolItem)}
isSelected={isActiveToolItem(toolItem, activeToolId, geoState)}
isSelected={isActiveTLUiToolItem(toolItem, activeToolId, geoState)}
/>
))}
{/* Everything Else */}
@ -170,7 +170,7 @@ export const Toolbar = function Toolbar() {
key={toolItem.id}
item={toolItem}
title={getTitle(toolItem)}
isSelected={isActiveToolItem(toolItem, activeToolId, geoState)}
isSelected={isActiveTLUiToolItem(toolItem, activeToolId, geoState)}
/>
))}
{/* Overflowing Shapes */}
@ -181,7 +181,7 @@ export const Toolbar = function Toolbar() {
key={dropdownFirstItem.toolItem.id}
item={dropdownFirstItem.toolItem}
title={getTitle(dropdownFirstItem.toolItem)}
isSelected={isActiveToolItem(
isSelected={isActiveTLUiToolItem(
dropdownFirstItem.toolItem,
activeToolId,
geoState
@ -220,7 +220,7 @@ export const Toolbar = function Toolbar() {
const OverflowToolsContent = track(function OverflowToolsContent({
toolbarItems,
}: {
toolbarItems: ToolbarItem[]
toolbarItems: TLUiToolbarItem[]
}) {
const msg = useTranslation()
@ -250,7 +250,7 @@ function ToolbarButton({
title,
isSelected,
}: {
item: ToolItem
item: TLUiToolItem
title: string
isSelected: boolean
}) {
@ -273,8 +273,8 @@ function ToolbarButton({
)
}
const isActiveToolItem = (
item: ToolItem,
const isActiveTLUiToolItem = (
item: TLUiToolItem,
activeToolId: string | undefined,
geoState: string | null | undefined
) => {

View file

@ -1,6 +1,6 @@
import classnames from 'classnames'
import * as React from 'react'
import { TLTranslationKey } from '../../hooks/useTranslation/TLTranslationKey'
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
import { TLUiIconType } from '../../icon-types'
import { Spinner } from '../Spinner'
@ -8,10 +8,10 @@ import { Icon } from './Icon'
import { Kbd } from './Kbd'
/** @public */
export interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
export interface TLUiButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
loading?: boolean // TODO: loading spinner
disabled?: boolean
label?: TLTranslationKey
label?: TLUiTranslationKey
icon?: TLUiIconType
spinner?: boolean
iconLeft?: TLUiIconType
@ -23,7 +23,7 @@ export interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
}
/** @public */
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(function Button(
export const Button = React.forwardRef<HTMLButtonElement, TLUiButtonProps>(function Button(
{
label,
icon,

View file

@ -3,12 +3,12 @@ import { clamp } from '@tldraw/primitives'
import classNames from 'classnames'
import * as React from 'react'
import { useRef } from 'react'
import { TLTranslationKey } from '../../hooks/useTranslation/TLTranslationKey'
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
import { TLUiIconType } from '../../icon-types'
import { Button } from './Button'
/** @public */
/** @internal */
export interface ButtonPickerProps<T extends TLStyleItem> {
title: string
items: T[]
@ -97,7 +97,7 @@ function _ButtonPicker<T extends TLStyleItem>(props: ButtonPickerProps<T>) {
data-testid={`${props['data-testid']}.${item.id}`}
aria-label={item.id}
data-state={value === item.id ? 'hinted' : undefined}
title={title + ' — ' + msg(`${styleType}-style.${item.id}` as TLTranslationKey)}
title={title + ' — ' + msg(`${styleType}-style.${item.id}` as TLUiTranslationKey)}
className={classNames('tlui-button-grid__button')}
style={item.type === 'color' ? { color: `var(--palette-${item.id})` } : undefined}
onPointerEnter={handleButtonPointerEnter}
@ -111,5 +111,5 @@ function _ButtonPicker<T extends TLStyleItem>(props: ButtonPickerProps<T>) {
)
}
/** @public */
/** @internal */
export const ButtonPicker = React.memo(_ButtonPicker)

View file

@ -1,8 +1,8 @@
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
import { preventDefault, useContainer } from '@tldraw/editor'
import { useMenuIsOpen } from '../../hooks/useMenuIsOpen'
import { TLTranslationKey } from '../../hooks/useTranslation/TLTranslationKey'
import { Button, ButtonProps } from './Button'
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
import { Button, TLUiButtonProps } from './Button'
import { Icon } from './Icon'
/** @public */
@ -88,7 +88,7 @@ export function SubTrigger({
'data-testid': testId,
'data-direction': dataDirection,
}: {
label: TLTranslationKey
label: TLUiTranslationKey
'data-testid'?: string
'data-direction'?: 'left' | 'right'
}) {
@ -153,7 +153,7 @@ export function Indicator() {
}
/** @public */
export interface DropdownMenuItemProps extends ButtonProps {
export interface DropdownMenuItemProps extends TLUiButtonProps {
noClose?: boolean
}

View file

@ -4,7 +4,7 @@ import { useAssetUrls } from '../../hooks/useAssetUrls'
import { TLUiIconType } from '../../icon-types'
/** @public */
export interface IconProps extends React.HTMLProps<HTMLDivElement> {
export interface TLUiIconProps extends React.HTMLProps<HTMLDivElement> {
icon: TLUiIconType
small?: boolean
color?: string
@ -21,7 +21,7 @@ export const Icon = memo(function Icon({
color,
className,
...props
}: IconProps) {
}: TLUiIconProps) {
const assetUrls = useAssetUrls()
const asset = assetUrls.icons[icon]
const ref = useRef<HTMLDivElement>(null)

View file

@ -1,14 +1,14 @@
import classNames from 'classnames'
import * as React from 'react'
import { TLTranslationKey } from '../../hooks/useTranslation/TLTranslationKey'
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
import { TLUiIconType } from '../../icon-types'
import { Icon } from './Icon'
/** @public */
export interface InputProps {
export interface TLUiInputProps {
disabled?: boolean
label?: TLTranslationKey
label?: TLUiTranslationKey
icon?: TLUiIconType
iconLeft?: TLUiIconType
autofocus?: boolean
@ -34,7 +34,7 @@ export interface InputProps {
}
/** @public */
export const Input = React.forwardRef<HTMLInputElement, InputProps>(function Input(
export const Input = React.forwardRef<HTMLInputElement, TLUiInputProps>(function Input(
{
className,
label,

View file

@ -1,11 +1,11 @@
import { kbd } from './shared'
/** @public */
/** @internal */
export interface KbdProps {
children: string
}
/** @public */
/** @internal */
export function Kbd({ children }: KbdProps) {
return (
<kbd className="tlui-kbd">

View file

@ -1,10 +1,10 @@
import { Range, Root, Thumb, Track } from '@radix-ui/react-slider'
import { useEditor } from '@tldraw/editor'
import { useCallback } from 'react'
import { TLTranslationKey } from '../../hooks/useTranslation/TLTranslationKey'
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
/** @public */
/** @internal */
export interface SliderProps {
steps: number
value: number | null
@ -14,7 +14,7 @@ export interface SliderProps {
'data-testid'?: string
}
/** @public */
/** @internal */
export function Slider(props: SliderProps) {
const { title, steps, value, label, onValueChange } = props
const editor = useEditor()
@ -50,7 +50,7 @@ export function Slider(props: SliderProps) {
onPointerDown={handlePointerDown}
onValueChange={handleValueChange}
onPointerUp={handlePointerUp}
title={title + ' — ' + msg(label as TLTranslationKey)}
title={title + ' — ' + msg(label as TLUiTranslationKey)}
>
<Track className="tlui-slider__track" dir="ltr">
{value !== null && <Range className="tlui-slider__range" dir="ltr" />}

View file

@ -1,4 +1,4 @@
/** @public */
/** @internal */
export function toStartCase(str: string) {
return str
.split(' ')
@ -13,7 +13,7 @@ const isDarwin =
const cmdKey = isDarwin ? '⌘' : 'Ctrl'
const altKey = isDarwin ? '⌥' : 'Alt'
/** @public */
/** @internal */
export function kbd(str: string) {
return str
.split(',')[0]
@ -24,7 +24,7 @@ export function kbd(str: string) {
})
}
/** @public */
/** @internal */
export function kbdStr(str: string) {
return (
'— ' +
@ -38,27 +38,3 @@ export function kbdStr(str: string) {
.join('')
)
}
/** @public */
export const getBaseUrl = () => {
if (typeof process === 'undefined') {
return 'http://localhost:5420'
}
if (process.env.NODE_ENV === 'development') {
return 'http://localhost:3000'
}
if (process.env.NEXT_PUBLIC_VERCEL_ENV === 'production') {
return 'https://www.tldraw.com'
}
if (process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview') {
return `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`
}
return 'http://localhost:3000'
}
/** @public */
export const BASE_URL = getBaseUrl()

View file

@ -1,15 +1,15 @@
import { Editor, TLArrowUtil, useEditor } from '@tldraw/editor'
import { assert, exhaustiveSwitchError } from '@tldraw/utils'
import { useValue } from 'signia-react'
import { ActionItem } from './useActions'
import { ToolItem } from './useTools'
import { TLTranslationKey } from './useTranslation/TLTranslationKey'
import { TLUiActionItem } from './useActions'
import { TLUiToolItem } from './useTools'
import { TLUiTranslationKey } from './useTranslation/TLUiTranslationKey'
/** @public */
export type MenuChild = MenuItem | SubMenu | MenuGroup | CustomMenuItem
export type TLUiMenuChild = TLUiMenuItem | TLUiSubMenu | TLUiMenuGroup | TLUiCustomMenuItem
/** @public */
export type CustomMenuItem = {
export type TLUiCustomMenuItem = {
id: string
type: 'custom'
disabled: boolean
@ -17,37 +17,37 @@ export type CustomMenuItem = {
}
/** @public */
export type MenuItem = {
export type TLUiMenuItem = {
id: string
type: 'item'
readonlyOk: boolean
actionItem: ActionItem
actionItem: TLUiActionItem
disabled: boolean
checked: boolean
}
/** @public */
export type MenuGroup = {
export type TLUiMenuGroup = {
id: string
type: 'group'
checkbox: boolean
disabled: boolean
readonlyOk: boolean
children: MenuChild[]
children: TLUiMenuChild[]
}
/** @public */
export type SubMenu = {
export type TLUiSubMenu = {
id: string
type: 'submenu'
label: TLTranslationKey
label: TLUiTranslationKey
disabled: boolean
readonlyOk: boolean
children: MenuChild[]
children: TLUiMenuChild[]
}
/** @public */
export type MenuSchema = (MenuGroup | MenuItem | CustomMenuItem)[]
export type TLUiMenuSchema = (TLUiMenuGroup | TLUiMenuItem | TLUiCustomMenuItem)[]
/** @public */
export function compactMenuItems<T>(arr: T[]): Exclude<T, null | false | undefined>[] {
@ -55,7 +55,10 @@ export function compactMenuItems<T>(arr: T[]): Exclude<T, null | false | undefin
}
/** @public */
export function menuGroup(id: string, ...children: (MenuChild | null | false)[]): MenuGroup | null {
export function menuGroup(
id: string,
...children: (TLUiMenuChild | null | false)[]
): TLUiMenuGroup | null {
const childItems = compactMenuItems(children)
if (childItems.length === 0) return null
@ -73,9 +76,9 @@ export function menuGroup(id: string, ...children: (MenuChild | null | false)[])
/** @public */
export function menuSubmenu(
id: string,
label: TLTranslationKey,
...children: (MenuChild | null | false)[]
): SubMenu | null {
label: TLUiTranslationKey,
...children: (TLUiMenuChild | null | false)[]
): TLUiSubMenu | null {
const childItems = compactMenuItems(children)
if (childItems.length === 0) return null
@ -105,9 +108,9 @@ export function menuCustom(
/** @public */
export function menuItem(
actionItem: ActionItem | ToolItem,
actionItem: TLUiActionItem | TLUiToolItem,
opts = {} as Partial<{ checked: boolean; disabled: boolean }>
): MenuItem {
): TLUiMenuItem {
if (!actionItem) {
throw Error('No action item provided to menuItem')
}
@ -146,19 +149,19 @@ function shapesWithUnboundArrows(editor: Editor) {
})
}
/** @public */
/** @internal */
export const useThreeStackableItems = () => {
const editor = useEditor()
return useValue('threeStackableItems', () => shapesWithUnboundArrows(editor).length > 2, [editor])
}
/** @public */
/** @internal */
export const useAllowGroup = () => {
const editor = useEditor()
return useValue('allowGroup', () => shapesWithUnboundArrows(editor).length > 1, [editor])
}
/** @public */
/** @internal */
export const useAllowUngroup = () => {
const editor = useEditor()
return useValue(
@ -169,13 +172,16 @@ export const useAllowUngroup = () => {
}
/** @public */
export function findMenuItem(menu: MenuSchema, path: string[]) {
export function findMenuItem(menu: TLUiMenuSchema, path: string[]) {
const item = _findMenuItem(menu, path)
assert(item, `Menu item ${path.join(' > ')} not found`)
return item
}
function _findMenuItem(menu: MenuSchema | MenuChild[], path: string[]): MenuChild | null {
function _findMenuItem(
menu: TLUiMenuSchema | TLUiMenuChild[],
path: string[]
): TLUiMenuChild | null {
const [next, ...rest] = path
if (!next) return null

View file

@ -27,44 +27,44 @@ import { useExportAs } from './useExportAs'
import { useInsertMedia } from './useInsertMedia'
import { usePrint } from './usePrint'
import { useToasts } from './useToastsProvider'
import { TLTranslationKey } from './useTranslation/TLTranslationKey'
import { TLUiTranslationKey } from './useTranslation/TLUiTranslationKey'
/** @public */
export interface ActionItem {
export interface TLUiActionItem {
icon?: TLUiIconType
id: string
kbd?: string
title?: string
label?: TLTranslationKey
menuLabel?: TLTranslationKey
shortcutsLabel?: TLTranslationKey
contextMenuLabel?: TLTranslationKey
label?: TLUiTranslationKey
menuLabel?: TLUiTranslationKey
shortcutsLabel?: TLUiTranslationKey
contextMenuLabel?: TLUiTranslationKey
readonlyOk: boolean
checkbox?: boolean
onSelect: (source: TLUiEventSource) => Promise<void> | void
}
/** @public */
export type ActionsContextType = Record<string, ActionItem>
export type TLUiActionsContextType = Record<string, TLUiActionItem>
/** @public */
export const ActionsContext = React.createContext<ActionsContextType>({})
/** @internal */
export const ActionsContext = React.createContext<TLUiActionsContextType>({})
/** @public */
export type ActionsProviderProps = {
overrides?: (
editor: Editor,
actions: ActionsContextType,
actions: TLUiActionsContextType,
helpers: undefined
) => ActionsContextType
) => TLUiActionsContextType
children: any
}
function makeActions(actions: ActionItem[]) {
return Object.fromEntries(actions.map((action) => [action.id, action])) as ActionsContextType
function makeActions(actions: TLUiActionItem[]) {
return Object.fromEntries(actions.map((action) => [action.id, action])) as TLUiActionsContextType
}
/** @public */
/** @internal */
export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
const editor = useEditor()
@ -80,7 +80,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
const trackEvent = useEvents()
// should this be a useMemo? looks like it doesn't actually deref any reactive values
const actions = React.useMemo<ActionsContextType>(() => {
const actions = React.useMemo<TLUiActionsContextType>(() => {
const actions = makeActions([
{
id: 'edit-link',
@ -976,6 +976,6 @@ export function useActions() {
return ctx
}
function asActions<T extends Record<string, ActionItem>>(actions: T) {
return actions as Record<keyof typeof actions, ActionItem>
function asActions<T extends Record<string, TLUiActionItem>>(actions: T) {
return actions as Record<keyof typeof actions, TLUiActionItem>
}

View file

@ -2,7 +2,7 @@ import { Editor, useEditor } from '@tldraw/editor'
import React, { useMemo } from 'react'
import { track } from 'signia-react'
import {
MenuSchema,
TLUiMenuSchema,
menuItem,
useAllowGroup,
useAllowUngroup,
@ -13,27 +13,27 @@ import { useBreakpoint } from './useBreakpoint'
import { useHasLinkShapeSelected } from './useHasLinkShapeSelected'
/** @public */
export type ActionsMenuSchemaContextType = MenuSchema
export type TLUiActionsMenuSchemaContextType = TLUiMenuSchema
/** @public */
export const ActionsMenuSchemaContext = React.createContext({} as ActionsMenuSchemaContextType)
/** @internal */
export const ActionsMenuSchemaContext = React.createContext({} as TLUiActionsMenuSchemaContextType)
/** @public */
export type ActionsMenuSchemaProviderProps = {
overrides?: (
editor: Editor,
schema: ActionsMenuSchemaContextType,
schema: TLUiActionsMenuSchemaContextType,
helpers: {
actions: ReturnType<typeof useActions>
oneSelected: boolean
twoSelected: boolean
threeSelected: boolean
}
) => ActionsMenuSchemaContextType
) => TLUiActionsMenuSchemaContextType
children: any
}
/** @public */
/** @internal */
export const ActionsMenuSchemaProvider = track(function ActionsMenuSchemaProvider({
overrides,
children,
@ -53,7 +53,7 @@ export const ActionsMenuSchemaProvider = track(function ActionsMenuSchemaProvide
const breakpoint = useBreakpoint()
const isZoomedTo100 = editor.zoomLevel === 1
const actionMenuSchema = useMemo<MenuSchema>(() => {
const actionTLUiMenuSchema = useMemo<TLUiMenuSchema>(() => {
const results = [
menuItem(actions['align-left'], { disabled: !twoSelected }),
menuItem(actions['align-center-horizontal'], { disabled: !twoSelected }),
@ -104,14 +104,14 @@ export const ActionsMenuSchemaProvider = track(function ActionsMenuSchemaProvide
])
return (
<ActionsMenuSchemaContext.Provider value={actionMenuSchema}>
<ActionsMenuSchemaContext.Provider value={actionTLUiMenuSchema}>
{children}
</ActionsMenuSchemaContext.Provider>
)
})
/** @public */
export function useActionsMenuSchema(): MenuSchema {
export function useActionsMenuSchema(): TLUiMenuSchema {
const ctx = React.useContext(ActionsMenuSchemaContext)
if (!ctx) {

View file

@ -1,20 +1,23 @@
import { createContext, useContext } from 'react'
import { UiAssetUrls } from '../assetUrls'
import { TLUiAssetUrls } from '../assetUrls'
const AssetUrlsContext = createContext<UiAssetUrls | null>(null)
/** @internal */
type UiAssetUrlsContextType = TLUiAssetUrls | null
/** @public */
const AssetUrlsContext = createContext<UiAssetUrlsContextType>(null)
/** @internal */
export function AssetUrlsProvider({
assetUrls,
children,
}: {
assetUrls: UiAssetUrls
assetUrls: TLUiAssetUrls
children: React.ReactNode
}) {
return <AssetUrlsContext.Provider value={assetUrls}>{children}</AssetUrlsContext.Provider>
}
/** @public */
/** @internal */
export function useAssetUrls() {
const assetUrls = useContext(AssetUrlsContext)
if (!assetUrls) {

View file

@ -2,7 +2,7 @@ import { Editor, TLBookmarkUtil, TLEmbedUtil, getEmbedInfo, useEditor } from '@t
import React, { useMemo } from 'react'
import { track, useValue } from 'signia-react'
import {
MenuSchema,
TLUiMenuSchema,
compactMenuItems,
menuCustom,
menuGroup,
@ -19,16 +19,18 @@ import { useOnlyFlippableShape } from './useOnlyFlippableShape'
import { useShowAutoSizeToggle } from './useShowAutoSizeToggle'
/** @public */
export type ContextMenuSchemaContextType = MenuSchema
export type TLUiContextTTLUiMenuSchemaContextType = TLUiMenuSchema
/** @internal */
export const TLUiContextMenuSchemaContext = React.createContext(
{} as TLUiContextTTLUiMenuSchemaContextType
)
/** @public */
export const ContextMenuSchemaContext = React.createContext({} as ContextMenuSchemaContextType)
/** @public */
export type ContextMenuSchemaProviderProps = {
export type TLUiContextMenuSchemaProviderProps = {
overrides?: (
editor: Editor,
schema: ContextMenuSchemaContextType,
schema: TLUiContextTTLUiMenuSchemaContextType,
helpers: {
actions: ReturnType<typeof useActions>
oneSelected: boolean
@ -38,15 +40,15 @@ export type ContextMenuSchemaProviderProps = {
showUngroup: boolean
onlyFlippableShapeSelected: boolean
}
) => ContextMenuSchemaContextType
) => TLUiContextTTLUiMenuSchemaContextType
children: any
}
/** @public */
export const ContextMenuSchemaProvider = track(function ContextMenuSchemaProvider({
/** @internal */
export const TLUiContextMenuSchemaProvider = track(function TLUiContextMenuSchemaProvider({
overrides,
children,
}: ContextMenuSchemaProviderProps) {
}: TLUiContextMenuSchemaProviderProps) {
const editor = useEditor()
const actions = useActions()
@ -100,8 +102,8 @@ export const ContextMenuSchemaProvider = track(function ContextMenuSchemaProvide
const { onlySelectedShape } = editor
const isShapeLocked = onlySelectedShape && editor.isShapeOrAncestorLocked(onlySelectedShape)
const contextMenuSchema = useMemo<MenuSchema>(() => {
let contextMenuSchema: ContextMenuSchemaContextType = compactMenuItems([
const contextTLUiMenuSchema = useMemo<TLUiMenuSchema>(() => {
let contextTLUiMenuSchema: TLUiContextTTLUiMenuSchemaContextType = compactMenuItems([
menuGroup(
'selection',
oneEmbedSelected && menuItem(actions['open-embed-link']),
@ -220,7 +222,7 @@ export const ContextMenuSchemaProvider = track(function ContextMenuSchemaProvide
])
if (overrides) {
contextMenuSchema = overrides(editor, contextMenuSchema, {
contextTLUiMenuSchema = overrides(editor, contextTLUiMenuSchema, {
actions,
oneSelected,
twoSelected,
@ -231,7 +233,7 @@ export const ContextMenuSchemaProvider = track(function ContextMenuSchemaProvide
})
}
return contextMenuSchema
return contextTLUiMenuSchema
}, [
editor,
overrides,
@ -254,18 +256,18 @@ export const ContextMenuSchemaProvider = track(function ContextMenuSchemaProvide
])
return (
<ContextMenuSchemaContext.Provider value={contextMenuSchema}>
<TLUiContextMenuSchemaContext.Provider value={contextTLUiMenuSchema}>
{children}
</ContextMenuSchemaContext.Provider>
</TLUiContextMenuSchemaContext.Provider>
)
})
/** @public */
export function useContextMenuSchema(): MenuSchema {
const ctx = React.useContext(ContextMenuSchemaContext)
export function useContextMenuSchema(): TLUiMenuSchema {
const ctx = React.useContext(TLUiContextMenuSchemaContext)
if (!ctx) {
throw new Error('useContextMenuSchema must be used inside of a ContextMenuSchemaProvider.')
throw new Error('useContextMenuSchema must be used inside of a TLUiContextMenuSchemaProvider.')
}
return ctx

View file

@ -3,44 +3,44 @@ import { createContext, useCallback, useContext, useState } from 'react'
import { useEvents } from './useEventsProvider'
/** @public */
export interface DialogProps {
export interface TLUiDialogProps {
onClose: () => void
}
/** @public */
export interface TLDialog {
export interface TLUiDialog {
id: string
onClose?: () => void
component: (props: DialogProps) => any
component: (props: TLUiDialogProps) => any
}
/** @public */
export type DialogsContextType = {
addDialog: (dialog: Omit<TLDialog, 'id'> & { id?: string }) => string
export type TLUiDialogsContextType = {
addDialog: (dialog: Omit<TLUiDialog, 'id'> & { id?: string }) => string
removeDialog: (id: string) => string
updateDialog: (id: string, newDialogData: Partial<TLDialog>) => string
updateDialog: (id: string, newDialogData: Partial<TLUiDialog>) => string
clearDialogs: () => void
dialogs: TLDialog[]
dialogs: TLUiDialog[]
}
/** @public */
export const DialogsContext = createContext({} as DialogsContextType)
/** @internal */
export const DialogsContext = createContext({} as TLUiDialogsContextType)
/** @public */
/** @internal */
export type DialogsProviderProps = {
overrides?: (editor: Editor) => DialogsContextType
overrides?: (editor: Editor) => TLUiDialogsContextType
children: any
}
/** @public */
/** @internal */
export function DialogsProvider({ children }: DialogsProviderProps) {
const editor = useEditor()
const trackEvent = useEvents()
const [dialogs, setDialogs] = useState<TLDialog[]>([])
const [dialogs, setDialogs] = useState<TLUiDialog[]>([])
const addDialog = useCallback(
(dialog: Omit<TLDialog, 'id'> & { id?: string }) => {
(dialog: Omit<TLUiDialog, 'id'> & { id?: string }) => {
const id = dialog.id ?? uniqueId()
setDialogs((d) => {
return [...d.filter((m) => m.id !== dialog.id), { ...dialog, id }]
@ -55,7 +55,7 @@ export function DialogsProvider({ children }: DialogsProviderProps) {
)
const updateDialog = useCallback(
(id: string, newDialogData: Partial<TLDialog>) => {
(id: string, newDialogData: Partial<TLUiDialog>) => {
setDialogs((d) =>
d.map((m) => {
if (m.id === id) {

View file

@ -2,7 +2,7 @@ import { useEditor } from '@tldraw/editor'
import { useEffect } from 'react'
import { useToasts } from './useToastsProvider'
/** @public */
/** @internal */
export function useEditorEvents() {
const editor = useEditor()
const { addToast } = useToasts()

View file

@ -96,16 +96,19 @@ export type TLUiEventHandler<T extends keyof TLUiEventMap = keyof TLUiEventMap>
/** @internal */
const defaultEventHandler: TLUiEventHandler = () => void null
/** @internal */
export const EventsContext = React.createContext({} as TLUiEventHandler)
/** @public */
export type TLUiEventContextType = TLUiEventHandler<keyof TLUiEventMap>
/** @internal */
export const EventsContext = React.createContext<TLUiEventContextType>({} as TLUiEventContextType)
/** @internal */
export type EventsProviderProps = {
onEvent?: TLUiEventHandler
children: any
}
/** @public */
/** @internal */
export function EventsProvider({ onEvent, children }: EventsProviderProps) {
return (
<EventsContext.Provider value={onEvent ?? defaultEventHandler}>
@ -115,6 +118,6 @@ export function EventsProvider({ onEvent, children }: EventsProviderProps) {
}
/** @public */
export function useEvents(): TLUiEventHandler<keyof TLUiEventMap> {
export function useEvents() {
return React.useContext(EventsContext)
}

View file

@ -2,41 +2,41 @@ import { Editor, useEditor } from '@tldraw/editor'
import { compact } from '@tldraw/utils'
import React, { useMemo } from 'react'
import { track } from 'signia-react'
import { TLUiLanguage } from '../..'
import { KeyboardShortcutsDialog } from '../components/KeyboardShortcutsDialog'
import { MenuSchema, menuCustom, menuGroup, menuItem } from './menuHelpers'
import { TLUiMenuSchema, menuCustom, menuGroup, menuItem } from './menuHelpers'
import { useActions } from './useActions'
import { useDialogs } from './useDialogsProvider'
import { TLListedTranslations } from './useTranslation/translations'
import { useLanguages } from './useTranslation/useLanguages'
/** @public */
export type HelpMenuSchemaProviderType = MenuSchema
export type TLUiHelpMenuSchemaContextType = TLUiMenuSchema
/** @internal */
export const HelpMenuSchemaContext = React.createContext({} as HelpMenuSchemaProviderType)
export const HelpMenuSchemaContext = React.createContext({} as TLUiHelpMenuSchemaContextType)
/** @public */
export type HelpMenuSchemaProviderProps = {
export type TLUiHelpMenuSchemaProviderProps = {
overrides?: (
editor: Editor,
schema: HelpMenuSchemaProviderType,
schema: TLUiHelpMenuSchemaContextType,
helpers: {
actions: ReturnType<typeof useActions>
languages: TLListedTranslations
languages: readonly TLUiLanguage[]
currentLanguage: string
oneSelected: boolean
twoSelected: boolean
threeSelected: boolean
}
) => HelpMenuSchemaProviderType
) => TLUiHelpMenuSchemaContextType
children: any
}
/** @public */
/** @internal */
export const HelpMenuSchemaProvider = track(function HelpMenuSchemaProvider({
overrides,
children,
}: HelpMenuSchemaProviderProps) {
}: TLUiHelpMenuSchemaProviderProps) {
const editor = useEditor()
const actions = useActions()
@ -49,8 +49,8 @@ export const HelpMenuSchemaProvider = track(function HelpMenuSchemaProvider({
const { languages, currentLanguage } = useLanguages()
const { addDialog } = useDialogs()
const helpMenuSchema = useMemo<MenuSchema>(() => {
const helpMenuSchema = compact([
const helpTLUiMenuSchema = useMemo<TLUiMenuSchema>(() => {
const helpTLUiMenuSchema = compact([
menuGroup(
'top',
menuCustom('LANGUAGE_MENU', { readonlyOk: true }),
@ -66,7 +66,7 @@ export const HelpMenuSchemaProvider = track(function HelpMenuSchemaProvider({
])
if (overrides) {
return overrides(editor, helpMenuSchema, {
return overrides(editor, helpTLUiMenuSchema, {
actions,
currentLanguage,
languages,
@ -76,7 +76,7 @@ export const HelpMenuSchemaProvider = track(function HelpMenuSchemaProvider({
})
}
return helpMenuSchema
return helpTLUiMenuSchema
}, [
editor,
overrides,
@ -90,18 +90,18 @@ export const HelpMenuSchemaProvider = track(function HelpMenuSchemaProvider({
])
return (
<HelpMenuSchemaContext.Provider value={helpMenuSchema}>
<HelpMenuSchemaContext.Provider value={helpTLUiMenuSchema}>
{children}
</HelpMenuSchemaContext.Provider>
)
})
/** @public */
export function useHelpMenuSchema(): MenuSchema {
export function useHelpMenuSchema(): TLUiMenuSchema {
const ctx = React.useContext(HelpMenuSchemaContext)
if (!ctx) {
throw new Error('useHelpMenuSchema must be used inside of a helpMenuSchemaProvider.')
throw new Error('useHelpMenuSchema must be used inside of a helpTLUiMenuSchemaProvider.')
}
return ctx

View file

@ -1,6 +1,6 @@
import { useLayoutEffect } from 'react'
/** @public */
/** @internal */
export function useHighDpiCanvas(ref: React.RefObject<HTMLCanvasElement>, dpr: number) {
// Match the resolution of the client
useLayoutEffect(() => {

View file

@ -2,38 +2,38 @@ import { Editor, useEditor } from '@tldraw/editor'
import { compact } from '@tldraw/utils'
import React, { useMemo } from 'react'
import { track } from 'signia-react'
import { MenuSchema, menuGroup, menuItem } from './menuHelpers'
import { ActionsContextType, useActions } from './useActions'
import { ToolsContextType, useTools } from './useTools'
import { TLUiMenuSchema, menuGroup, menuItem } from './menuHelpers'
import { TLUiActionsContextType, useActions } from './useActions'
import { TLUiToolsContextType, useTools } from './useTools'
/** @public */
export type KeyboardShortcutsSchemaContextType = MenuSchema
export type TLUiKeyboardShortcutsSchemaContextType = TLUiMenuSchema
/** @public */
/** @internal */
export const KeyboardShortcutsSchemaContext = React.createContext(
{} as KeyboardShortcutsSchemaContextType
{} as TLUiKeyboardShortcutsSchemaContextType
)
/** @public */
export type KeyboardShortcutsSchemaProviderProps = {
export type TLUiKeyboardShortcutsSchemaProviderProps = {
overrides?: (
editor: Editor,
schema: KeyboardShortcutsSchemaContextType,
more: { tools: ToolsContextType; actions: ActionsContextType }
) => KeyboardShortcutsSchemaContextType
schema: TLUiKeyboardShortcutsSchemaContextType,
more: { tools: TLUiToolsContextType; actions: TLUiActionsContextType }
) => TLUiKeyboardShortcutsSchemaContextType
children: any
}
/** @public */
/** @internal */
export const KeyboardShortcutsSchemaProvider = track(function KeyboardShortcutsSchemaProvider({
overrides,
children,
}: KeyboardShortcutsSchemaProviderProps) {
}: TLUiKeyboardShortcutsSchemaProviderProps) {
const editor = useEditor()
const tools = useTools()
const actions = useActions()
const keyboardShortcutsSchema = useMemo<MenuSchema>(() => {
const keyboardShortcutsSchema = useMemo<TLUiMenuSchema>(() => {
const keyboardShortcutsSchema = compact([
menuGroup(
'shortcuts-dialog.tools',
@ -118,7 +118,7 @@ export const KeyboardShortcutsSchemaProvider = track(function KeyboardShortcutsS
})
/** @public */
export function useKeyboardShortcutsSchema(): KeyboardShortcutsSchemaContextType {
export function useKeyboardShortcutsSchema(): TLUiKeyboardShortcutsSchemaContextType {
const ctx = React.useContext(KeyboardShortcutsSchemaContext)
if (!ctx) {

View file

@ -3,7 +3,7 @@ import { compact } from '@tldraw/utils'
import React, { useMemo } from 'react'
import { useValue } from 'signia-react'
import {
MenuSchema,
TLUiMenuSchema,
menuCustom,
menuGroup,
menuItem,
@ -20,16 +20,16 @@ import { useHasLinkShapeSelected } from './useHasLinkShapeSelected'
import { useShowAutoSizeToggle } from './useShowAutoSizeToggle'
/** @public */
export type MenuSchemaContextType = MenuSchema
export type TLUiMenuSchemaContextType = TLUiMenuSchema
/** @internal */
export const TLUiMenuSchemaContext = React.createContext({} as TLUiMenuSchemaContextType)
/** @public */
export const MenuSchemaContext = React.createContext({} as MenuSchemaContextType)
/** @public */
export type MenuSchemaProviderProps = {
export type TLUiMenuSchemaProviderProps = {
overrides?: (
editor: Editor,
schema: MenuSchemaContextType,
schema: TLUiMenuSchemaContextType,
helpers: {
actions: ReturnType<typeof useActions>
noneSelected: boolean
@ -37,12 +37,12 @@ export type MenuSchemaProviderProps = {
twoSelected: boolean
threeSelected: boolean
}
) => MenuSchemaContextType
) => TLUiMenuSchemaContextType
children: any
}
/** @public */
export function MenuSchemaProvider({ overrides, children }: MenuSchemaProviderProps) {
/** @internal */
export function TLUiMenuSchemaProvider({ overrides, children }: TLUiMenuSchemaProviderProps) {
const editor = useEditor()
const actions = useActions()
@ -79,7 +79,7 @@ export function MenuSchemaProvider({ overrides, children }: MenuSchemaProviderPr
const canRedo = useCanRedo()
const isZoomedTo100 = useValue('isZoomedTo100', () => editor.zoomLevel === 1, [editor])
const menuSchema = useMemo<MenuSchema>(() => {
const menuSchema = useMemo<TLUiMenuSchema>(() => {
const menuSchema = compact([
menuGroup(
'menu',
@ -221,15 +221,17 @@ export function MenuSchemaProvider({ overrides, children }: MenuSchemaProviderPr
isZoomedTo100,
])
return <MenuSchemaContext.Provider value={menuSchema}>{children}</MenuSchemaContext.Provider>
return (
<TLUiMenuSchemaContext.Provider value={menuSchema}>{children}</TLUiMenuSchemaContext.Provider>
)
}
/** @public */
export function useMenuSchema(): MenuSchema {
const ctx = React.useContext(MenuSchemaContext)
export function useMenuSchema(): TLUiMenuSchema {
const ctx = React.useContext(TLUiMenuSchemaContext)
if (!ctx) {
throw new Error('useMenuSchema must be used inside of a MenuSchemaProvider.')
throw new Error('useMenuSchema must be used inside of a TLUiMenuSchemaProvider.')
}
return ctx

View file

@ -1,5 +1,5 @@
import { useEffect, useState } from 'react'
import { TLUiIconTypes } from '../icon-types'
import { iconTypes } from '../icon-types'
import { useAssetUrls } from './useAssetUrls'
/** @internal */
@ -16,7 +16,7 @@ export function usePreloadIcons(): boolean {
// all of the icons it can so that they're available when we need them.
await Promise.allSettled(
TLUiIconTypes.map((icon) => {
iconTypes.map((icon) => {
const image = new Image()
image.src = assetUrls.icons[icon]
return image.decode()

View file

@ -1,7 +1,7 @@
import { uniqueId, useEditor } from '@tldraw/editor'
import { useCallback, useRef } from 'react'
/** @public */
/** @internal */
export function usePrint() {
const editor = useEditor()
const prevPrintEl = useRef<HTMLDivElement | null>(null)

View file

@ -2,45 +2,45 @@ import { Editor, uniqueId } from '@tldraw/editor'
import { createContext, useCallback, useContext, useState } from 'react'
/** @public */
export interface TLToast {
export interface TLUiToast {
id: string
icon?: string
title?: string
description?: string
actions?: TLToastAction[]
actions?: TLUiToastAction[]
keepOpen?: boolean
closeLabel?: string
}
/** @public */
export interface TLToastAction {
export interface TLUiToastAction {
type: 'primary' | 'secondary' | 'warn'
label: string
onClick: () => void
}
/** @public */
export type ToastsContextType = {
addToast: (toast: Omit<TLToast, 'id'> & { id?: string }) => string
removeToast: (id: TLToast['id']) => string
export type TLUiToastsContextType = {
addToast: (toast: Omit<TLUiToast, 'id'> & { id?: string }) => string
removeToast: (id: TLUiToast['id']) => string
clearToasts: () => void
toasts: TLToast[]
toasts: TLUiToast[]
}
/** @public */
export const ToastsContext = createContext({} as ToastsContextType)
/** @internal */
export const ToastsContext = createContext({} as TLUiToastsContextType)
/** @public */
/** @internal */
export type ToastsProviderProps = {
overrides?: (editor: Editor) => ToastsContextType
overrides?: (editor: Editor) => TLUiToastsContextType
children: any
}
/** @public */
/** @internal */
export function ToastsProvider({ children }: ToastsProviderProps) {
const [toasts, setToasts] = useState<TLToast[]>([])
const [toasts, setToasts] = useState<TLUiToast[]>([])
const addToast = useCallback((toast: Omit<TLToast, 'id'> & { id?: string }) => {
const addToast = useCallback((toast: Omit<TLUiToast, 'id'> & { id?: string }) => {
const id = toast.id ?? uniqueId()
setToasts((d) => [...d.filter((m) => m.id !== toast.id), { ...toast, id }])
return id

View file

@ -2,18 +2,18 @@ import { Editor, featureFlags, useEditor } from '@tldraw/editor'
import { compact } from '@tldraw/utils'
import React from 'react'
import { useValue } from 'signia-react'
import { ToolItem, ToolsContextType, useTools } from './useTools'
import { TLUiToolItem, TLUiToolsContextType, useTools } from './useTools'
/** @public */
export type ToolbarItem = {
export type TLUiToolbarItem = {
id: string
type: 'item'
readonlyOk: boolean
toolItem: ToolItem
toolItem: TLUiToolItem
}
/** @public */
export function toolbarItem(toolItem: ToolItem): ToolbarItem {
export function toolbarItem(toolItem: TLUiToolItem): TLUiToolbarItem {
return {
id: toolItem.id,
type: 'item',
@ -23,30 +23,30 @@ export function toolbarItem(toolItem: ToolItem): ToolbarItem {
}
/** @public */
export type ToolbarSchemaContextType = ToolbarItem[]
export type TLUiToolbarSchemaContextType = TLUiToolbarItem[]
/** @internal */
export const ToolbarSchemaContext = React.createContext([] as TLUiToolbarSchemaContextType)
/** @public */
export const ToolbarSchemaContext = React.createContext([] as ToolbarSchemaContextType)
/** @public */
export type ToolbarSchemaProviderProps = {
export type TLUiToolbarSchemaProviderProps = {
overrides?: (
editor: Editor,
schema: ToolbarSchemaContextType,
more: { tools: ToolsContextType }
) => ToolbarSchemaContextType
schema: TLUiToolbarSchemaContextType,
more: { tools: TLUiToolsContextType }
) => TLUiToolbarSchemaContextType
children: any
}
/** @public */
export function ToolbarSchemaProvider({ overrides, children }: ToolbarSchemaProviderProps) {
/** @internal */
export function ToolbarSchemaProvider({ overrides, children }: TLUiToolbarSchemaProviderProps) {
const editor = useEditor()
const tools = useTools()
const highlighterEnabled = useValue(featureFlags.highlighterTool)
const toolbarSchema = React.useMemo<ToolbarSchemaContextType>(() => {
const schema: ToolbarSchemaContextType = compact([
const toolbarSchema = React.useMemo<TLUiToolbarSchemaContextType>(() => {
const schema: TLUiToolbarSchemaContextType = compact([
toolbarItem(tools.select),
toolbarItem(tools.hand),
toolbarItem(tools.draw),

View file

@ -6,13 +6,13 @@ import { TLUiIconType } from '../icon-types'
import { useDialogs } from './useDialogsProvider'
import { TLUiEventSource, useEvents } from './useEventsProvider'
import { useInsertMedia } from './useInsertMedia'
import { TLTranslationKey } from './useTranslation/TLTranslationKey'
import { TLUiTranslationKey } from './useTranslation/TLUiTranslationKey'
/** @public */
export interface ToolItem {
export interface TLUiToolItem {
id: string
label: TLTranslationKey
shortcutsLabel?: TLTranslationKey
label: TLUiTranslationKey
shortcutsLabel?: TLUiTranslationKey
icon: TLUiIconType
onSelect: (source: TLUiEventSource) => void
kbd?: string
@ -23,23 +23,23 @@ export interface ToolItem {
}
/** @public */
export type ToolsContextType = Record<string, ToolItem>
export type TLUiToolsContextType = Record<string, TLUiToolItem>
/** @internal */
export const ToolsContext = React.createContext({} as TLUiToolsContextType)
/** @public */
export const ToolsContext = React.createContext({} as ToolsContextType)
/** @public */
export type ToolsProviderProps = {
export type TLUiToolsProviderProps = {
overrides?: (
editor: Editor,
tools: ToolsContextType,
tools: TLUiToolsContextType,
helpers: { insertMedia: () => void }
) => ToolsContextType
) => TLUiToolsContextType
children: any
}
/** @public */
export function ToolsProvider({ overrides, children }: ToolsProviderProps) {
/** @internal */
export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
const editor = useEditor()
const trackEvent = useEvents()
@ -48,8 +48,8 @@ export function ToolsProvider({ overrides, children }: ToolsProviderProps) {
const highlighterEnabled = useValue(featureFlags.highlighterTool)
const tools = React.useMemo<ToolsContextType>(() => {
const toolsArray: ToolItem[] = [
const tools = React.useMemo<TLUiToolsContextType>(() => {
const toolsArray: TLUiToolItem[] = [
{
id: 'select',
label: 'tool.select',
@ -96,7 +96,7 @@ export function ToolsProvider({ overrides, children }: ToolsProviderProps) {
},
...[...TL_GEO_TYPES].map((id) => ({
id,
label: `tool.${id}` as TLTranslationKey,
label: `tool.${id}` as TLUiTranslationKey,
readonlyOk: false,
meta: {
geo: id,
@ -218,7 +218,7 @@ export function ToolsProvider({ overrides, children }: ToolsProviderProps) {
})
}
const tools = makeTools(toolsArray)
const tools = Object.fromEntries(toolsArray.map((t) => [t.id, t]))
if (overrides) {
return overrides(editor, tools, { insertMedia })
@ -230,10 +230,6 @@ export function ToolsProvider({ overrides, children }: ToolsProviderProps) {
return <ToolsContext.Provider value={tools}>{children}</ToolsContext.Provider>
}
function makeTools(tools: ToolItem[]) {
return Object.fromEntries(tools.map((t) => [t.id, t]))
}
/** @public */
export function useTools() {
const ctx = React.useContext(ToolsContext)

View file

@ -2,7 +2,7 @@
// Do not edit manually.
/** @public */
export type TLTranslationKey =
export type TLUiTranslationKey =
| 'action.convert-to-bookmark'
| 'action.convert-to-embed'
| 'action.open-embed-link'

View file

@ -1,7 +1,7 @@
import { UiAssetUrls } from '../../assetUrls'
import { TLUiAssetUrls } from '../../assetUrls'
import { TLUiTranslationKey } from './TLUiTranslationKey'
import { DEFAULT_TRANSLATION } from './defaultTranslation'
import { LANGUAGES } from './languages'
import { TLTranslationKey } from './TLTranslationKey'
// The default language (english) must have a value for every message.
// Other languages may have missing messages. If the application finds
@ -11,42 +11,29 @@ import { TLTranslationKey } from './TLTranslationKey'
/* ----------------- (do not change) ---------------- */
/** @public */
export type TLListedTranslation = {
export type TLUiLanguage = {
readonly locale: string
readonly label: string
}
/** @public */
export type TLListedTranslations = readonly TLListedTranslation[]
/** @public */
export type TLTranslationMessages = Record<TLTranslationKey, string>
/** @public */
export type TLTranslation = {
export type TLUiTranslation = {
readonly locale: string
readonly label: string
readonly messages: TLTranslationMessages
readonly messages: Record<TLUiTranslationKey, string>
}
/** @public */
export type TLTranslations = TLTranslation[]
/** @public */
export type TLTranslationLocale = TLTranslations[number]['locale']
/** @public */
export const EN_TRANSLATION: TLTranslation = {
const EN_TRANSLATION: TLUiTranslation = {
locale: 'en',
label: 'English',
messages: DEFAULT_TRANSLATION as TLTranslationMessages,
messages: DEFAULT_TRANSLATION as TLUiTranslation['messages'],
}
/** @public */
/** @internal */
export async function fetchTranslation(
locale: TLTranslationLocale,
assetUrls: UiAssetUrls
): Promise<TLTranslation> {
locale: TLUiTranslation['locale'],
assetUrls: TLUiAssetUrls
): Promise<TLUiTranslation> {
const mainRes = await fetch(assetUrls.translations.en)
if (!mainRes.ok) {
@ -66,7 +53,7 @@ export async function fetchTranslation(
}
const res = await fetch(assetUrls.translations[language.locale])
const messages: TLTranslationMessages = await res.json()
const messages: TLUiTranslation['messages'] = await res.json()
if (!messages) {
console.warn(`No messages found for locale ${locale}`)
@ -76,7 +63,7 @@ export async function fetchTranslation(
const missing: string[] = []
for (const key in EN_TRANSLATION) {
if (!messages[key as TLTranslationKey]) {
if (!messages[key as TLUiTranslationKey]) {
missing.push(key)
}
}
@ -91,11 +78,3 @@ export async function fetchTranslation(
messages: { ...EN_TRANSLATION.messages, ...messages },
}
}
/** @public */
export async function getTranslation(
locale: TLTranslationLocale,
assetUrls: UiAssetUrls
): Promise<TLTranslation> {
return await fetchTranslation(locale, assetUrls)
}

View file

@ -1,8 +1,12 @@
import { useEditor } from '@tldraw/editor'
import { LANGUAGES } from './languages'
import { TLUiLanguage } from './translations'
/** @public */
/** @internal */
export function useLanguages() {
const editor = useEditor()
return { languages: LANGUAGES, currentLanguage: editor.locale }
return {
languages: LANGUAGES as readonly TLUiLanguage[],
currentLanguage: editor.locale,
}
}

View file

@ -2,12 +2,12 @@ import { useEditor } from '@tldraw/editor'
import * as React from 'react'
import { track } from 'signia-react'
import { useAssetUrls } from '../useAssetUrls'
import { TLTranslationKey } from './TLTranslationKey'
import { TLUiTranslationKey } from './TLUiTranslationKey'
import { DEFAULT_TRANSLATION } from './defaultTranslation'
import { TLTranslation, getTranslation } from './translations'
import { TLUiTranslation, fetchTranslation } from './translations'
/** @public */
export interface TranslationProviderProps {
export interface TLUiTranslationProviderProps {
children: any
/**
* (optional) A collection of overrides different locales.
@ -21,24 +21,29 @@ export interface TranslationProviderProps {
overrides?: Record<string, Record<string, string>>
}
const TranslationsContext = React.createContext<TLTranslation>({} as TLTranslation)
/** @public */
export type TLUiTranslationContextType = TLUiTranslation
const TranslationsContext = React.createContext<TLUiTranslationContextType>(
{} as TLUiTranslationContextType
)
const useCurrentTranslation = () => React.useContext(TranslationsContext)
/**
* Provides a translation context to the editor.
*
* @public
* @internal
*/
export const TranslationProvider = track(function TranslationProvider({
overrides,
children,
}: TranslationProviderProps) {
}: TLUiTranslationProviderProps) {
const editor = useEditor()
const locale = editor.locale
const getAssetUrl = useAssetUrls()
const [currentTranslation, setCurrentTranslation] = React.useState<TLTranslation>(() => {
const [currentTranslation, setCurrentTranslation] = React.useState<TLUiTranslation>(() => {
if (overrides && overrides['en']) {
return {
locale: 'en',
@ -58,7 +63,7 @@ export const TranslationProvider = track(function TranslationProvider({
let isCancelled = false
async function loadTranslation() {
const translation = await getTranslation(locale, getAssetUrl)
const translation = await fetchTranslation(locale, getAssetUrl)
if (translation && !isCancelled) {
if (overrides && overrides[locale]) {
@ -101,7 +106,7 @@ export const TranslationProvider = track(function TranslationProvider({
export function useTranslation() {
const translation = useCurrentTranslation()
return React.useCallback(
function msg(id: TLTranslationKey) {
function msg(id: TLUiTranslationKey) {
return translation.messages[id] ?? id
},
[translation]

View file

@ -166,7 +166,7 @@ export type TLUiIconType =
| 'zoom-out'
/** @public */
export const TLUiIconTypes = [
export const iconTypes = [
'align-bottom-center',
'align-bottom-left',
'align-bottom-right',

View file

@ -4,15 +4,15 @@ import { useMemo } from 'react'
import { ActionsProviderProps } from './hooks/useActions'
import { ActionsMenuSchemaProviderProps } from './hooks/useActionsMenuSchema'
import { useBreakpoint } from './hooks/useBreakpoint'
import { ContextMenuSchemaProviderProps } from './hooks/useContextMenuSchema'
import { TLUiContextMenuSchemaProviderProps } from './hooks/useContextMenuSchema'
import { useDialogs } from './hooks/useDialogsProvider'
import { HelpMenuSchemaProviderProps } from './hooks/useHelpMenuSchema'
import { KeyboardShortcutsSchemaProviderProps } from './hooks/useKeyboardShortcutsSchema'
import { MenuSchemaProviderProps } from './hooks/useMenuSchema'
import { TLUiHelpMenuSchemaProviderProps } from './hooks/useHelpMenuSchema'
import { TLUiKeyboardShortcutsSchemaProviderProps } from './hooks/useKeyboardShortcutsSchema'
import { TLUiMenuSchemaProviderProps } from './hooks/useMenuSchema'
import { useToasts } from './hooks/useToastsProvider'
import { ToolbarSchemaProviderProps } from './hooks/useToolbarSchema'
import { ToolsProviderProps } from './hooks/useTools'
import { TranslationProviderProps, useTranslation } from './hooks/useTranslation/useTranslation'
import { TLUiToolbarSchemaProviderProps } from './hooks/useToolbarSchema'
import { TLUiToolsProviderProps } from './hooks/useTools'
import { TLUiTranslationProviderProps, useTranslation } from './hooks/useTranslation/useTranslation'
/** @public */
export function useDefaultHelpers() {
@ -49,51 +49,47 @@ export function useDefaultHelpers() {
type DefaultHelpers = ReturnType<typeof useDefaultHelpers>
export type TldrawUiOverride<Type, Helpers> = (
editor: Editor,
schema: Type,
helpers: Helpers
) => Type
export type TLUiOverride<Type, Helpers> = (editor: Editor, schema: Type, helpers: Helpers) => Type
type WithDefaultHelpers<T extends TldrawUiOverride<any, any>> = T extends TldrawUiOverride<
type WithDefaultHelpers<T extends TLUiOverride<any, any>> = T extends TLUiOverride<
infer Type,
infer Helpers
>
? TldrawUiOverride<Type, Helpers extends undefined ? DefaultHelpers : Helpers & DefaultHelpers>
? TLUiOverride<Type, Helpers extends undefined ? DefaultHelpers : Helpers & DefaultHelpers>
: never
/** @public */
export interface TldrawUiOverrides {
export interface TLUiOverrides {
actionsMenu?: WithDefaultHelpers<NonNullable<ActionsMenuSchemaProviderProps['overrides']>>
actions?: WithDefaultHelpers<NonNullable<ActionsProviderProps['overrides']>>
contextMenu?: WithDefaultHelpers<NonNullable<ContextMenuSchemaProviderProps['overrides']>>
helpMenu?: WithDefaultHelpers<NonNullable<HelpMenuSchemaProviderProps['overrides']>>
menu?: WithDefaultHelpers<NonNullable<MenuSchemaProviderProps['overrides']>>
toolbar?: WithDefaultHelpers<NonNullable<ToolbarSchemaProviderProps['overrides']>>
contextMenu?: WithDefaultHelpers<NonNullable<TLUiContextMenuSchemaProviderProps['overrides']>>
helpMenu?: WithDefaultHelpers<NonNullable<TLUiHelpMenuSchemaProviderProps['overrides']>>
menu?: WithDefaultHelpers<NonNullable<TLUiMenuSchemaProviderProps['overrides']>>
toolbar?: WithDefaultHelpers<NonNullable<TLUiToolbarSchemaProviderProps['overrides']>>
keyboardShortcutsMenu?: WithDefaultHelpers<
NonNullable<KeyboardShortcutsSchemaProviderProps['overrides']>
NonNullable<TLUiKeyboardShortcutsSchemaProviderProps['overrides']>
>
tools?: WithDefaultHelpers<NonNullable<ToolsProviderProps['overrides']>>
translations?: TranslationProviderProps['overrides']
tools?: WithDefaultHelpers<NonNullable<TLUiToolsProviderProps['overrides']>>
translations?: TLUiTranslationProviderProps['overrides']
}
export interface TldrawUiOverridesWithoutDefaults {
export interface TLUiOverridesWithoutDefaults {
actionsMenu?: ActionsMenuSchemaProviderProps['overrides']
actions?: ActionsProviderProps['overrides']
contextMenu?: ContextMenuSchemaProviderProps['overrides']
helpMenu?: HelpMenuSchemaProviderProps['overrides']
menu?: MenuSchemaProviderProps['overrides']
toolbar?: ToolbarSchemaProviderProps['overrides']
keyboardShortcutsMenu?: KeyboardShortcutsSchemaProviderProps['overrides']
tools?: ToolsProviderProps['overrides']
translations?: TranslationProviderProps['overrides']
contextMenu?: TLUiContextMenuSchemaProviderProps['overrides']
helpMenu?: TLUiHelpMenuSchemaProviderProps['overrides']
menu?: TLUiMenuSchemaProviderProps['overrides']
toolbar?: TLUiToolbarSchemaProviderProps['overrides']
keyboardShortcutsMenu?: TLUiKeyboardShortcutsSchemaProviderProps['overrides']
tools?: TLUiToolsProviderProps['overrides']
translations?: TLUiTranslationProviderProps['overrides']
}
export function mergeOverrides(
overrides: TldrawUiOverrides[],
overrides: TLUiOverrides[],
defaultHelpers: DefaultHelpers
): TldrawUiOverridesWithoutDefaults {
const mergedTranslations: TranslationProviderProps['overrides'] = {}
): TLUiOverridesWithoutDefaults {
const mergedTranslations: TLUiTranslationProviderProps['overrides'] = {}
for (const override of overrides) {
if (override.translations) {
for (const [key, value] of objectMapEntries(override.translations)) {
@ -180,13 +176,13 @@ function useShallowArrayEquality<T extends unknown[]>(array: T): T {
}
export function useMergedTranslationOverrides(
overrides?: TldrawUiOverrides[] | TldrawUiOverrides
): NonNullable<TranslationProviderProps['overrides']> {
overrides?: TLUiOverrides[] | TLUiOverrides
): NonNullable<TLUiTranslationProviderProps['overrides']> {
const overridesArray = useShallowArrayEquality(
overrides == null ? [] : Array.isArray(overrides) ? overrides : [overrides]
)
return useMemo(() => {
const mergedTranslations: TranslationProviderProps['overrides'] = {}
const mergedTranslations: TLUiTranslationProviderProps['overrides'] = {}
for (const override of overridesArray) {
if (override.translations) {
for (const [key, value] of objectMapEntries(override.translations)) {
@ -203,8 +199,8 @@ export function useMergedTranslationOverrides(
}
export function useMergedOverrides(
overrides?: TldrawUiOverrides[] | TldrawUiOverrides
): TldrawUiOverridesWithoutDefaults {
overrides?: TLUiOverrides[] | TLUiOverrides
): TLUiOverridesWithoutDefaults {
const defaultHelpers = useDefaultHelpers()
const overridesArray = useShallowArrayEquality(
overrides == null ? [] : Array.isArray(overrides) ? overrides : [overrides]

View file

@ -85,7 +85,7 @@ async function copyIcons() {
${icons.map((icon) => JSON.stringify(icon.replace('.svg', ''))).join(' | ')}
/** @public */
export const TLUiIconTypes = [
export const iconTypes = [
${icons.map((icon) => JSON.stringify(icon.replace('.svg', ''))).join(', ')}
] as const`
@ -239,10 +239,10 @@ async function copyTranslations() {
// translationKeys.ts
const translationKeys = Object.keys(defaultTranslation).map((key) => `'${key}'`)
const translationKeysFilePath = join(uiPath, 'TLTranslationKey.ts')
const translationKeysFilePath = join(uiPath, 'TLUiTranslationKey.ts')
const translationKeysFile = `
/** @public */
export type TLTranslationKey = ${translationKeys.join(' | ')}
export type TLUiTranslationKey = ${translationKeys.join(' | ')}
`
await writeCodeFile(
'scripts/refresh-assets.ts',