make sure everything marked @public gets documented (#3892)

Previously, we had the `ae-forgotten-export` rule from api-extractor
disabled. This rule makes sure that everything that's referred to in the
public API is actually exported. There are more details on the rule
[here](https://api-extractor.com/pages/messages/ae-forgotten-export/),
but not exporting public API entires is bad because they're hard to
document and can't be typed/called from consumer code. For us, the big
effect is that they don't appear in our docs at all.

This diff re-enables that rule. Now, if you introduce something new to
the public API but don't export it, your build will fail.

### Change Type

- [x] `docs` — Changes to the documentation, examples, or templates.
- [x] `improvement` — Improving existing features
This commit is contained in:
alex 2024-06-10 14:50:03 +01:00 committed by GitHub
parent f5a6ed7b91
commit fb0dd1d2fe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
87 changed files with 2378 additions and 1014 deletions

View file

@ -1,17 +1,11 @@
import {
LegacyTldrawDocument,
TldrawUiButton,
TldrawUiButtonLabel,
useEditor,
useValue,
} from 'tldraw'
import { TLV1Document, TldrawUiButton, TldrawUiButtonLabel, useEditor, useValue } from 'tldraw'
export function MigrationAnnouncement({
onClose,
originalFile,
}: {
onClose: () => void
originalFile: { name: string; document: LegacyTldrawDocument }
originalFile: { name: string; document: TLV1Document }
}) {
const editor = useEditor()
const isDarkMode = useValue('is dark mode', () => editor.user.getIsDarkMode(), [editor])

View file

@ -1,5 +1,5 @@
import { openDB } from 'idb'
import { Editor, LegacyTldrawDocument, buildFromV1Document } from 'tldraw'
import { Editor, TLV1Document, buildFromV1Document } from 'tldraw'
export function isEditorEmpty(editor: Editor) {
const hasAnyShapes = editor.store.allRecords().some((r) => r.typeName === 'shape')
@ -7,7 +7,7 @@ export function isEditorEmpty(editor: Editor) {
}
export async function findV1ContentFromIdb(): Promise<{
document: LegacyTldrawDocument
document: TLV1Document
clear: () => Promise<void>
} | null> {
try {
@ -28,7 +28,7 @@ export async function findV1ContentFromIdb(): Promise<{
typeof home.document.version === 'number'
) {
return {
document: home.document as LegacyTldrawDocument,
document: home.document as TLV1Document,
clear: async () => {
try {
const tx = db.transaction('keyval', 'readwrite')
@ -52,7 +52,7 @@ export async function findV1ContentFromIdb(): Promise<{
export async function importFromV1LocalRoom(
editor: Editor,
didCancel: () => boolean
): Promise<{ didImport: false } | { didImport: true; document: LegacyTldrawDocument }> {
): Promise<{ didImport: false } | { didImport: true; document: TLV1Document }> {
const v1Doc = await findV1ContentFromIdb()
if (didCancel() || !v1Doc) return { didImport: false }
@ -75,7 +75,7 @@ export async function importFromV1MultiplayerRoom(
editor: Editor,
roomSlug: string,
didCancel: () => boolean
): Promise<{ didImport: false } | { didImport: true; document: LegacyTldrawDocument }> {
): Promise<{ didImport: false } | { didImport: true; document: TLV1Document }> {
const response = await fetch(`/api/static-legacy-multiplayer?roomSlug=${roomSlug}`)
if (!response.ok || didCancel()) {
return { didImport: false }
@ -89,7 +89,7 @@ export async function importFromV1MultiplayerRoom(
// TODO: handle weird data formats (TLD-1605) & v1 migrations (TLD-1638)
const { assets, bindings, shapes, version } = data.room.storage.data
const PAGE_ID = 'page'
const document: LegacyTldrawDocument = {
const document: TLV1Document = {
id: 'doc',
name: roomSlug,
version,

View file

@ -370,7 +370,7 @@
"addToApiReportFile": false
},
"ae-forgotten-export": {
"logLevel": "none",
"logLevel": "error",
"addToApiReportFile": false
}
// "ae-extra-release-tag": {

View file

@ -154,7 +154,7 @@ export function average(A: VecLike, B: VecLike): string;
// @public (undocumented)
export abstract class BaseBoxShapeTool extends StateNode {
// (undocumented)
static children: () => (typeof Idle | typeof Pointing)[];
static children: () => TLStateNodeConstructor[];
// (undocumented)
static id: string;
// (undocumented)
@ -253,6 +253,32 @@ export interface BoundsSnapPoint {
y: number;
}
// @public (undocumented)
export class BoundsSnaps {
constructor(manager: SnapManager);
// (undocumented)
readonly editor: Editor;
// (undocumented)
getSnapPoints(shapeId: TLShapeId): BoundsSnapPoint[];
// (undocumented)
readonly manager: SnapManager;
// (undocumented)
snapResizeShapes({ initialSelectionPageBounds, dragDelta, handle: originalHandle, isAspectRatioLocked, isResizingFromCenter, }: {
dragDelta: Vec;
handle: SelectionCorner | SelectionEdge;
initialSelectionPageBounds: Box;
isAspectRatioLocked: boolean;
isResizingFromCenter: boolean;
}): SnapData;
// (undocumented)
snapTranslateShapes({ lockedAxis, initialSelectionPageBounds, initialSelectionSnapPoints, dragDelta, }: {
dragDelta: Vec;
initialSelectionPageBounds: Box;
initialSelectionSnapPoints: BoundsSnapPoint[];
lockedAxis: 'x' | 'y' | null;
}): SnapData;
}
// @public (undocumented)
export class Box {
constructor(x?: number, y?: number, w?: number, h?: number);
@ -425,6 +451,20 @@ export function clamp(n: number, min: number, max: number): number;
// @public
export function clampRadians(r: number): number;
// @public (undocumented)
export class ClickManager {
constructor(editor: Editor);
// @internal
cancelDoubleClickTimeout: () => void;
get clickState(): TLClickState | undefined;
// (undocumented)
editor: Editor;
// (undocumented)
handlePointerEvent: (info: TLPointerEventInfo) => TLClickEventInfo | TLPointerEventInfo;
// (undocumented)
lastPointerInfo: TLPointerEventInfo;
}
// @public
export function clockwiseAngleDist(a0: number, a1: number): number;
@ -514,6 +554,28 @@ export function dataUrlToFile(url: string, filename: string, mimeType: string):
// @internal (undocumented)
export type DebugFlag<T> = DebugFlagDef<T> & Atom<T>;
// @internal (undocumented)
export interface DebugFlagDef<T> {
// (undocumented)
defaults: DebugFlagDefaults<T>;
// (undocumented)
name: string;
// (undocumented)
shouldStoreForSession: boolean;
}
// @internal (undocumented)
export interface DebugFlagDefaults<T> {
// (undocumented)
all: T;
// (undocumented)
development?: T;
// (undocumented)
production?: T;
// (undocumented)
staging?: T;
}
// @internal (undocumented)
export const debugFlags: {
readonly debugCursors: DebugFlag<boolean>;
@ -1051,7 +1113,7 @@ export class Editor extends EventEmitter<TLEventMap> {
reparentShapes(shapes: TLShape[] | TLShapeId[], parentId: TLParentId, insertIndex?: IndexKey): this;
resetZoom(point?: Vec, opts?: TLCameraMoveOptions): this;
resizeShape(shape: TLShape | TLShapeId, scale: VecLike, options?: TLResizeShapeOptions): this;
readonly root: RootState;
readonly root: StateNode;
rotateShapesBy(shapes: TLShape[] | TLShapeId[], delta: number): this;
screenToPage(point: VecLike): Vec;
readonly scribbles: ScribbleManager;
@ -1172,7 +1234,21 @@ export class Ellipse2d extends Geometry2d {
export { EMPTY_ARRAY }
// @public (undocumented)
export class ErrorBoundary extends React_3.Component<React_3.PropsWithRef<React_3.PropsWithChildren<TLErrorBoundaryProps>>, TLErrorBoundaryState> {
export class EnvironmentManager {
constructor(editor: Editor);
// (undocumented)
editor: Editor;
readonly isAndroid: boolean;
readonly isChromeForIos: boolean;
readonly isFirefox: boolean;
readonly isIos: boolean;
readonly isSafari: boolean;
}
// @public (undocumented)
export class ErrorBoundary extends React_3.Component<React_3.PropsWithRef<React_3.PropsWithChildren<TLErrorBoundaryProps>>, {
error: Error | null;
}> {
// (undocumented)
componentDidCatch(error: unknown): void;
// (undocumented)
@ -1182,7 +1258,9 @@ export class ErrorBoundary extends React_3.Component<React_3.PropsWithRef<React_
// (undocumented)
render(): boolean | JSX_2.Element | Iterable<React_3.ReactNode> | null | number | string | undefined;
// (undocumented)
state: TLErrorBoundaryState;
state: {
error: null;
};
}
// @public (undocumented)
@ -1265,6 +1343,20 @@ export abstract class Geometry2d {
get vertices(): Vec[];
}
// @public (undocumented)
export interface Geometry2dOptions {
// (undocumented)
debugColor?: string;
// (undocumented)
ignore?: boolean;
// (undocumented)
isClosed: boolean;
// (undocumented)
isFilled: boolean;
// (undocumented)
isLabel?: boolean;
}
// @public
export function getArcMeasure(A: number, B: number, sweepFlag: number, largeArcFlag: number): number;
@ -1382,6 +1474,20 @@ export interface HandleSnapGeometry {
points?: VecModel[];
}
// @public (undocumented)
export class HandleSnaps {
constructor(manager: SnapManager);
// (undocumented)
readonly editor: Editor;
// (undocumented)
readonly manager: SnapManager;
// (undocumented)
snapHandle({ currentShapeId, handle, }: {
currentShapeId: TLShapeId;
handle: TLHandle;
}): null | SnapData;
}
// @public
export function hardReset({ shouldReload }?: {
shouldReload?: boolean | undefined;
@ -1411,7 +1517,7 @@ export class HistoryManager<R extends UnknownRecord> {
isEmpty: boolean;
};
redos: (NonNullable<TLHistoryEntry<R>> | undefined)[];
state: HistoryRecorderState;
state: string;
undos: (NonNullable<TLHistoryEntry<R>> | undefined)[];
};
// (undocumented)
@ -1430,11 +1536,6 @@ export class HistoryManager<R extends UnknownRecord> {
onBatchComplete: () => void;
// (undocumented)
redo: () => this | undefined;
// @internal (undocumented)
stacks: Atom< {
redos: Stack<TLHistoryEntry<R>>;
undos: Stack<TLHistoryEntry<R>>;
}, unknown>;
// (undocumented)
undo: () => this;
}
@ -1637,6 +1738,9 @@ export function OptionalErrorBoundary({ children, fallback, ...props }: Omit<TLE
fallback: TLErrorFallbackComponent;
}): JSX_2.Element;
// @public (undocumented)
export type OptionalKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
// @public
export function perimeterOfEllipse(rx: number, ry: number): number;
@ -1834,6 +1938,38 @@ export const runtime: {
refreshPage: () => void;
};
// @public (undocumented)
export interface ScribbleItem {
// (undocumented)
delayRemaining: number;
// (undocumented)
id: string;
// (undocumented)
next: null | VecModel;
// (undocumented)
prev: null | VecModel;
// (undocumented)
scribble: TLScribble;
// (undocumented)
timeoutMs: number;
}
// @public (undocumented)
export class ScribbleManager {
constructor(editor: Editor);
addPoint: (id: ScribbleItem['id'], x: number, y: number) => ScribbleItem;
// (undocumented)
addScribble: (scribble: Partial<TLScribble>, id?: string) => ScribbleItem;
// (undocumented)
reset(): void;
// (undocumented)
scribbleItems: Map<string, ScribbleItem>;
// (undocumented)
state: "paused" | "running";
stop: (id: ScribbleItem['id']) => ScribbleItem;
tick: (elapsed: number) => void;
}
// @public (undocumented)
export type SelectionCorner = 'bottom_left' | 'bottom_right' | 'top_left' | 'top_right';
@ -1948,6 +2084,12 @@ export const SIN: (x: number) => number;
// @public
export function snapAngle(r: number, segments: number): number;
// @public (undocumented)
export interface SnapData {
// (undocumented)
nudge: Vec;
}
// @public (undocumented)
export type SnapIndicator = GapsSnapIndicator | PointsSnapIndicator;
@ -2090,7 +2232,7 @@ export abstract class StateNode implements Partial<TLEventHandlers> {
shapeType?: string;
transition: (id: string, info?: any) => this;
// (undocumented)
type: TLStateNodeType;
type: 'branch' | 'leaf' | 'root';
}
// @public (undocumented)
@ -2119,6 +2261,42 @@ export interface SvgExportDef {
// @public
export const TAB_ID: string;
// @public (undocumented)
export class TextManager {
constructor(editor: Editor);
// (undocumented)
baseElm: HTMLDivElement;
// (undocumented)
editor: Editor;
measureElementTextNodeSpans(element: HTMLElement, { shouldTruncateToFirstLine }?: {
shouldTruncateToFirstLine?: boolean;
}): {
didTruncate: boolean;
spans: {
box: BoxModel;
text: string;
}[];
};
// (undocumented)
measureText: (textToMeasure: string, opts: {
maxWidth: null | number;
disableOverflowWrapBreaking?: boolean;
fontFamily: string;
fontSize: number;
fontStyle: string;
fontWeight: string;
lineHeight: number;
minWidth?: null | number;
padding: string;
}) => BoxModel & {
scrollWidth: number;
};
measureTextSpans(textToMeasure: string, opts: TLMeasureTextSpanOpts): {
box: BoxModel;
text: string;
}[];
}
// @public (undocumented)
export type TLAnyBindingUtilConstructor = TLBindingUtilConstructor<any>;
@ -2210,6 +2388,12 @@ export interface TLCancelEventInfo {
type: 'misc';
}
// @public (undocumented)
export interface TLCanvasComponentProps {
// (undocumented)
className?: string;
}
// @public (undocumented)
export type TLClickEvent = (info: TLClickEventInfo) => void;
@ -2226,6 +2410,9 @@ export type TLClickEventInfo = TLBaseEventInfo & {
// @public (undocumented)
export type TLCLickEventName = 'double_click' | 'quadruple_click' | 'triple_click';
// @public (undocumented)
export type TLClickState = 'idle' | 'overflow' | 'pendingDouble' | 'pendingOverflow' | 'pendingQuadruple' | 'pendingTriple';
// @public (undocumented)
export interface TLCollaboratorHintProps {
// (undocumented)
@ -2375,9 +2562,60 @@ export interface TldrawOptions {
}
// @public (undocumented)
export type TLEditorComponents = Partial<{
[K in keyof BaseEditorComponents]: BaseEditorComponents[K] | null;
} & ErrorComponents>;
export interface TLEditorComponents {
// (undocumented)
Background?: ComponentType | null;
// (undocumented)
Brush?: ComponentType<TLBrushProps> | null;
// (undocumented)
Canvas?: ComponentType<TLCanvasComponentProps> | null;
// (undocumented)
CollaboratorBrush?: ComponentType<TLBrushProps> | null;
// (undocumented)
CollaboratorCursor?: ComponentType<TLCursorProps> | null;
// (undocumented)
CollaboratorHint?: ComponentType<TLCollaboratorHintProps> | null;
// (undocumented)
CollaboratorScribble?: ComponentType<TLScribbleProps> | null;
// (undocumented)
CollaboratorShapeIndicator?: ComponentType<TLShapeIndicatorProps> | null;
// (undocumented)
Cursor?: ComponentType<TLCursorProps> | null;
// (undocumented)
ErrorFallback?: TLErrorFallbackComponent;
// (undocumented)
Grid?: ComponentType<TLGridProps> | null;
// (undocumented)
Handle?: ComponentType<TLHandleProps> | null;
// (undocumented)
Handles?: ComponentType<TLHandlesProps> | null;
// (undocumented)
InFrontOfTheCanvas?: ComponentType | null;
// (undocumented)
LoadingScreen?: ComponentType | null;
// (undocumented)
OnTheCanvas?: ComponentType | null;
// (undocumented)
Scribble?: ComponentType<TLScribbleProps> | null;
// (undocumented)
SelectionBackground?: ComponentType<TLSelectionBackgroundProps> | null;
// (undocumented)
SelectionForeground?: ComponentType<TLSelectionForegroundProps> | null;
// (undocumented)
ShapeErrorFallback?: TLShapeErrorFallbackComponent;
// (undocumented)
ShapeIndicator?: ComponentType<TLShapeIndicatorProps> | null;
// (undocumented)
ShapeIndicatorErrorFallback?: TLShapeIndicatorErrorFallbackComponent;
// (undocumented)
SnapIndicator?: ComponentType<TLSnapIndicatorProps> | null;
// (undocumented)
Spinner?: ComponentType | null;
// (undocumented)
SvgDefs?: ComponentType | null;
// (undocumented)
ZoomBrush?: ComponentType<TLBrushProps> | null;
}
// @public (undocumented)
export interface TLEditorOptions {
@ -2416,6 +2654,12 @@ export interface TLErrorBoundaryProps {
onError?: ((error: unknown) => void) | null;
}
// @public (undocumented)
export type TLErrorFallbackComponent = ComponentType<{
editor?: Editor;
error: unknown;
}>;
// @public (undocumented)
export interface TLEventHandlers {
// (undocumented)
@ -2581,6 +2825,30 @@ export interface TLHandlesProps {
children: ReactNode;
}
// @public (undocumented)
export interface TLHistoryBatchOptions {
history?: 'ignore' | 'record-preserveRedoStack' | 'record';
}
// @public (undocumented)
export interface TLHistoryDiff<R extends UnknownRecord> {
// (undocumented)
diff: RecordsDiff<R>;
// (undocumented)
type: 'diff';
}
// @public (undocumented)
export type TLHistoryEntry<R extends UnknownRecord> = TLHistoryDiff<R> | TLHistoryMark;
// @public (undocumented)
export interface TLHistoryMark {
// (undocumented)
id: string;
// (undocumented)
type: 'stop';
}
// @public (undocumented)
export type TLInterruptEvent = (info: TLInterruptEventInfo) => void;
@ -2606,6 +2874,30 @@ export type TLKeyboardEventInfo = TLBaseEventInfo & {
// @public (undocumented)
export type TLKeyboardEventName = 'key_down' | 'key_repeat' | 'key_up';
// @public (undocumented)
export interface TLMeasureTextSpanOpts {
// (undocumented)
fontFamily: string;
// (undocumented)
fontSize: number;
// (undocumented)
fontStyle: string;
// (undocumented)
fontWeight: string;
// (undocumented)
height: number;
// (undocumented)
lineHeight: number;
// (undocumented)
overflow: 'truncate-clip' | 'truncate-ellipsis' | 'wrap';
// (undocumented)
padding: number;
// (undocumented)
textAlign: TLDefaultHorizontalAlignStyle;
// (undocumented)
width: number;
}
// @public (undocumented)
export type TLOnBeforeCreateHandler<T extends TLShape> = (next: T) => T | void;
@ -2644,31 +2936,31 @@ export type TLOnHandleDragHandler<T extends TLShape> = (shape: T, info: {
export type TLOnMountHandler = (editor: Editor) => (() => undefined | void) | undefined | void;
// @public (undocumented)
export type TLOnResizeEndHandler<T extends TLShape> = TLEventChangeHandler<T>;
export type TLOnResizeEndHandler<T extends TLShape> = (initial: T, current: T) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnResizeHandler<T extends TLShape> = (shape: T, info: TLResizeInfo<T>) => Omit<TLShapePartial<T>, 'id' | 'type'> | undefined | void;
// @public (undocumented)
export type TLOnResizeStartHandler<T extends TLShape> = TLEventStartHandler<T>;
export type TLOnResizeStartHandler<T extends TLShape> = (shape: T) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnRotateEndHandler<T extends TLShape> = TLEventChangeHandler<T>;
export type TLOnRotateEndHandler<T extends TLShape> = (initial: T, current: T) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnRotateHandler<T extends TLShape> = TLEventChangeHandler<T>;
export type TLOnRotateHandler<T extends TLShape> = (initial: T, current: T) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnRotateStartHandler<T extends TLShape> = TLEventStartHandler<T>;
export type TLOnRotateStartHandler<T extends TLShape> = (shape: T) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnTranslateEndHandler<T extends TLShape> = TLEventChangeHandler<T>;
export type TLOnTranslateEndHandler<T extends TLShape> = (initial: T, current: T) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnTranslateHandler<T extends TLShape> = TLEventChangeHandler<T>;
export type TLOnTranslateHandler<T extends TLShape> = (initial: T, current: T) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnTranslateStartHandler<T extends TLShape> = TLEventStartHandler<T>;
export type TLOnTranslateStartHandler<T extends TLShape> = (shape: T) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLPinchEvent = (info: TLPinchEventInfo) => void;
@ -2831,6 +3123,16 @@ export interface TLSessionStateSnapshot {
version: number;
}
// @public (undocumented)
export type TLShapeErrorFallbackComponent = ComponentType<{
error: any;
}>;
// @public (undocumented)
export type TLShapeIndicatorErrorFallbackComponent = ComponentType<{
error: unknown;
}>;
// @public (undocumented)
export interface TLShapeIndicatorProps {
// (undocumented)
@ -2956,6 +3258,26 @@ export interface TLSvgOptions {
// @public (undocumented)
export type TLTickEvent = (info: TLTickEventInfo) => void;
// @public (undocumented)
export interface TLTickEventInfo {
// (undocumented)
elapsed: number;
// (undocumented)
name: 'tick';
// (undocumented)
type: 'misc';
}
// @public (undocumented)
export interface TLUser {
// (undocumented)
readonly derivePresenceState: (store: TLStore) => Signal<null | TLInstancePresence>;
// (undocumented)
readonly setUserPreferences: (userPreferences: TLUserPreferences) => void;
// (undocumented)
readonly userPreferences: Signal<TLUserPreferences>;
}
// @public
export interface TLUserPreferences {
// (undocumented)
@ -3028,31 +3350,7 @@ export function useContainer(): HTMLDivElement;
export function useEditor(): Editor;
// @public (undocumented)
export function useEditorComponents(): Partial<{
Background: ComponentType | null;
Brush: ComponentType<TLBrushProps> | null;
Canvas: ComponentType<TLCanvasComponentProps> | null;
CollaboratorBrush: ComponentType<TLBrushProps> | null;
CollaboratorCursor: ComponentType<TLCursorProps> | null;
CollaboratorHint: ComponentType<TLCollaboratorHintProps> | null;
CollaboratorScribble: ComponentType<TLScribbleProps> | null;
CollaboratorShapeIndicator: ComponentType<TLShapeIndicatorProps> | null;
Cursor: ComponentType<TLCursorProps> | null;
Grid: ComponentType<TLGridProps> | null;
Handle: ComponentType<TLHandleProps> | null;
Handles: ComponentType<TLHandlesProps> | null;
InFrontOfTheCanvas: ComponentType | null;
LoadingScreen: ComponentType | null;
OnTheCanvas: ComponentType | null;
Scribble: ComponentType<TLScribbleProps> | null;
SelectionBackground: ComponentType<TLSelectionBackgroundProps> | null;
SelectionForeground: ComponentType<TLSelectionForegroundProps> | null;
ShapeIndicator: ComponentType<TLShapeIndicatorProps> | null;
SnapIndicator: ComponentType<TLSnapIndicatorProps> | null;
Spinner: ComponentType | null;
SvgDefs: ComponentType | null;
ZoomBrush: ComponentType<TLBrushProps> | null;
} & ErrorComponents> & ErrorComponents;
export function useEditorComponents(): Required<TLEditorComponents>;
// @internal
export function useEvent<Args extends Array<unknown>, Result>(handler: (...args: Args) => Result): (...args: Args) => Result;
@ -3086,6 +3384,41 @@ export const USER_COLORS: readonly ["#FF802B", "#EC5E41", "#F2555A", "#F04F88",
export { useReactor }
// @public (undocumented)
export class UserPreferencesManager {
constructor(user: TLUser, inferDarkMode: boolean);
// (undocumented)
getAnimationSpeed(): number;
// (undocumented)
getColor(): string;
getEdgeScrollSpeed(): number;
// (undocumented)
getId(): string;
// (undocumented)
getIsDarkMode(): boolean;
// (undocumented)
getIsSnapMode(): boolean;
// (undocumented)
getIsWrapMode(): boolean;
// (undocumented)
getLocale(): string;
// (undocumented)
getName(): string;
// (undocumented)
getUserPreferences(): {
animationSpeed: number;
color: string;
id: string;
isDarkMode: boolean;
isSnapMode: boolean;
isWrapMode: boolean;
locale: string;
name: string;
};
// (undocumented)
updateUserPreferences: (userPreferences: Partial<TLUserPreferences>) => void;
}
// @internal
export function useSafeId(): string;
@ -3100,7 +3433,7 @@ export function useSelectionEvents(handle: TLSelectionHandle): {
export function useShallowArrayIdentity<T>(arr: readonly T[]): readonly T[];
// @internal (undocumented)
export function useShallowObjectIdentity<T extends Record<string, unknown>>(arr: T): T;
export function useShallowObjectIdentity<T extends object>(arr: T): T;
// @public
export function useSvgExportContext(): {

View file

@ -1,6 +1,21 @@
// Important! don't move this tlschema re-export to lib/index.ts, doing so causes esbuild to produce
// incorrect output. https://github.com/evanw/esbuild/issues/1737
import 'core-js/stable/array/at.js'
import 'core-js/stable/array/flat-map.js'
import 'core-js/stable/array/flat.js'
import 'core-js/stable/string/at.js'
import 'core-js/stable/string/replace-all.js'
// eslint-disable-next-line local/no-export-star
export * from '@tldraw/store'
// eslint-disable-next-line local/no-export-star
export * from '@tldraw/tlschema'
// eslint-disable-next-line local/no-export-star
export * from '@tldraw/utils'
// eslint-disable-next-line local/no-export-star
export * from '@tldraw/validate'
export {
EMPTY_ARRAY,
atom,
@ -17,14 +32,6 @@ export {
type Atom,
type Signal,
} from '@tldraw/state'
// eslint-disable-next-line local/no-export-star
export * from '@tldraw/store'
// eslint-disable-next-line local/no-export-star
export * from '@tldraw/tlschema'
// eslint-disable-next-line local/no-export-star
export * from '@tldraw/utils'
// eslint-disable-next-line local/no-export-star
export * from '@tldraw/validate'
export {
ErrorScreen,
LoadingScreen,
@ -42,7 +49,10 @@ export { HTMLContainer, type HTMLContainerProps } from './lib/components/HTMLCon
export { SVGContainer, type SVGContainerProps } from './lib/components/SVGContainer'
export { DefaultBackground } from './lib/components/default-components/DefaultBackground'
export { DefaultBrush, type TLBrushProps } from './lib/components/default-components/DefaultBrush'
export { DefaultCanvas } from './lib/components/default-components/DefaultCanvas'
export {
DefaultCanvas,
type TLCanvasComponentProps,
} from './lib/components/default-components/DefaultCanvas'
export {
DefaultCollaboratorHint,
type TLCollaboratorHintProps,
@ -51,7 +61,10 @@ export {
DefaultCursor,
type TLCursorProps,
} from './lib/components/default-components/DefaultCursor'
export { DefaultErrorFallback } from './lib/components/default-components/DefaultErrorFallback'
export {
DefaultErrorFallback,
type TLErrorFallbackComponent,
} from './lib/components/default-components/DefaultErrorFallback'
export { DefaultGrid, type TLGridProps } from './lib/components/default-components/DefaultGrid'
export {
DefaultHandle,
@ -73,10 +86,12 @@ export {
DefaultSelectionForeground,
type TLSelectionForegroundProps,
} from './lib/components/default-components/DefaultSelectionForeground'
export { type TLShapeErrorFallbackComponent } from './lib/components/default-components/DefaultShapeErrorFallback'
export {
DefaultShapeIndicator,
type TLShapeIndicatorProps,
} from './lib/components/default-components/DefaultShapeIndicator'
export { type TLShapeIndicatorErrorFallbackComponent } from './lib/components/default-components/DefaultShapeIndicatorErrorFallback'
export {
DefaultSnapIndicator,
type TLSnapIndicatorProps,
@ -104,7 +119,7 @@ export {
type TLStoreEventInfo,
type TLStoreOptions,
} from './lib/config/createTLStore'
export { createTLUser } from './lib/config/createTLUser'
export { createTLUser, type TLUser } from './lib/config/createTLUser'
export { type TLAnyBindingUtilConstructor } from './lib/config/defaultBindings'
export { coreShapes, type TLAnyShapeUtilConstructor } from './lib/config/defaultShapes'
export { DEFAULT_ANIMATION_OPTIONS, DEFAULT_CAMERA_OPTIONS, SIDES } from './lib/constants'
@ -119,18 +134,25 @@ export {
type BindingOnShapeIsolateOptions,
type TLBindingUtilConstructor,
} from './lib/editor/bindings/BindingUtil'
export { ClickManager, type TLClickState } from './lib/editor/managers/ClickManager'
export { EnvironmentManager } from './lib/editor/managers/EnvironmentManager'
export { HistoryManager } from './lib/editor/managers/HistoryManager'
export { ScribbleManager, type ScribbleItem } from './lib/editor/managers/ScribbleManager'
export {
BoundsSnaps,
type BoundsSnapGeometry,
type BoundsSnapPoint,
} from './lib/editor/managers/SnapManager/BoundsSnaps'
export { type HandleSnapGeometry } from './lib/editor/managers/SnapManager/HandleSnaps'
export { HandleSnaps, type HandleSnapGeometry } from './lib/editor/managers/SnapManager/HandleSnaps'
export {
SnapManager,
type GapsSnapIndicator,
type PointsSnapIndicator,
type SnapData,
type SnapIndicator,
} from './lib/editor/managers/SnapManager/SnapManager'
export { TextManager, type TLMeasureTextSpanOpts } from './lib/editor/managers/TextManager'
export { UserPreferencesManager } from './lib/editor/managers/UserPreferencesManager'
export { BaseBoxShapeUtil, type TLBaseBoxShape } from './lib/editor/shapes/BaseBoxShapeUtil'
export {
ShapeUtil,
@ -199,6 +221,7 @@ export {
type TLPointerEventName,
type TLPointerEventTarget,
type TLTickEvent,
type TLTickEventInfo,
type TLWheelEvent,
type TLWheelEventInfo,
type UiEvent,
@ -210,6 +233,13 @@ export {
type TLExternalContentSource,
} from './lib/editor/types/external-content'
export {
type TLHistoryBatchOptions,
type TLHistoryDiff,
type TLHistoryEntry,
type TLHistoryMark,
} from './lib/editor/types/history-types'
export {
type OptionalKeys,
type RequiredKeys,
type TLCameraConstraints,
type TLCameraMoveOptions,
@ -254,7 +284,7 @@ export { CubicBezier2d } from './lib/primitives/geometry/CubicBezier2d'
export { CubicSpline2d } from './lib/primitives/geometry/CubicSpline2d'
export { Edge2d } from './lib/primitives/geometry/Edge2d'
export { Ellipse2d } from './lib/primitives/geometry/Ellipse2d'
export { Geometry2d } from './lib/primitives/geometry/Geometry2d'
export { Geometry2d, type Geometry2dOptions } from './lib/primitives/geometry/Geometry2d'
export { Group2d } from './lib/primitives/geometry/Group2d'
export { Point2d } from './lib/primitives/geometry/Point2d'
export { Polygon2d } from './lib/primitives/geometry/Polygon2d'
@ -314,7 +344,13 @@ export {
type SharedStyle,
} from './lib/utils/SharedStylesMap'
export { dataUrlToFile } from './lib/utils/assets'
export { debugFlags, featureFlags, type DebugFlag } from './lib/utils/debug-flags'
export {
debugFlags,
featureFlags,
type DebugFlag,
type DebugFlagDef,
type DebugFlagDefaults,
} from './lib/utils/debug-flags'
export {
loopToHtmlElement,
preventDefault,
@ -340,11 +376,3 @@ export { hardReset } from './lib/utils/sync/hardReset'
export { uniq } from './lib/utils/uniq'
export { uniqueId } from './lib/utils/uniqueId'
export { openWindow } from './lib/utils/window-open'
/** @polyfills */
import 'core-js/stable/array/at.js'
import 'core-js/stable/array/flat-map.js'
import 'core-js/stable/array/flat.js'
import 'core-js/stable/string/at.js'
import 'core-js/stable/string/replace-all.js'

View file

@ -8,16 +8,12 @@ export interface TLErrorBoundaryProps {
fallback: TLErrorFallbackComponent
}
interface TLErrorBoundaryState {
error: Error | null
}
const initialState: TLErrorBoundaryState = { error: null }
const initialState = { error: null }
/** @public */
export class ErrorBoundary extends React.Component<
React.PropsWithRef<React.PropsWithChildren<TLErrorBoundaryProps>>,
TLErrorBoundaryState
{ error: Error | null }
> {
static getDerivedStateFromError(error: Error) {
return { error }

View file

@ -1,4 +1,5 @@
import { useValue } from '@tldraw/state'
import { noop } from '@tldraw/utils'
import classNames from 'classnames'
import { ComponentType, useEffect, useLayoutEffect, useRef, useState } from 'react'
import { Editor } from '../../editor/Editor'
@ -10,9 +11,6 @@ import { ErrorBoundary } from '../ErrorBoundary'
const BASE_ERROR_URL = 'https://github.com/tldraw/tldraw/issues/new'
// eslint-disable-next-line @typescript-eslint/no-empty-function
function noop() {}
/** @public */
export type TLErrorFallbackComponent = ComponentType<{ error: unknown; editor?: Editor }>

View file

@ -707,7 +707,7 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
readonly root: RootState
readonly root: StateNode
/**
* A set of functions to call when the app is disposed.

View file

@ -3,7 +3,8 @@ import { uniqueId } from '../../utils/uniqueId'
import type { Editor } from '../Editor'
import { TLClickEventInfo, TLPointerEventInfo } from '../types/event-types'
type TLClickState =
/** @public */
export type TLClickState =
| 'idle'
| 'pendingDouble'
| 'pendingTriple'
@ -13,6 +14,7 @@ type TLClickState =
const MAX_CLICK_DISTANCE = 40
/** @public */
export class ClickManager {
constructor(public editor: Editor) {}

View file

@ -1,5 +1,6 @@
import { Editor } from '../Editor'
/** @public */
export class EnvironmentManager {
constructor(public editor: Editor) {
if (typeof window !== 'undefined' && 'navigator' in window) {

View file

@ -1,7 +1,6 @@
import { BaseRecord, RecordId, Store, StoreSchema, createRecordType } from '@tldraw/store'
import { TLHistoryBatchOptions } from '../types/history-types'
import { HistoryManager } from './HistoryManager'
import { stack } from './Stack'
interface TestRecord extends BaseRecord<'test', TestRecordId> {
value: number | string
@ -99,9 +98,9 @@ describe(HistoryManager, () => {
editor.decrement()
expect(editor.getCount()).toBe(3)
const undos = [...editor.history.stacks.get().undos]
const undos = editor.history.debug().undos
const parsedUndos = JSON.parse(JSON.stringify(undos))
editor.history.stacks.update(({ redos }) => ({ undos: stack(parsedUndos), redos }))
expect(parsedUndos).toEqual(undos)
editor.history.undo()

View file

@ -27,8 +27,7 @@ export class HistoryManager<R extends UnknownRecord> {
private state: HistoryRecorderState = HistoryRecorderState.Recording
private readonly pendingDiff = new PendingDiff<R>()
/** @internal */
stacks = atom(
private stacks = atom(
'HistoryManager.stacks',
{
undos: stack<TLHistoryEntry<R>>(),
@ -274,7 +273,7 @@ export class HistoryManager<R extends UnknownRecord> {
undos: undos.toArray(),
redos: redos.toArray(),
pendingDiff: this.pendingDiff.debug(),
state: this.state,
state: this.state as string,
}
}
}

View file

@ -3,7 +3,8 @@ import { Vec } from '../../primitives/Vec'
import { uniqueId } from '../../utils/uniqueId'
import { Editor } from '../Editor'
interface ScribbleItem {
/** @public */
export interface ScribbleItem {
id: string
scribble: TLScribble
timeoutMs: number

View file

@ -196,6 +196,7 @@ function dedupeGapSnaps(snaps: Array<Extract<SnapIndicator, { type: 'gaps' }>>)
}
}
/** @public */
export class BoundsSnaps {
readonly editor: Editor
constructor(readonly manager: SnapManager) {

View file

@ -47,6 +47,7 @@ export interface HandleSnapGeometry {
const defaultGetSelfSnapOutline = () => null
const defaultGetSelfSnapPoints = () => []
/** @public */
export class HandleSnaps {
readonly editor: Editor
constructor(readonly manager: SnapManager) {

View file

@ -20,9 +20,9 @@ const textAlignmentsForLtr = {
'end-legacy': 'right',
}
type TLOverflowMode = 'wrap' | 'truncate-ellipsis' | 'truncate-clip'
interface TLMeasureTextSpanOpts {
overflow: TLOverflowMode
/** @public */
export interface TLMeasureTextSpanOpts {
overflow: 'wrap' | 'truncate-ellipsis' | 'truncate-clip'
width: number
height: number
padding: number
@ -36,6 +36,7 @@ interface TLMeasureTextSpanOpts {
const spaceCharacterRegex = /\s/
/** @public */
export class TextManager {
baseElm: HTMLDivElement

View file

@ -6,6 +6,7 @@ import {
} from '../../config/TLUserPreferences'
import { TLUser } from '../../config/createTLUser'
/** @public */
export class UserPreferencesManager {
constructor(
private readonly user: TLUser,

View file

@ -542,17 +542,29 @@ export type TLOnBeforeCreateHandler<T extends TLShape> = (next: T) => T | void
/** @public */
export type TLOnBeforeUpdateHandler<T extends TLShape> = (prev: T, next: T) => T | void
/** @public */
export type TLOnTranslateStartHandler<T extends TLShape> = TLEventStartHandler<T>
export type TLOnTranslateStartHandler<T extends TLShape> = (shape: T) => TLShapePartial<T> | void
/** @public */
export type TLOnTranslateHandler<T extends TLShape> = TLEventChangeHandler<T>
export type TLOnTranslateHandler<T extends TLShape> = (
initial: T,
current: T
) => TLShapePartial<T> | void
/** @public */
export type TLOnTranslateEndHandler<T extends TLShape> = TLEventChangeHandler<T>
export type TLOnTranslateEndHandler<T extends TLShape> = (
initial: T,
current: T
) => TLShapePartial<T> | void
/** @public */
export type TLOnRotateStartHandler<T extends TLShape> = TLEventStartHandler<T>
export type TLOnRotateStartHandler<T extends TLShape> = (shape: T) => TLShapePartial<T> | void
/** @public */
export type TLOnRotateHandler<T extends TLShape> = TLEventChangeHandler<T>
export type TLOnRotateHandler<T extends TLShape> = (
initial: T,
current: T
) => TLShapePartial<T> | void
/** @public */
export type TLOnRotateEndHandler<T extends TLShape> = TLEventChangeHandler<T>
export type TLOnRotateEndHandler<T extends TLShape> = (
initial: T,
current: T
) => TLShapePartial<T> | void
/**
* The type of resize.
@ -595,10 +607,13 @@ export type TLOnResizeHandler<T extends TLShape> = (
) => Omit<TLShapePartial<T>, 'id' | 'type'> | undefined | void
/** @public */
export type TLOnResizeStartHandler<T extends TLShape> = TLEventStartHandler<T>
export type TLOnResizeStartHandler<T extends TLShape> = (shape: T) => TLShapePartial<T> | void
/** @public */
export type TLOnResizeEndHandler<T extends TLShape> = TLEventChangeHandler<T>
export type TLOnResizeEndHandler<T extends TLShape> = (
initial: T,
current: T
) => TLShapePartial<T> | void
/* -------------------- Dragging -------------------- */
@ -632,6 +647,3 @@ export type TLOnDoubleClickHandleHandler<T extends TLShape> = (
shape: T,
handle: TLHandle
) => TLShapePartial<T> | void
type TLEventStartHandler<T extends TLShape> = (shape: T) => TLShapePartial<T> | void
type TLEventChangeHandler<T extends TLShape> = (initial: T, current: T) => TLShapePartial<T> | void

View file

@ -1,5 +1,5 @@
import { TLShape } from '@tldraw/tlschema'
import { StateNode } from '../StateNode'
import { StateNode, TLStateNodeConstructor } from '../StateNode'
import { Idle } from './children/Idle'
import { Pointing } from './children/Pointing'
@ -7,7 +7,7 @@ import { Pointing } from './children/Pointing'
export abstract class BaseBoxShapeTool extends StateNode {
static override id = 'box'
static override initial = 'idle'
static override children = () => [Idle, Pointing]
static override children = (): TLStateNodeConstructor[] => [Idle, Pointing]
abstract override shapeType: string

View file

@ -11,7 +11,6 @@ import {
TLPinchEventInfo,
} from '../types/event-types'
type TLStateNodeType = 'branch' | 'leaf' | 'root'
const STATE_NODES_TO_MEASURE = [
'brushing',
'cropping',
@ -84,7 +83,7 @@ export abstract class StateNode implements Partial<TLEventHandlers> {
static children?: () => TLStateNodeConstructor[]
id: string
type: TLStateNodeType
type: 'branch' | 'leaf' | 'root'
shapeType?: string
initial?: string
children?: Record<string, StateNode>

View file

@ -17,6 +17,7 @@ import {
import { DefaultGrid, TLGridProps } from '../components/default-components/DefaultGrid'
import { DefaultHandle, TLHandleProps } from '../components/default-components/DefaultHandle'
import { DefaultHandles, TLHandlesProps } from '../components/default-components/DefaultHandles'
import { DefaultLoadingScreen } from '../components/default-components/DefaultLoadingScreen'
import { DefaultScribble, TLScribbleProps } from '../components/default-components/DefaultScribble'
import {
DefaultSelectionBackground,
@ -46,47 +47,39 @@ import { DefaultSpinner } from '../components/default-components/DefaultSpinner'
import { DefaultSvgDefs } from '../components/default-components/DefaultSvgDefs'
import { useShallowObjectIdentity } from './useIdentity'
export interface BaseEditorComponents {
Background: ComponentType
SvgDefs: ComponentType
Brush: ComponentType<TLBrushProps>
ZoomBrush: ComponentType<TLBrushProps>
ShapeIndicator: ComponentType<TLShapeIndicatorProps>
Cursor: ComponentType<TLCursorProps>
Canvas: ComponentType<TLCanvasComponentProps>
CollaboratorBrush: ComponentType<TLBrushProps>
CollaboratorCursor: ComponentType<TLCursorProps>
CollaboratorHint: ComponentType<TLCollaboratorHintProps>
CollaboratorShapeIndicator: ComponentType<TLShapeIndicatorProps>
Grid: ComponentType<TLGridProps>
Scribble: ComponentType<TLScribbleProps>
CollaboratorScribble: ComponentType<TLScribbleProps>
SnapIndicator: ComponentType<TLSnapIndicatorProps>
Handles: ComponentType<TLHandlesProps>
Handle: ComponentType<TLHandleProps>
Spinner: ComponentType
SelectionForeground: ComponentType<TLSelectionForegroundProps>
SelectionBackground: ComponentType<TLSelectionBackgroundProps>
OnTheCanvas: ComponentType
InFrontOfTheCanvas: ComponentType
LoadingScreen: ComponentType
}
// These will always have defaults
interface ErrorComponents {
ErrorFallback: TLErrorFallbackComponent
ShapeErrorFallback: TLShapeErrorFallbackComponent
ShapeIndicatorErrorFallback: TLShapeIndicatorErrorFallbackComponent
}
/** @public */
export type TLEditorComponents = Partial<
{
[K in keyof BaseEditorComponents]: BaseEditorComponents[K] | null
} & ErrorComponents
>
export interface TLEditorComponents {
Background?: ComponentType | null
SvgDefs?: ComponentType | null
Brush?: ComponentType<TLBrushProps> | null
ZoomBrush?: ComponentType<TLBrushProps> | null
ShapeIndicator?: ComponentType<TLShapeIndicatorProps> | null
Cursor?: ComponentType<TLCursorProps> | null
Canvas?: ComponentType<TLCanvasComponentProps> | null
CollaboratorBrush?: ComponentType<TLBrushProps> | null
CollaboratorCursor?: ComponentType<TLCursorProps> | null
CollaboratorHint?: ComponentType<TLCollaboratorHintProps> | null
CollaboratorShapeIndicator?: ComponentType<TLShapeIndicatorProps> | null
Grid?: ComponentType<TLGridProps> | null
Scribble?: ComponentType<TLScribbleProps> | null
CollaboratorScribble?: ComponentType<TLScribbleProps> | null
SnapIndicator?: ComponentType<TLSnapIndicatorProps> | null
Handles?: ComponentType<TLHandlesProps> | null
Handle?: ComponentType<TLHandleProps> | null
Spinner?: ComponentType | null
SelectionForeground?: ComponentType<TLSelectionForegroundProps> | null
SelectionBackground?: ComponentType<TLSelectionBackgroundProps> | null
OnTheCanvas?: ComponentType | null
InFrontOfTheCanvas?: ComponentType | null
LoadingScreen?: ComponentType | null
const EditorComponentsContext = createContext<null | (TLEditorComponents & ErrorComponents)>(null)
// These will always have defaults
ErrorFallback?: TLErrorFallbackComponent
ShapeErrorFallback?: TLShapeErrorFallbackComponent
ShapeIndicatorErrorFallback?: TLShapeIndicatorErrorFallbackComponent
}
const EditorComponentsContext = createContext<null | Required<TLEditorComponents>>(null)
interface ComponentsContextProviderProps {
overrides?: TLEditorComponents
@ -101,12 +94,11 @@ export function EditorComponentsProvider({
return (
<EditorComponentsContext.Provider
value={useMemo(
() => ({
(): Required<TLEditorComponents> => ({
Background: DefaultBackground,
SvgDefs: DefaultSvgDefs,
Brush: DefaultBrush,
ZoomBrush: DefaultBrush,
ScreenshotBrush: DefaultBrush,
CollaboratorBrush: DefaultBrush,
Cursor: DefaultCursor,
CollaboratorCursor: DefaultCursor,
@ -128,6 +120,7 @@ export function EditorComponentsProvider({
OnTheCanvas: null,
InFrontOfTheCanvas: null,
Canvas: DefaultCanvas,
LoadingScreen: DefaultLoadingScreen,
..._overrides,
}),
[_overrides]

View file

@ -16,6 +16,6 @@ export function useShallowArrayIdentity<T>(arr: readonly T[]): readonly T[] {
}
/** @internal */
export function useShallowObjectIdentity<T extends Record<string, unknown>>(arr: T): T {
export function useShallowObjectIdentity<T extends object>(arr: T): T {
return useIdentity(arr, areObjectsShallowEqual)
}

View file

@ -2,6 +2,7 @@ import { Box } from '../Box'
import { Vec } from '../Vec'
import { pointInPolygon } from '../utils'
/** @public */
export interface Geometry2dOptions {
isFilled: boolean
isClosed: boolean

View file

@ -97,7 +97,7 @@ function createDebugValue<T>(
{
defaults,
shouldStoreForSession = true,
}: { defaults: Defaults<T>; shouldStoreForSession?: boolean }
}: { defaults: DebugFlagDefaults<T>; shouldStoreForSession?: boolean }
) {
return createDebugValueBase({
name,
@ -188,16 +188,18 @@ function getDefaultValue<T>(def: DebugFlagDef<T>): T {
}
}
interface Defaults<T> {
/** @internal */
export interface DebugFlagDefaults<T> {
development?: T
staging?: T
production?: T
all: T
}
interface DebugFlagDef<T> {
/** @internal */
export interface DebugFlagDef<T> {
name: string
defaults: Defaults<T>
defaults: DebugFlagDefaults<T>
shouldStoreForSession: boolean
}

View file

@ -7,6 +7,20 @@
import { FunctionComponent } from 'react';
import { default as React_2 } from 'react';
// @internal
export class ArraySet<T> {
add(elem: T): boolean;
// (undocumented)
clear(): void;
// (undocumented)
has(elem: T): boolean;
get isEmpty(): boolean;
remove(elem: T): boolean;
// (undocumented)
size(): number;
visit(visitor: (item: T) => void): void;
}
// @public
export interface Atom<Value, Diff = unknown> extends Signal<Value, Diff> {
set(value: Value, diff?: Diff): Value;
@ -26,6 +40,20 @@ export interface AtomOptions<Value, Diff> {
isEqual?: (a: any, b: any) => boolean;
}
// @internal (undocumented)
export interface Child {
// (undocumented)
isActivelyListening: boolean;
// (undocumented)
lastTraversedEpoch: number;
// (undocumented)
readonly parentEpochs: number[];
// (undocumented)
readonly parents: Signal<any, any>[];
// (undocumented)
readonly parentSet: ArraySet<Signal<any, any>>;
}
// @public
export interface Computed<Value, Diff = unknown> extends Signal<Value, Diff> {
readonly isActivelyListening: boolean;
@ -46,6 +74,9 @@ export function computed(target: any, key: string, descriptor: PropertyDescripto
// @public (undocumented)
export function computed<Value, Diff = unknown>(options?: ComputedOptions<Value, Diff>): (target: any, key: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
// @public
export type ComputeDiff<Value, Diff> = (previousValue: Value, currentValue: Value, lastComputedEpoch: number, currentEpoch: number) => Diff | RESET_VALUE;
// @public
export interface ComputedOptions<Value, Diff> {
computeDiff?: ComputeDiff<Value, Diff>;
@ -54,10 +85,35 @@ export interface ComputedOptions<Value, Diff> {
}
// @public
export const EffectScheduler: typeof __EffectScheduler__;
export const EffectScheduler: new <Result>(name: string, runEffect: (lastReactedEpoch: number) => Result, options?: EffectSchedulerOptions) => EffectScheduler<Result>;
// @public (undocumented)
export type EffectScheduler<Result> = __EffectScheduler__<Result>;
export interface EffectScheduler<Result> {
attach(): void;
detach(): void;
execute(): Result;
readonly isActivelyListening: boolean;
// @internal (undocumented)
readonly lastTraversedEpoch: number;
// @internal (undocumented)
maybeExecute(): void;
// @internal (undocumented)
maybeScheduleEffect(): void;
// @internal (undocumented)
readonly parentEpochs: number[];
// @internal (undocumented)
readonly parents: Signal<any, any>[];
// @internal (undocumented)
readonly parentSet: ArraySet<Signal<any, any>>;
readonly scheduleCount: number;
// @internal (undocumented)
scheduleEffect(): void;
}
// @public (undocumented)
export interface EffectSchedulerOptions {
scheduleEffect?: (execute: () => void) => void;
}
// @public (undocumented)
export const EMPTY_ARRAY: [];
@ -115,6 +171,12 @@ export function transact<T>(fn: () => T): T;
// @public
export function transaction<T>(fn: (rollback: () => void) => T): T;
// @public (undocumented)
export const UNINITIALIZED: unique symbol;
// @public
export type UNINITIALIZED = typeof UNINITIALIZED;
// @public
export function unsafe__withoutCapture<T>(fn: () => T): T;
@ -148,6 +210,22 @@ export function useValue<Value>(name: string, fn: () => Value, deps: unknown[]):
// @public
export function whyAmIRunning(): void;
// @public (undocumented)
export const WithDiff: {
new <Value, Diff>(value: Value, diff: Diff): {
diff: Diff;
value: Value;
};
};
// @public (undocumented)
export interface WithDiff<Value, Diff> {
// (undocumented)
diff: Diff;
// (undocumented)
value: Value;
}
// @public
export function withDiff<Value, Diff>(value: Value, diff: Diff): WithDiff<Value, Diff>;

View file

@ -43,6 +43,7 @@ export const isUninitialized = (value: any): value is UNINITIALIZED => {
return value === UNINITIALIZED
}
/** @public */
export const WithDiff = singleton(
'WithDiff',
() =>
@ -53,6 +54,8 @@ export const WithDiff = singleton(
) {}
}
)
/** @public */
export interface WithDiff<Value, Diff> {
value: Value
diff: Diff

View file

@ -5,7 +5,8 @@ import { attach, detach, haveParentsChanged, singleton } from './helpers'
import { getGlobalEpoch } from './transactions'
import { Signal } from './types'
interface EffectSchedulerOptions {
/** @public */
export interface EffectSchedulerOptions {
/**
* scheduleEffect is a function that will be called when the effect is scheduled.
*
@ -38,7 +39,7 @@ interface EffectSchedulerOptions {
scheduleEffect?: (execute: () => void) => void
}
class __EffectScheduler__<Result> {
class __EffectScheduler__<Result> implements EffectScheduler<Result> {
private _isActivelyListening = false
/**
* Whether this scheduler is attached and actively listening to its parents.
@ -174,9 +175,71 @@ class __EffectScheduler__<Result> {
*
* @public
*/
export const EffectScheduler = singleton('EffectScheduler', () => __EffectScheduler__)
export const EffectScheduler = singleton(
'EffectScheduler',
(): {
new <Result>(
name: string,
runEffect: (lastReactedEpoch: number) => Result,
options?: EffectSchedulerOptions
): EffectScheduler<Result>
} => __EffectScheduler__
)
/** @public */
export type EffectScheduler<Result> = __EffectScheduler__<Result>
export interface EffectScheduler<Result> {
/**
* Whether this scheduler is attached and actively listening to its parents.
* @public
*/
readonly isActivelyListening: boolean
/** @internal */
readonly lastTraversedEpoch: number
/**
* The number of times this effect has been scheduled.
* @public
*/
readonly scheduleCount: number
/** @internal */
readonly parentSet: ArraySet<Signal<any, any>>
/** @internal */
readonly parentEpochs: number[]
/** @internal */
readonly parents: Signal<any, any>[]
/** @internal */
maybeScheduleEffect(): void
/** @internal */
scheduleEffect(): void
/** @internal */
maybeExecute(): void
/**
* Makes this scheduler become 'actively listening' to its parents.
* If it has been executed before it will immediately become eligible to receive 'maybeScheduleEffect' calls.
* If it has not executed before it will need to be manually executed once to become eligible for scheduling, i.e. by calling [[EffectScheduler.execute]].
* @public
*/
attach(): void
/**
* Makes this scheduler stop 'actively listening' to its parents.
* It will no longer be eligible to receive 'maybeScheduleEffect' calls until [[EffectScheduler.attach]] is called again.
*/
detach(): void
/**
* Executes the effect immediately and returns the result.
* @returns The result of the effect.
*/
execute(): Result
}
/**
* Starts a new effect scheduler, scheduling the effect immediately.

View file

@ -1,17 +1,18 @@
import { singleton } from './helpers'
export { ArraySet } from './ArraySet'
export { atom, isAtom } from './Atom'
export type { Atom, AtomOptions } from './Atom'
export { computed, getComputedInstance, isUninitialized, withDiff } from './Computed'
export type { Computed, ComputedOptions } from './Computed'
export { UNINITIALIZED, computed, getComputedInstance, isUninitialized, withDiff } from './Computed'
export type { Computed, ComputedOptions, WithDiff } from './Computed'
export { EffectScheduler, react, reactor } from './EffectScheduler'
export type { Reactor } from './EffectScheduler'
export type { EffectSchedulerOptions, Reactor } from './EffectScheduler'
export { unsafe__withoutCapture, whyAmIRunning } from './capture'
export { EMPTY_ARRAY } from './helpers'
export { isSignal } from './isSignal'
export { transact, transaction } from './transactions'
export { RESET_VALUE } from './types'
export type { Signal } from './types'
export type { Child, ComputeDiff, Signal } from './types'
// This should be incremented any time an API change is made. i.e. for additions or removals.
// Bugfixes need not increment this.

View file

@ -333,14 +333,6 @@ type AuthorRecord extends BaseRecord<"author"> {
}
```
### `AllRecords`
A helper to get the type of all records in a record store.
```ts
type AllAuthorRecords = AllRecords<RecordStore<Author>>
```
### `RecordsDiff`
A diff describing the changes to a record.

View file

@ -8,9 +8,6 @@ import { Atom } from '@tldraw/state';
import { Computed } from '@tldraw/state';
import { Result } from '@tldraw/utils';
// @public
export type AllRecords<T extends Store<any>> = ExtractR<ExtractRecordType<T>>;
// @public
export function assertIdType<R extends UnknownRecord>(id: string | undefined, type: RecordType<R, any>): asserts id is IdOf<R>;
@ -22,6 +19,9 @@ export interface BaseRecord<TypeName extends string, Id extends RecordId<Unknown
readonly typeName: TypeName;
}
// @public (undocumented)
export type ChangeSource = 'remote' | 'user';
// @public
export interface CollectionDiff<T> {
// (undocumented)
@ -37,7 +37,7 @@ export interface ComputedCache<Data, R extends UnknownRecord> {
}
// @public
export function createComputedCache<Context extends StoreContext<any>, Result, Record extends ContextRecordType<Context> = ContextRecordType<Context>>(name: string, derive: (context: Context, record: Record) => Result | undefined, isEqual?: (a: Record, b: Record) => boolean): {
export function createComputedCache<Context extends StoreObject<any>, Result, Record extends StoreObjectRecordType<Context> = StoreObjectRecordType<Context>>(name: string, derive: (context: Context, record: Record) => Result | undefined, isEqual?: (a: Record, b: Record) => boolean): {
get(context: Context, id: IdOf<Record>): Result | undefined;
};
@ -117,6 +117,18 @@ export class IncrementalSetConstructor<T> {
// @internal
export function isRecordsDiffEmpty<T extends UnknownRecord>(diff: RecordsDiff<T>): boolean;
// @public (undocumented)
export interface LegacyBaseMigrationsInfo {
// (undocumented)
currentVersion: number;
// (undocumented)
firstVersion: number;
// (undocumented)
migrators: {
[version: number]: LegacyMigration;
};
}
// @public (undocumented)
export interface LegacyMigration<Before = any, After = any> {
// (undocumented)
@ -191,11 +203,31 @@ export function parseMigrationId(id: MigrationId): {
version: number;
};
// @public (undocumented)
export type QueryExpression<R extends object> = {
[k in keyof R & string]?: QueryValueMatcher<R[k]>;
};
// @public (undocumented)
export type QueryValueMatcher<T> = {
eq: T;
} | {
gt: number;
} | {
neq: T;
};
// @public (undocumented)
export type RecordFromId<K extends RecordId<UnknownRecord>> = K extends RecordId<infer R> ? R : never;
// @public (undocumented)
export type RecordId<R extends UnknownRecord> = string & {
__type__: R;
};
// @public
export type RecordScope = 'document' | 'presence' | 'session';
// @public
export interface RecordsDiff<R extends UnknownRecord> {
// (undocumented)
@ -210,7 +242,7 @@ export interface RecordsDiff<R extends UnknownRecord> {
export class RecordType<R extends UnknownRecord, RequiredProperties extends keyof Omit<R, 'id' | 'typeName'>> {
constructor(
typeName: R['typeName'], config: {
readonly createDefaultProperties: () => Exclude<OmitMeta<R>, RequiredProperties>;
readonly createDefaultProperties: () => Exclude<Omit<R, 'id' | 'typeName'>, RequiredProperties>;
readonly ephemeralKeys?: {
readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean;
};
@ -222,7 +254,7 @@ export class RecordType<R extends UnknownRecord, RequiredProperties extends keyo
// @deprecated
createCustomId(id: string): IdOf<R>;
// (undocumented)
readonly createDefaultProperties: () => Exclude<OmitMeta<R>, RequiredProperties>;
readonly createDefaultProperties: () => Exclude<Omit<R, 'id' | 'typeName'>, RequiredProperties>;
createId(customUniquePart?: string): IdOf<R>;
// (undocumented)
readonly ephemeralKeys?: {
@ -245,6 +277,15 @@ export class RecordType<R extends UnknownRecord, RequiredProperties extends keyo
// @public (undocumented)
export function reverseRecordsDiff(diff: RecordsDiff<any>): RecordsDiff<any>;
// @public (undocumented)
export type RSIndex<R extends UnknownRecord, Property extends string & keyof R = string & keyof R> = Computed<RSIndexMap<R, Property>, RSIndexDiff<R, Property>>;
// @public (undocumented)
export type RSIndexDiff<R extends UnknownRecord, Property extends string & keyof R = string & keyof R> = Map<R[Property], CollectionDiff<IdOf<R>>>;
// @public (undocumented)
export type RSIndexMap<R extends UnknownRecord, Property extends string & keyof R = string & keyof R> = Map<R[Property], Set<IdOf<R>>>;
// @public (undocumented)
export type SerializedSchema = SerializedSchemaV1 | SerializedSchemaV2;
@ -317,7 +358,7 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
} | null;
// (undocumented)
_flushHistory(): void;
get: <K extends IdOf<R>>(id: K) => RecFromId<K> | undefined;
get: <K extends IdOf<R>>(id: K) => RecordFromId<K> | undefined;
// @deprecated (undocumented)
getSnapshot(scope?: 'all' | RecordScope): StoreSnapshot<R>;
getStoreSnapshot(scope?: 'all' | RecordScope): StoreSnapshot<R>;
@ -348,8 +389,8 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
serialize: (scope?: 'all' | RecordScope) => SerializedStore<R>;
// (undocumented)
readonly sideEffects: StoreSideEffects<R>;
unsafeGetWithoutCapture: <K extends IdOf<R>>(id: K) => RecFromId<K> | undefined;
update: <K extends IdOf<R>>(id: K, updater: (record: RecFromId<K>) => RecFromId<K>) => void;
unsafeGetWithoutCapture: <K extends IdOf<R>>(id: K) => RecordFromId<K> | undefined;
update: <K extends IdOf<R>>(id: K, updater: (record: RecordFromId<K>) => RecordFromId<K>) => void;
// (undocumented)
validate(phase: 'createRecord' | 'initialize' | 'tests' | 'updateRecord'): void;
}
@ -389,9 +430,69 @@ export interface StoreError {
// @public
export type StoreListener<R extends UnknownRecord> = (entry: HistoryEntry<R>) => void;
// @public (undocumented)
export interface StoreListenerFilters {
// (undocumented)
scope: 'all' | RecordScope;
// (undocumented)
source: 'all' | ChangeSource;
}
// @public (undocumented)
export type StoreObject<R extends UnknownRecord> = {
store: Store<R>;
} | Store<R>;
// @public (undocumented)
export type StoreObjectRecordType<Context extends StoreObject<any>> = Context extends Store<infer R> ? R : Context extends {
store: Store<infer R>;
} ? R : never;
// @public (undocumented)
export type StoreOperationCompleteHandler = (source: 'remote' | 'user') => void;
// @public
export class StoreQueries<R extends UnknownRecord> {
constructor(atoms: Atom<Record<IdOf<R>, Atom<R>>>, history: Atom<number, RecordsDiff<R>>);
// @internal
__uncached_createIndex<TypeName extends R['typeName'], Property extends string & keyof Extract<R, {
typeName: TypeName;
}>>(typeName: TypeName, property: Property): RSIndex<Extract<R, {
typeName: TypeName;
}>, Property>;
// (undocumented)
exec<TypeName extends R['typeName']>(typeName: TypeName, query: QueryExpression<Extract<R, {
typeName: TypeName;
}>>): Array<Extract<R, {
typeName: TypeName;
}>>;
filterHistory<TypeName extends R['typeName']>(typeName: TypeName): Computed<number, RecordsDiff<Extract<R, {
typeName: TypeName;
}>>>;
ids<TypeName extends R['typeName']>(typeName: TypeName, queryCreator?: () => QueryExpression<Extract<R, {
typeName: TypeName;
}>>, name?: string): Computed<Set<IdOf<Extract<R, {
typeName: TypeName;
}>>>, CollectionDiff<IdOf<Extract<R, {
typeName: TypeName;
}>>>>;
index<TypeName extends R['typeName'], Property extends string & keyof Extract<R, {
typeName: TypeName;
}>>(typeName: TypeName, property: Property): RSIndex<Extract<R, {
typeName: TypeName;
}>, Property>;
record<TypeName extends R['typeName']>(typeName: TypeName, queryCreator?: () => QueryExpression<Extract<R, {
typeName: TypeName;
}>>, name?: string): Computed<Extract<R, {
typeName: TypeName;
}> | undefined>;
records<TypeName extends R['typeName']>(typeName: TypeName, queryCreator?: () => QueryExpression<Extract<R, {
typeName: TypeName;
}>>, name?: string): Computed<Array<Extract<R, {
typeName: TypeName;
}>>>;
}
// @public (undocumented)
export class StoreSchema<R extends UnknownRecord, P = unknown> {
// (undocumented)

View file

@ -1,6 +1,6 @@
export type { BaseRecord, IdOf, RecordId, UnknownRecord } from './lib/BaseRecord'
export { IncrementalSetConstructor } from './lib/IncrementalSetConstructor'
export { RecordType, assertIdType, createRecordType } from './lib/RecordType'
export { RecordType, assertIdType, createRecordType, type RecordScope } from './lib/RecordType'
export {
createEmptyRecordsDiff,
isRecordsDiffEmpty,
@ -9,7 +9,15 @@ export {
squashRecordDiffsMutable,
type RecordsDiff,
} from './lib/RecordsDiff'
export { Store, createComputedCache } from './lib/Store'
export {
Store,
createComputedCache,
type ChangeSource,
type RecordFromId,
type StoreListenerFilters,
type StoreObject,
type StoreObjectRecordType,
} from './lib/Store'
export type {
CollectionDiff,
ComputedCache,
@ -21,6 +29,7 @@ export type {
StoreValidator,
StoreValidators,
} from './lib/Store'
export { StoreQueries, type RSIndex, type RSIndexDiff, type RSIndexMap } from './lib/StoreQueries'
export { StoreSchema } from './lib/StoreSchema'
export type {
SerializedSchema,
@ -39,6 +48,7 @@ export {
type StoreOperationCompleteHandler,
} from './lib/StoreSideEffects'
export { devFreeze } from './lib/devFreeze'
export { type QueryExpression, type QueryValueMatcher } from './lib/executeQuery'
export {
MigrationFailureReason,
createMigrationIds,
@ -47,6 +57,7 @@ export {
// eslint-disable-next-line deprecation/deprecation
defineMigrations,
parseMigrationId,
type LegacyBaseMigrationsInfo,
type LegacyMigration,
type LegacyMigrations,
type Migration,
@ -55,4 +66,3 @@ export {
type MigrationSequence,
type StandaloneDependsOn,
} from './lib/migrate'
export type { AllRecords } from './lib/type-utils'

View file

@ -17,8 +17,6 @@ export interface BaseRecord<TypeName extends string, Id extends RecordId<Unknown
/** @public */
export type UnknownRecord = BaseRecord<string, RecordId<UnknownRecord>>
export type OmitMeta<R extends UnknownRecord> = R extends R ? Omit<R, 'id' | 'typeName'> : R
export function isRecord(record: unknown): record is UnknownRecord {
return typeof record === 'object' && record !== null && 'id' in record && 'typeName' in record
}

View file

@ -1,6 +1,6 @@
import { objectMapEntries, structuredClone } from '@tldraw/utils'
import { nanoid } from 'nanoid'
import { IdOf, OmitMeta, UnknownRecord } from './BaseRecord'
import { IdOf, UnknownRecord } from './BaseRecord'
import { StoreValidator } from './Store'
export type RecordTypeRecord<R extends RecordType<any, any>> = ReturnType<R['create']>
@ -26,7 +26,7 @@ export class RecordType<
R extends UnknownRecord,
RequiredProperties extends keyof Omit<R, 'id' | 'typeName'>,
> {
readonly createDefaultProperties: () => Exclude<OmitMeta<R>, RequiredProperties>
readonly createDefaultProperties: () => Exclude<Omit<R, 'id' | 'typeName'>, RequiredProperties>
readonly validator: StoreValidator<R>
readonly ephemeralKeys?: { readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean }
readonly ephemeralKeySet: ReadonlySet<string>
@ -41,7 +41,10 @@ export class RecordType<
*/
public readonly typeName: R['typeName'],
config: {
readonly createDefaultProperties: () => Exclude<OmitMeta<R>, RequiredProperties>
readonly createDefaultProperties: () => Exclude<
Omit<R, 'id' | 'typeName'>,
RequiredProperties
>
readonly validator?: StoreValidator<R>
readonly scope?: RecordScope
readonly ephemeralKeys?: { readonly [K in Exclude<keyof R, 'id' | 'typeName'>]: boolean }

View file

@ -19,7 +19,9 @@ import { SerializedSchema, StoreSchema } from './StoreSchema'
import { StoreSideEffects } from './StoreSideEffects'
import { devFreeze } from './devFreeze'
type RecFromId<K extends RecordId<UnknownRecord>> = K extends RecordId<infer R> ? R : never
/** @public */
export type RecordFromId<K extends RecordId<UnknownRecord>> =
K extends RecordId<infer R> ? R : never
/**
* A diff describing the changes to a collection.
@ -31,8 +33,10 @@ export interface CollectionDiff<T> {
removed?: Set<T>
}
/** @public */
export type ChangeSource = 'user' | 'remote'
/** @public */
export interface StoreListenerFilters {
source: ChangeSource | 'all'
scope: RecordScope | 'all'
@ -450,7 +454,7 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
* @param id - The id of the record to get.
* @public
*/
get = <K extends IdOf<R>>(id: K): RecFromId<K> | undefined => {
get = <K extends IdOf<R>>(id: K): RecordFromId<K> | undefined => {
return this.atoms.get()[id]?.get() as any
}
@ -460,7 +464,7 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
* @param id - The id of the record to get.
* @public
*/
unsafeGetWithoutCapture = <K extends IdOf<R>>(id: K): RecFromId<K> | undefined => {
unsafeGetWithoutCapture = <K extends IdOf<R>>(id: K): RecordFromId<K> | undefined => {
return this.atoms.get()[id]?.__unsafe__getWithoutCapture() as any
}
@ -602,14 +606,14 @@ export class Store<R extends UnknownRecord = UnknownRecord, Props = unknown> {
* @param id - The id of the record to update.
* @param updater - A function that updates the record.
*/
update = <K extends IdOf<R>>(id: K, updater: (record: RecFromId<K>) => RecFromId<K>) => {
update = <K extends IdOf<R>>(id: K, updater: (record: RecordFromId<K>) => RecordFromId<K>) => {
const atom = this.atoms.get()[id]
if (!atom) {
console.error(`Record ${id} not found. This is probably an error`)
return
}
this.put([updater(atom.__unsafe__getWithoutCapture() as any as RecFromId<K>) as any])
this.put([updater(atom.__unsafe__getWithoutCapture() as any as RecordFromId<K>) as any])
}
/**
@ -973,8 +977,10 @@ class HistoryAccumulator<T extends UnknownRecord> {
}
}
type StoreContext<R extends UnknownRecord> = Store<R> | { store: Store<R> }
type ContextRecordType<Context extends StoreContext<any>> =
/** @public */
export type StoreObject<R extends UnknownRecord> = Store<R> | { store: Store<R> }
/** @public */
export type StoreObjectRecordType<Context extends StoreObject<any>> =
Context extends Store<infer R> ? R : Context extends { store: Store<infer R> } ? R : never
/**
@ -992,9 +998,9 @@ type ContextRecordType<Context extends StoreContext<any>> =
* @public
*/
export function createComputedCache<
Context extends StoreContext<any>,
Context extends StoreObject<any>,
Result,
Record extends ContextRecordType<Context> = ContextRecordType<Context>,
Record extends StoreObjectRecordType<Context> = StoreObjectRecordType<Context>,
>(
name: string,
derive: (context: Context, record: Record) => Result | undefined,

View file

@ -16,24 +16,28 @@ import { RecordsDiff } from './RecordsDiff'
import { diffSets } from './setUtils'
import { CollectionDiff } from './Store'
/** @public */
export type RSIndexDiff<
R extends UnknownRecord,
Property extends string & keyof R = string & keyof R,
> = Map<R[Property], CollectionDiff<IdOf<R>>>
/** @public */
export type RSIndexMap<
R extends UnknownRecord,
Property extends string & keyof R = string & keyof R,
> = Map<R[Property], Set<IdOf<R>>>
/** @public */
export type RSIndex<
R extends UnknownRecord,
Property extends string & keyof R = string & keyof R,
> = Computed<Map<R[Property], Set<IdOf<R>>>, RSIndexDiff<R, Property>>
> = Computed<RSIndexMap<R, Property>, RSIndexDiff<R, Property>>
/**
* A class that provides a 'namespace' for the various kinds of indexes one may wish to derive from
* the record store.
* @public
*/
export class StoreQueries<R extends UnknownRecord> {
constructor(

View file

@ -2,17 +2,19 @@ import { IdOf, UnknownRecord } from './BaseRecord'
import { intersectSets } from './setUtils'
import { StoreQueries } from './StoreQueries'
export type ValueMatcher<T> = { eq: T } | { neq: T } | { gt: number }
/** @public */
export type QueryValueMatcher<T> = { eq: T } | { neq: T } | { gt: number }
/** @public */
export type QueryExpression<R extends object> = {
[k in keyof R & string]?: ValueMatcher<R[k]>
[k in keyof R & string]?: QueryValueMatcher<R[k]>
// todo: handle nesting
// | (R[k] extends object ? { match: QueryExpression<R[k]> } : never)
}
export function objectMatchesQuery<T extends object>(query: QueryExpression<T>, object: T) {
for (const [key, _matcher] of Object.entries(query)) {
const matcher = _matcher as ValueMatcher<T>
const matcher = _matcher as QueryValueMatcher<T>
const value = object[key as keyof T]
// if you add matching logic here, make sure you also update executeQuery,
// where initial data is pulled out of the indexes, since that requires different

View file

@ -163,7 +163,8 @@ export type Migration = {
}
)
interface LegacyBaseMigrationsInfo {
/** @public */
export interface LegacyBaseMigrationsInfo {
firstVersion: number
currentVersion: number
migrators: { [version: number]: LegacyMigration }

View file

@ -1,13 +0,0 @@
import { RecordType } from './RecordType'
import { Store } from './Store'
type ExtractRecordType<T extends Store<any>> = T extends Store<infer R> ? R : never
type ExtractR<T extends RecordType<any, any>> = T extends RecordType<infer S, any> ? S : never
/**
* Get the type of all records in a record store.
*
* @public
*/
export type AllRecords<T extends Store<any>> = ExtractR<ExtractRecordType<T>>

File diff suppressed because one or more lines are too long

View file

@ -1,18 +1,16 @@
/// <reference types="react" />
export { preloadFont } from './lib/utils/assets/preload-font'
export { useCanRedo, useCanUndo } from './lib/ui/hooks/menu-hooks'
// eslint-disable-next-line local/no-export-star
export * from '@tldraw/editor'
export { Tldraw, type TldrawProps } from './lib/Tldraw'
export { Tldraw, type TLComponents, type TldrawProps } from './lib/Tldraw'
export { TldrawImage, type TldrawImageProps } from './lib/TldrawImage'
export { TldrawHandles } from './lib/canvas/TldrawHandles'
export { TldrawScribble } from './lib/canvas/TldrawScribble'
export { TldrawSelectionBackground } from './lib/canvas/TldrawSelectionBackground'
export { TldrawSelectionForeground } from './lib/canvas/TldrawSelectionForeground'
export { defaultBindingUtils } from './lib/defaultBindingUtils'
export { type TLExternalContentProps } from './lib/defaultExternalContentHandlers'
export { defaultShapeTools } from './lib/defaultShapeTools'
export { defaultShapeUtils } from './lib/defaultShapeUtils'
export { defaultTools } from './lib/defaultTools'
@ -40,139 +38,30 @@ export { LineShapeUtil } from './lib/shapes/line/LineShapeUtil'
export { NoteShapeTool } from './lib/shapes/note/NoteShapeTool'
export { NoteShapeUtil } from './lib/shapes/note/NoteShapeUtil'
export { useDefaultColorTheme } from './lib/shapes/shared/ShapeFill'
export { TextLabel } from './lib/shapes/shared/TextLabel'
export { TextLabel, type TextLabelProps } from './lib/shapes/shared/TextLabel'
export {
FONT_FAMILIES,
LABEL_FONT_SIZES,
TEXT_PROPS,
} from './lib/shapes/shared/default-shape-constants'
export { getPerfectDashProps } from './lib/shapes/shared/getPerfectDashProps'
export { useEditableText } from './lib/shapes/shared/useEditableText'
export { TextShapeTool } from './lib/shapes/text/TextShapeTool'
export { TextShapeUtil } from './lib/shapes/text/TextShapeUtil'
export { VideoShapeUtil } from './lib/shapes/video/VideoShapeUtil'
export { type StyleValuesForUi } from './lib/styles'
export { EraserTool } from './lib/tools/EraserTool/EraserTool'
export { HandTool } from './lib/tools/HandTool/HandTool'
export { LaserTool } from './lib/tools/LaserTool/LaserTool'
export { SelectTool } from './lib/tools/SelectTool/SelectTool'
export { getOccludedChildren, kickoutOccludedShapes } from './lib/tools/SelectTool/selectHelpers'
export { ZoomTool } from './lib/tools/ZoomTool/ZoomTool'
// UI
export { useEditableText } from './lib/shapes/shared/useEditableText'
export { TldrawUi, type TldrawUiBaseProps, type TldrawUiProps } from './lib/ui/TldrawUi'
export { setDefaultUiAssetUrls, type TLUiAssetUrlOverrides } from './lib/ui/assetUrls'
export { OfflineIndicator } from './lib/ui/components/OfflineIndicator/OfflineIndicator'
export { Spinner } from './lib/ui/components/Spinner'
export { PORTRAIT_BREAKPOINT } from './lib/ui/constants'
export {
TldrawUiContextProvider,
type TldrawUiContextProviderProps,
} from './lib/ui/context/TldrawUiContextProvider'
export {
useActions,
type TLUiActionItem,
type TLUiActionsContextType,
} from './lib/ui/context/actions'
export { AssetUrlsProvider, useAssetUrls } from './lib/ui/context/asset-urls'
export { BreakPointProvider, useBreakpoint } from './lib/ui/context/breakpoints'
export {
useDialogs,
type TLUiDialog,
type TLUiDialogProps,
type TLUiDialogsContextType,
} from './lib/ui/context/dialogs'
export {
UiEventsProvider,
useUiEvents,
type EventsProviderProps,
type TLUiEventContextType,
type TLUiEventHandler,
type TLUiEventMap,
type TLUiEventSource,
} from './lib/ui/context/events'
export {
useToasts,
type AlertSeverity,
type TLUiToast,
type TLUiToastAction,
type TLUiToastsContextType,
} from './lib/ui/context/toasts'
export { useMenuClipboardEvents, useNativeClipboardEvents } from './lib/ui/hooks/useClipboardEvents'
export { useCopyAs } from './lib/ui/hooks/useCopyAs'
export { useExportAs } from './lib/ui/hooks/useExportAs'
export { useKeyboardShortcuts } from './lib/ui/hooks/useKeyboardShortcuts'
export { useLocalStorageState } from './lib/ui/hooks/useLocalStorageState'
export { useMenuIsOpen } from './lib/ui/hooks/useMenuIsOpen'
export { usePreloadAssets } from './lib/ui/hooks/usePreloadAssets'
export { useReadonly } from './lib/ui/hooks/useReadonly'
export { useRelevantStyles } from './lib/ui/hooks/useRelevantStyles'
export {
useTools,
type TLUiToolItem,
type TLUiToolsContextType,
type TLUiToolsProviderProps,
} from './lib/ui/hooks/useTools'
export { type TLUiTranslationKey } from './lib/ui/hooks/useTranslation/TLUiTranslationKey'
export { type TLUiTranslation } from './lib/ui/hooks/useTranslation/translations'
export {
useCurrentTranslation,
useTranslation,
type TLUiTranslationContextType,
} from './lib/ui/hooks/useTranslation/useTranslation'
export { type TLUiIconType } from './lib/ui/icon-types'
export { useDefaultHelpers, type TLUiOverrides } from './lib/ui/overrides'
export { containBoxSize, downsizeImage } from './lib/utils/assets/assets'
export { getEmbedInfo } from './lib/utils/embeds/embeds'
export { copyAs } from './lib/utils/export/copyAs'
export { exportToBlob, getSvgAsImage } from './lib/utils/export/export'
export { exportAs, type TLExportType } from './lib/utils/export/exportAs'
export { fitFrameToContent, removeFrame } from './lib/utils/frames/frames'
export {
defaultEditorAssetUrls,
setDefaultEditorAssetUrls,
} from './lib/utils/static-assets/assetUrls'
export { truncateStringWithEllipsis } from './lib/utils/text/text'
export {
buildFromV1Document,
type LegacyTldrawDocument,
} from './lib/utils/tldr/buildFromV1Document'
export {
TLDRAW_FILE_EXTENSION,
parseAndLoadDocument,
parseTldrawJsonFile,
serializeTldrawJson,
serializeTldrawJsonBlob,
type TldrawFile,
} from './lib/utils/tldr/file'
// Minimap default component
export { DefaultMinimap } from './lib/ui/components/Minimap/DefaultMinimap'
// Helper to unwrap label from action items
export { unwrapLabel } from './lib/ui/context/actions'
export {
TldrawUiComponentsProvider,
useTldrawUiComponents,
type TLUiComponents,
type TLUiComponentsProviderProps,
} from './lib/ui/context/components'
export { DefaultPageMenu } from './lib/ui/components/PageMenu/DefaultPageMenu'
export { PageItemInput } from './lib/ui/components/PageMenu/PageItemInput'
export { PageItemSubmenu } from './lib/ui/components/PageMenu/PageItemSubmenu'
export { DefaultNavigationPanel } from './lib/ui/components/NavigationPanel/DefaultNavigationPanel'
export {
DefaultStylePanel,
type TLUiStylePanelProps,
} from './lib/ui/components/StylePanel/DefaultStylePanel'
export {
ArrowheadStylePickerSet,
CommonStylePickerSet,
DefaultStylePanelContent,
GeoStylePickerSet,
OpacitySlider,
SplineStylePickerSet,
TextStylePickerSet,
type TLUiStylePanelContentProps,
} from './lib/ui/components/StylePanel/DefaultStylePanelContent'
setDefaultUiAssetUrls,
type TLUiAssetUrlOverrides,
type TLUiAssetUrls,
} from './lib/ui/assetUrls'
export {
DefaultActionsMenu,
type TLUiActionsMenuProps,
@ -187,14 +76,22 @@ export {
StackMenuItems,
ZoomOrRotateMenuItem,
} from './lib/ui/components/ActionsMenu/DefaultActionsMenuContent'
export {
DefaultContextMenu as ContextMenu,
DefaultContextMenu,
type TLUiContextMenuProps,
} from './lib/ui/components/ContextMenu/DefaultContextMenu'
export { DefaultContextMenuContent } from './lib/ui/components/ContextMenu/DefaultContextMenuContent'
export {
DefaultDebugMenu,
type TLUiDebugMenuProps,
} from './lib/ui/components/DebugMenu/DefaultDebugMenu'
export {
DebugFlags,
DefaultDebugMenuContent,
ExampleDialog,
FeatureFlags,
} from './lib/ui/components/DebugMenu/DefaultDebugMenuContent'
export {
DefaultHelpMenu,
type TLUiHelpMenuProps,
@ -203,8 +100,99 @@ export {
DefaultHelpMenuContent,
KeyboardShortcutsMenuItem,
} from './lib/ui/components/HelpMenu/DefaultHelpMenuContent'
export {
DefaultHelperButtons,
type TLUiHelperButtonsProps,
} from './lib/ui/components/HelperButtons/DefaultHelperButtons'
export { DefaultHelperButtonsContent } from './lib/ui/components/HelperButtons/DefaultHelperButtonsContent'
export {
DefaultKeyboardShortcutsDialog,
type TLUiKeyboardShortcutsDialogProps,
} from './lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialog'
export { DefaultKeyboardShortcutsDialogContent } from './lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent'
export { LanguageMenu } from './lib/ui/components/LanguageMenu'
export {
DefaultMainMenu,
type TLUiMainMenuProps,
} from './lib/ui/components/MainMenu/DefaultMainMenu'
export {
DefaultMainMenuContent,
EditSubmenu,
ExportFileContentSubMenu,
ExtrasGroup,
MiscMenuGroup,
PreferencesGroup,
UndoRedoGroup,
ViewSubmenu,
} from './lib/ui/components/MainMenu/DefaultMainMenuContent'
export { DefaultMinimap } from './lib/ui/components/Minimap/DefaultMinimap'
export { DefaultNavigationPanel } from './lib/ui/components/NavigationPanel/DefaultNavigationPanel'
export { OfflineIndicator } from './lib/ui/components/OfflineIndicator/OfflineIndicator'
export { DefaultPageMenu } from './lib/ui/components/PageMenu/DefaultPageMenu'
export { PageItemInput } from './lib/ui/components/PageMenu/PageItemInput'
export {
PageItemSubmenu,
type PageItemSubmenuProps,
} from './lib/ui/components/PageMenu/PageItemSubmenu'
export {
DefaultQuickActions,
type TLUiQuickActionsProps,
} from './lib/ui/components/QuickActions/DefaultQuickActions'
export { DefaultQuickActionsContent } from './lib/ui/components/QuickActions/DefaultQuickActionsContent'
export { Spinner } from './lib/ui/components/Spinner'
export {
DefaultStylePanel,
type TLUiStylePanelProps,
} from './lib/ui/components/StylePanel/DefaultStylePanel'
export {
ArrowheadStylePickerSet,
CommonStylePickerSet,
DefaultStylePanelContent,
GeoStylePickerSet,
OpacitySlider,
SplineStylePickerSet,
TextStylePickerSet,
type TLUiStylePanelContentProps,
} from './lib/ui/components/StylePanel/DefaultStylePanelContent'
export { DefaultToolbar } from './lib/ui/components/Toolbar/DefaultToolbar'
export {
ArrowDownToolbarItem,
ArrowLeftToolbarItem,
ArrowRightToolbarItem,
ArrowToolbarItem,
ArrowUpToolbarItem,
AssetToolbarItem,
CheckBoxToolbarItem,
CloudToolbarItem,
DefaultToolbarContent,
DiamondToolbarItem,
DrawToolbarItem,
EllipseToolbarItem,
EraserToolbarItem,
FrameToolbarItem,
HandToolbarItem,
HexagonToolbarItem,
HighlightToolbarItem,
LaserToolbarItem,
LineToolbarItem,
NoteToolbarItem,
OvalToolbarItem,
RectangleToolbarItem,
RhombusToolbarItem,
SelectToolbarItem,
StarToolbarItem,
TextToolbarItem,
ToolbarItem,
TrapezoidToolbarItem,
TriangleToolbarItem,
XBoxToolbarItem,
useIsToolSelected,
} from './lib/ui/components/Toolbar/DefaultToolbarContent'
export {
DefaultZoomMenu,
type TLUiZoomMenuProps,
} from './lib/ui/components/ZoomMenu/DefaultZoomMenu'
export { DefaultZoomMenuContent } from './lib/ui/components/ZoomMenu/DefaultZoomMenuContent'
export {
ArrangeMenuSubmenu,
ClipboardMenuGroup,
@ -243,62 +231,6 @@ export {
ZoomToFitMenuItem,
ZoomToSelectionMenuItem,
} from './lib/ui/components/menu-items'
export {
DefaultMainMenu,
type TLUiMainMenuProps,
} from './lib/ui/components/MainMenu/DefaultMainMenu'
export {
DefaultMainMenuContent,
EditSubmenu,
ExportFileContentSubMenu,
ExtrasGroup,
MiscMenuGroup,
PreferencesGroup,
UndoRedoGroup,
ViewSubmenu,
} from './lib/ui/components/MainMenu/DefaultMainMenuContent'
export {
DefaultQuickActions,
type TLUiQuickActionsProps,
} from './lib/ui/components/QuickActions/DefaultQuickActions'
export { DefaultQuickActionsContent } from './lib/ui/components/QuickActions/DefaultQuickActionsContent'
export {
DefaultZoomMenu,
type TLUiZoomMenuProps,
} from './lib/ui/components/ZoomMenu/DefaultZoomMenu'
export { DefaultZoomMenuContent } from './lib/ui/components/ZoomMenu/DefaultZoomMenuContent'
export {
DefaultHelperButtons,
type TLUiHelperButtonsProps,
} from './lib/ui/components/HelperButtons/DefaultHelperButtons'
export { DefaultHelperButtonsContent } from './lib/ui/components/HelperButtons/DefaultHelperButtonsContent'
export {
DefaultKeyboardShortcutsDialog,
type TLUiKeyboardShortcutsDialogProps,
} from './lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialog'
export { DefaultKeyboardShortcutsDialogContent } from './lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent'
export {
DefaultDebugMenu,
type TLUiDebugMenuProps,
} from './lib/ui/components/DebugMenu/DefaultDebugMenu'
export {
DebugFlags,
DefaultDebugMenuContent,
ExampleDialog,
FeatureFlags,
} from './lib/ui/components/DebugMenu/DefaultDebugMenuContent'
export { type TLComponents } from './lib/Tldraw'
/* ------------------- Primitives ------------------- */
// Button
export {
TldrawUiButton,
type TLUiButtonProps,
@ -315,14 +247,10 @@ export {
TldrawUiButtonLabel,
type TLUiButtonLabelProps,
} from './lib/ui/components/primitives/Button/TldrawUiButtonLabel'
// Button picker
export {
TldrawUiButtonPicker,
type TLUiButtonPickerProps,
} from './lib/ui/components/primitives/TldrawUiButtonPicker'
// Dialog
export {
TldrawUiDialogBody,
TldrawUiDialogCloseButton,
@ -334,8 +262,6 @@ export {
type TLUiDialogHeaderProps,
type TLUiDialogTitleProps,
} from './lib/ui/components/primitives/TldrawUiDialog'
// Dropdown Menu
export {
TldrawUiDropdownMenuCheckboxItem,
TldrawUiDropdownMenuContent,
@ -355,17 +281,9 @@ export {
type TLUiDropdownMenuSubTriggerProps,
type TLUiDropdownMenuTriggerProps,
} from './lib/ui/components/primitives/TldrawUiDropdownMenu'
// Icon
export { TldrawUiIcon, type TLUiIconProps } from './lib/ui/components/primitives/TldrawUiIcon'
// Input
export { TldrawUiInput, type TLUiInputProps } from './lib/ui/components/primitives/TldrawUiInput'
// Kbd
export { TldrawUiKbd, type TLUiKbdProps } from './lib/ui/components/primitives/TldrawUiKbd'
// Popover
export {
TldrawUiPopover,
TldrawUiPopoverContent,
@ -374,49 +292,7 @@ export {
type TLUiPopoverProps,
type TLUiPopoverTriggerProps,
} from './lib/ui/components/primitives/TldrawUiPopover'
// Slider
export { TldrawUiSlider, type TLUiSliderProps } from './lib/ui/components/primitives/TldrawUiSlider'
// Toolbar
export { DefaultToolbar } from './lib/ui/components/Toolbar/DefaultToolbar'
export {
ArrowDownToolbarItem,
ArrowLeftToolbarItem,
ArrowRightToolbarItem,
ArrowToolbarItem,
ArrowUpToolbarItem,
AssetToolbarItem,
CheckBoxToolbarItem,
CloudToolbarItem,
DefaultToolbarContent,
DiamondToolbarItem,
DrawToolbarItem,
EllipseToolbarItem,
EraserToolbarItem,
FrameToolbarItem,
HandToolbarItem,
HexagonToolbarItem,
HighlightToolbarItem,
LaserToolbarItem,
LineToolbarItem,
NoteToolbarItem,
OvalToolbarItem,
RectangleToolbarItem,
RhombusToolbarItem,
SelectToolbarItem,
StarToolbarItem,
TextToolbarItem,
ToolbarItem,
TrapezoidToolbarItem,
TriangleToolbarItem,
XBoxToolbarItem,
useIsToolSelected,
} from './lib/ui/components/Toolbar/DefaultToolbarContent'
/* ----------------- Menu Primitives ---------------- */
// General UI components for building menus
export {
TldrawUiMenuCheckboxItem,
type TLUiMenuCheckboxItemProps,
@ -424,6 +300,7 @@ export {
export {
TldrawUiMenuContextProvider,
type TLUiMenuContextProviderProps,
type TldrawUiMenuContextType,
} from './lib/ui/components/primitives/menus/TldrawUiMenuContext'
export {
TldrawUiMenuGroup,
@ -437,11 +314,130 @@ export {
TldrawUiMenuSubmenu,
type TLUiMenuSubmenuProps,
} from './lib/ui/components/primitives/menus/TldrawUiMenuSubmenu'
/* ----------------- Constants ---------------- */
export { PORTRAIT_BREAKPOINT } from './lib/ui/constants'
export {
FONT_FAMILIES,
LABEL_FONT_SIZES,
TEXT_PROPS,
} from './lib/shapes/shared/default-shape-constants'
TldrawUiContextProvider,
type TldrawUiContextProviderProps,
} from './lib/ui/context/TldrawUiContextProvider'
export {
unwrapLabel,
useActions,
type ActionsProviderProps,
type TLUiActionItem,
type TLUiActionsContextType,
} from './lib/ui/context/actions'
export { AssetUrlsProvider, useAssetUrls } from './lib/ui/context/asset-urls'
export { BreakPointProvider, useBreakpoint } from './lib/ui/context/breakpoints'
export {
TldrawUiComponentsProvider,
useTldrawUiComponents,
type TLUiComponents,
type TLUiComponentsProviderProps,
} from './lib/ui/context/components'
export {
useDialogs,
type TLUiDialog,
type TLUiDialogProps,
type TLUiDialogsContextType,
} from './lib/ui/context/dialogs'
export {
UiEventsProvider,
useUiEvents,
type EventsProviderProps,
type TLUiEventContextType,
type TLUiEventData,
type TLUiEventHandler,
type TLUiEventMap,
type TLUiEventSource,
} from './lib/ui/context/events'
export {
useToasts,
type AlertSeverity,
type TLUiToast,
type TLUiToastAction,
type TLUiToastsContextType,
} from './lib/ui/context/toasts'
export { useCanRedo, useCanUndo } from './lib/ui/hooks/menu-hooks'
export { useMenuClipboardEvents, useNativeClipboardEvents } from './lib/ui/hooks/useClipboardEvents'
export { useCopyAs } from './lib/ui/hooks/useCopyAs'
export { useExportAs } from './lib/ui/hooks/useExportAs'
export { useKeyboardShortcuts } from './lib/ui/hooks/useKeyboardShortcuts'
export { useLocalStorageState } from './lib/ui/hooks/useLocalStorageState'
export { useMenuIsOpen } from './lib/ui/hooks/useMenuIsOpen'
export { usePreloadAssets } from './lib/ui/hooks/usePreloadAssets'
export { useReadonly } from './lib/ui/hooks/useReadonly'
export { useRelevantStyles } from './lib/ui/hooks/useRelevantStyles'
export {
useTools,
type TLUiToolItem,
type TLUiToolsContextType,
type TLUiToolsProviderProps,
} from './lib/ui/hooks/useTools'
export { type TLUiTranslationKey } from './lib/ui/hooks/useTranslation/TLUiTranslationKey'
export { type TLUiTranslation } from './lib/ui/hooks/useTranslation/translations'
export {
useCurrentTranslation,
useTranslation,
type TLUiTranslationContextType,
type TLUiTranslationProviderProps,
} from './lib/ui/hooks/useTranslation/useTranslation'
export { type TLUiIconType } from './lib/ui/icon-types'
export { useDefaultHelpers, type TLUiOverrideHelpers, type TLUiOverrides } from './lib/ui/overrides'
export { containBoxSize, downsizeImage, type BoxWidthHeight } from './lib/utils/assets/assets'
export { preloadFont, type TLTypeFace } from './lib/utils/assets/preload-font'
export { getEmbedInfo, type TLEmbedResult } from './lib/utils/embeds/embeds'
export { copyAs, type TLCopyType } from './lib/utils/export/copyAs'
export { exportToBlob, getSvgAsImage } from './lib/utils/export/export'
export { exportAs, type TLExportType } from './lib/utils/export/exportAs'
export { fitFrameToContent, removeFrame } from './lib/utils/frames/frames'
export {
defaultEditorAssetUrls,
setDefaultEditorAssetUrls,
type TLEditorAssetUrls,
} from './lib/utils/static-assets/assetUrls'
export { truncateStringWithEllipsis } from './lib/utils/text/text'
export {
TLV1AlignStyle,
TLV1AssetType,
TLV1ColorStyle,
TLV1DashStyle,
TLV1Decoration,
TLV1FontStyle,
TLV1ShapeType,
TLV1SizeStyle,
buildFromV1Document,
type TLV1ArrowBinding,
type TLV1ArrowShape,
type TLV1Asset,
type TLV1BaseAsset,
type TLV1BaseBinding,
type TLV1BaseShape,
type TLV1Binding,
type TLV1Bounds,
type TLV1Document,
type TLV1DrawShape,
type TLV1EllipseShape,
type TLV1GroupShape,
type TLV1Handle,
type TLV1ImageAsset,
type TLV1ImageShape,
type TLV1Page,
type TLV1PageState,
type TLV1RectangleShape,
type TLV1Shape,
type TLV1ShapeStyles,
type TLV1StickyShape,
type TLV1TextShape,
type TLV1TriangleShape,
type TLV1VideoAsset,
type TLV1VideoShape,
} from './lib/utils/tldr/buildFromV1Document'
export {
TLDRAW_FILE_EXTENSION,
parseAndLoadDocument,
parseTldrawJsonFile,
serializeTldrawJson,
serializeTldrawJsonBlob,
type TldrawFile,
type TldrawFileParseError,
} from './lib/utils/tldr/file'

View file

@ -1,4 +1,4 @@
import { StateNode } from '@tldraw/editor'
import { StateNode, TLStateNodeConstructor } from '@tldraw/editor'
import { Idle } from './toolStates/Idle'
import { Pointing } from './toolStates/Pointing'
@ -6,7 +6,7 @@ import { Pointing } from './toolStates/Pointing'
export class ArrowShapeTool extends StateNode {
static override id = 'arrow'
static override initial = 'idle'
static override children = () => [Idle, Pointing]
static override children = (): TLStateNodeConstructor[] => [Idle, Pointing]
override shapeType = 'arrow'
}

View file

@ -1,4 +1,4 @@
import { StateNode } from '@tldraw/editor'
import { StateNode, TLStateNodeConstructor } from '@tldraw/editor'
import { Drawing } from './toolStates/Drawing'
import { Idle } from './toolStates/Idle'
@ -6,7 +6,7 @@ import { Idle } from './toolStates/Idle'
export class DrawShapeTool extends StateNode {
static override id = 'draw'
static override initial = 'idle'
static override children = () => [Idle, Drawing]
static override children = (): TLStateNodeConstructor[] => [Idle, Drawing]
override shapeType = 'draw'

View file

@ -1,4 +1,4 @@
import { StateNode } from '@tldraw/editor'
import { StateNode, TLStateNodeConstructor } from '@tldraw/editor'
import { Idle } from './toolStates/Idle'
import { Pointing } from './toolStates/Pointing'
@ -6,6 +6,6 @@ import { Pointing } from './toolStates/Pointing'
export class GeoShapeTool extends StateNode {
static override id = 'geo'
static override initial = 'idle'
static override children = () => [Idle, Pointing]
static override children = (): TLStateNodeConstructor[] => [Idle, Pointing]
override shapeType = 'geo'
}

View file

@ -1,5 +1,5 @@
// shared custody
import { StateNode } from '@tldraw/editor'
import { StateNode, TLStateNodeConstructor } from '@tldraw/editor'
import { Drawing } from '../draw/toolStates/Drawing'
import { Idle } from '../draw/toolStates/Idle'
@ -7,7 +7,7 @@ import { Idle } from '../draw/toolStates/Idle'
export class HighlightShapeTool extends StateNode {
static override id = 'highlight'
static override initial = 'idle'
static override children = () => [Idle, Drawing]
static override children = (): TLStateNodeConstructor[] => [Idle, Drawing]
override shapeType = 'highlight'
override onExit = () => {

View file

@ -1,4 +1,4 @@
import { StateNode } from '@tldraw/editor'
import { StateNode, TLStateNodeConstructor } from '@tldraw/editor'
import { Idle } from './toolStates/Idle'
import { Pointing } from './toolStates/Pointing'
@ -6,7 +6,7 @@ import { Pointing } from './toolStates/Pointing'
export class LineShapeTool extends StateNode {
static override id = 'line'
static override initial = 'idle'
static override children = () => [Idle, Pointing]
static override children = (): TLStateNodeConstructor[] => [Idle, Pointing]
override shapeType = 'line'
}

View file

@ -1,4 +1,4 @@
import { StateNode } from '@tldraw/editor'
import { StateNode, TLStateNodeConstructor } from '@tldraw/editor'
import { Idle } from './toolStates/Idle'
import { Pointing } from './toolStates/Pointing'
@ -6,6 +6,6 @@ import { Pointing } from './toolStates/Pointing'
export class NoteShapeTool extends StateNode {
static override id = 'note'
static override initial = 'idle'
static override children = () => [Idle, Pointing]
static override children = (): TLStateNodeConstructor[] => [Idle, Pointing]
override shapeType = 'note'
}

View file

@ -12,7 +12,8 @@ import { TextHelpers } from './TextHelpers'
import { isLegacyAlign } from './legacyProps'
import { useEditableText } from './useEditableText'
interface TextLabelProps {
/** @public */
export interface TextLabelProps {
id: TLShapeId
type: string
font: TLDefaultFontStyle

View file

@ -2,6 +2,7 @@ import {
TLShapeId,
TLUnknownShape,
getPointerInfo,
noop,
stopEventPropagation,
useEditor,
useValue,
@ -133,7 +134,3 @@ export function useEditableText(id: TLShapeId, type: string, text: string) {
isEditingAnything,
}
}
function noop() {
return
}

View file

@ -1,4 +1,4 @@
import { StateNode } from '@tldraw/editor'
import { StateNode, TLStateNodeConstructor } from '@tldraw/editor'
import { Idle } from './toolStates/Idle'
import { Pointing } from './toolStates/Pointing'
@ -6,6 +6,6 @@ import { Pointing } from './toolStates/Pointing'
export class TextShapeTool extends StateNode {
static override id = 'text'
static override initial = 'idle'
static override children = () => [Idle, Pointing]
static override children = (): TLStateNodeConstructor[] => [Idle, Pointing]
override shapeType = 'text'
}

View file

@ -1,3 +1,4 @@
/** @public */
export type StyleValuesForUi<T> = readonly {
readonly value: T
readonly icon: string

View file

@ -1,4 +1,4 @@
import { StateNode } from '@tldraw/editor'
import { StateNode, TLStateNodeConstructor } from '@tldraw/editor'
import { Erasing } from './childStates/Erasing'
import { Idle } from './childStates/Idle'
import { Pointing } from './childStates/Pointing'
@ -7,7 +7,7 @@ import { Pointing } from './childStates/Pointing'
export class EraserTool extends StateNode {
static override id = 'eraser'
static override initial = 'idle'
static override children = () => [Idle, Pointing, Erasing]
static override children = (): TLStateNodeConstructor[] => [Idle, Pointing, Erasing]
override onEnter = () => {
this.editor.setCursor({ type: 'cross', rotation: 0 })

View file

@ -1,4 +1,4 @@
import { EASINGS, StateNode, TLClickEvent } from '@tldraw/editor'
import { EASINGS, StateNode, TLClickEvent, TLStateNodeConstructor } from '@tldraw/editor'
import { Dragging } from './childStates/Dragging'
import { Idle } from './childStates/Idle'
import { Pointing } from './childStates/Pointing'
@ -7,7 +7,7 @@ import { Pointing } from './childStates/Pointing'
export class HandTool extends StateNode {
static override id = 'hand'
static override initial = 'idle'
static override children = () => [Idle, Pointing, Dragging]
static override children = (): TLStateNodeConstructor[] => [Idle, Pointing, Dragging]
override onDoubleClick: TLClickEvent = (info) => {
if (info.phase === 'settle') {

View file

@ -1,4 +1,4 @@
import { StateNode } from '@tldraw/editor'
import { StateNode, TLStateNodeConstructor } from '@tldraw/editor'
import { Idle } from './childStates/Idle'
import { Lasering } from './childStates/Lasering'
@ -6,7 +6,7 @@ import { Lasering } from './childStates/Lasering'
export class LaserTool extends StateNode {
static override id = 'laser'
static override initial = 'idle'
static override children = () => [Idle, Lasering]
static override children = (): TLStateNodeConstructor[] => [Idle, Lasering]
override onEnter = () => {
this.editor.setCursor({ type: 'cross', rotation: 0 })

View file

@ -1,4 +1,4 @@
import { StateNode, react } from '@tldraw/editor'
import { StateNode, TLStateNodeConstructor, react } from '@tldraw/editor'
import { Brushing } from './childStates/Brushing'
import { Crop } from './childStates/Crop/Crop'
import { Cropping } from './childStates/Cropping'
@ -24,7 +24,7 @@ export class SelectTool extends StateNode {
static override initial = 'idle'
reactor: undefined | (() => void) = undefined
static override children = () => [
static override children = (): TLStateNodeConstructor[] => [
Crop,
Cropping,
Idle,

View file

@ -1,4 +1,10 @@
import { StateNode, TLInterruptEvent, TLKeyboardEvent, TLPointerEventInfo } from '@tldraw/editor'
import {
StateNode,
TLInterruptEvent,
TLKeyboardEvent,
TLPointerEventInfo,
TLStateNodeConstructor,
} from '@tldraw/editor'
import { Idle } from './childStates/Idle'
import { Pointing } from './childStates/Pointing'
import { ZoomBrushing } from './childStates/ZoomBrushing'
@ -7,7 +13,7 @@ import { ZoomBrushing } from './childStates/ZoomBrushing'
export class ZoomTool extends StateNode {
static override id = 'zoom'
static override initial = 'idle'
static override children = () => [Idle, ZoomBrushing, Pointing]
static override children = (): TLStateNodeConstructor[] => [Idle, ZoomBrushing, Pointing]
info = {} as TLPointerEventInfo & { onInteractionEnd?: string }

View file

@ -3,6 +3,7 @@ import { version } from '../ui/version'
import { TLEditorAssetUrls, defaultEditorAssetUrls } from '../utils/static-assets/assetUrls'
import { TLUiIconType, iconTypes } from './icon-types'
/** @public */
export type TLUiAssetUrls = TLEditorAssetUrls & {
icons: Record<TLUiIconType | Exclude<string, TLUiIconType>, string>
translations: Record<(typeof LANGUAGES)[number]['locale'], string>

View file

@ -7,7 +7,7 @@ import {
useEditor,
} from '@tldraw/editor'
import classNames from 'classnames'
import { memo, useMemo, useRef } from 'react'
import { ReactElement, memo, useMemo, useRef } from 'react'
import { StyleValuesForUi } from '../../../styles'
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
@ -25,7 +25,10 @@ export interface TLUiButtonPickerProps<T extends string> {
onValueChange: (style: StyleProp<T>, value: T) => void
}
function _TldrawUiButtonPicker<T extends string>(props: TLUiButtonPickerProps<T>) {
/** @public */
export const TldrawUiButtonPicker = memo(function TldrawUiButtonPicker<T extends string>(
props: TLUiButtonPickerProps<T>
) {
const {
uiType,
items,
@ -130,6 +133,4 @@ function _TldrawUiButtonPicker<T extends string>(props: TLUiButtonPickerProps<T>
))}
</div>
)
}
/** @public */
export const TldrawUiButtonPicker = memo(_TldrawUiButtonPicker) as typeof _TldrawUiButtonPicker
}) as <T extends string>(props: TLUiButtonPickerProps<T>) => ReactElement

View file

@ -32,31 +32,27 @@ import { DefaultStylePanel, TLUiStylePanelProps } from '../components/StylePanel
import { DefaultToolbar } from '../components/Toolbar/DefaultToolbar'
import { DefaultZoomMenu, TLUiZoomMenuProps } from '../components/ZoomMenu/DefaultZoomMenu'
export interface BaseTLUiComponents {
ContextMenu: ComponentType<TLUiContextMenuProps>
ActionsMenu: ComponentType<TLUiActionsMenuProps>
HelpMenu: ComponentType<TLUiHelpMenuProps>
ZoomMenu: ComponentType<TLUiZoomMenuProps>
MainMenu: ComponentType<TLUiMainMenuProps>
Minimap: ComponentType
StylePanel: ComponentType<TLUiStylePanelProps>
PageMenu: ComponentType
NavigationPanel: ComponentType
Toolbar: ComponentType
KeyboardShortcutsDialog: ComponentType<TLUiKeyboardShortcutsDialogProps>
QuickActions: ComponentType<TLUiQuickActionsProps>
HelperButtons: ComponentType<TLUiHelperButtonsProps>
DebugPanel: ComponentType
DebugMenu: ComponentType
MenuPanel: ComponentType
TopPanel: ComponentType
SharePanel: ComponentType
}
/** @public */
export type TLUiComponents = Partial<{
[K in keyof BaseTLUiComponents]: BaseTLUiComponents[K] | null
}>
export interface TLUiComponents {
ContextMenu?: ComponentType<TLUiContextMenuProps> | null
ActionsMenu?: ComponentType<TLUiActionsMenuProps> | null
HelpMenu?: ComponentType<TLUiHelpMenuProps> | null
ZoomMenu?: ComponentType<TLUiZoomMenuProps> | null
MainMenu?: ComponentType<TLUiMainMenuProps> | null
Minimap?: ComponentType | null
StylePanel?: ComponentType<TLUiStylePanelProps> | null
PageMenu?: ComponentType | null
NavigationPanel?: ComponentType | null
Toolbar?: ComponentType | null
KeyboardShortcutsDialog?: ComponentType<TLUiKeyboardShortcutsDialogProps> | null
QuickActions?: ComponentType<TLUiQuickActionsProps> | null
HelperButtons?: ComponentType<TLUiHelperButtonsProps> | null
DebugPanel?: ComponentType | null
DebugMenu?: ComponentType | null
MenuPanel?: ComponentType | null
TopPanel?: ComponentType | null
SharePanel?: ComponentType | null
}
const TldrawUiComponentsContext = createContext<TLUiComponents | null>(null)

View file

@ -98,14 +98,15 @@ export interface TLUiEventMap {
'unlock-all': null
}
type Join<T, K> = K extends null
? { [R in keyof T]: T[R] }
: { [R in keyof T]: T[R] } & { [R in keyof K]: K[R] }
/** @public */
export type TLUiEventData<K> = K extends null
? { source: TLUiEventSource }
: { source: TLUiEventSource } & K
/** @public */
export type TLUiEventHandler<T extends keyof TLUiEventMap = keyof TLUiEventMap> = (
name: T,
data: Join<{ source: TLUiEventSource }, TLUiEventMap[T]>
data: TLUiEventData<TLUiEventMap[T]>
) => void
/** @internal */

View file

@ -1,11 +1,11 @@
import { Editor, objectMapEntries } from '@tldraw/editor'
import { useMemo } from 'react'
import { PORTRAIT_BREAKPOINT } from './constants'
import { ActionsProviderProps } from './context/actions'
import { ActionsProviderProps, TLUiActionsContextType } from './context/actions'
import { useBreakpoint } from './context/breakpoints'
import { useDialogs } from './context/dialogs'
import { useToasts } from './context/toasts'
import { TLUiToolsProviderProps } from './hooks/useTools'
import { TLUiToolsContextType, TLUiToolsProviderProps } from './hooks/useTools'
import { TLUiTranslationProviderProps, useTranslation } from './hooks/useTranslation/useTranslation'
/** @public */
@ -41,19 +41,21 @@ export function useDefaultHelpers() {
)
}
type DefaultHelpers = ReturnType<typeof useDefaultHelpers>
export type TLUiOverride<Type, Helpers> = (editor: Editor, schema: Type, helpers: Helpers) => Type
type WithDefaultHelpers<T extends TLUiOverride<any, any>> =
T extends TLUiOverride<infer Type, infer Helpers>
? TLUiOverride<Type, Helpers extends undefined ? DefaultHelpers : Helpers & DefaultHelpers>
: never
/** @public */
export type TLUiOverrideHelpers = ReturnType<typeof useDefaultHelpers>
/** @public */
export type TLUiOverrides = Partial<{
actions: WithDefaultHelpers<NonNullable<ActionsProviderProps['overrides']>>
tools: WithDefaultHelpers<NonNullable<TLUiToolsProviderProps['overrides']>>
actions: (
editor: Editor,
actions: TLUiActionsContextType,
helpers: TLUiOverrideHelpers
) => TLUiActionsContextType
tools: (
editor: Editor,
tools: TLUiToolsContextType,
helpers: { insertMedia: () => void } & TLUiOverrideHelpers
) => TLUiToolsContextType
translations: TLUiTranslationProviderProps['overrides']
}>
@ -65,7 +67,7 @@ export type TLUiOverridesWithoutDefaults = Partial<{
export function mergeOverrides(
overrides: TLUiOverrides[],
defaultHelpers: DefaultHelpers
defaultHelpers: TLUiOverrideHelpers
): TLUiOverridesWithoutDefaults {
const mergedTranslations: TLUiTranslationProviderProps['overrides'] = {}
for (const override of overrides) {

View file

@ -1,7 +1,8 @@
import { MediaHelpers, assertExists } from '@tldraw/editor'
import { clampToBrowserMaxCanvasSize } from '../../shapes/shared/getBrowserCanvasMaxSize'
interface BoxWidthHeight {
/** @public */
export interface BoxWidthHeight {
w: number
h: number
}

View file

@ -31,7 +31,8 @@ import { getArrowBindings } from '../../shapes/arrow/shared'
const TLDRAW_V1_VERSION = 15.5
/** @internal */
export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocument) {
export function buildFromV1Document(editor: Editor, _document: unknown) {
let document = _document as TLV1Document
editor.batch(() => {
document = migrate(document, TLDRAW_V1_VERSION)
// Cancel any interactions / states
@ -56,7 +57,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
Object.values(document.assets ?? {}).forEach((v1Asset) => {
switch (v1Asset.type) {
case TDAssetType.Image: {
case TLV1AssetType.Image: {
const assetId: TLAssetId = AssetRecordType.createId()
v1AssetIdsToV2AssetIds.set(v1Asset.id, assetId)
const placeholderAsset: TLAsset = {
@ -77,7 +78,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
tryMigrateAsset(editor, placeholderAsset)
break
}
case TDAssetType.Video:
case TLV1AssetType.Video:
{
const assetId: TLAssetId = AssetRecordType.createId()
v1AssetIdsToV2AssetIds.set(v1Asset.id, assetId)
@ -133,14 +134,14 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
// Groups only
v1Shapes.forEach((v1Shape) => {
if (v1Shape.type !== TDShapeType.Group) return
if (v1Shape.type !== TLV1ShapeType.Group) return
const shapeId = createShapeId()
v1ShapeIdsToV2ShapeIds.set(v1Shape.id, shapeId)
v1GroupShapeIdsToV1ChildIds.set(v1Shape.id, [])
})
function decideNotToCreateShape(v1Shape: TDShape) {
function decideNotToCreateShape(v1Shape: TLV1Shape) {
v1ShapeIdsToV2ShapeIds.delete(v1Shape.id)
const v1GroupParent = v1GroupShapeIdsToV1ChildIds.has(v1Shape.parentId)
if (v1GroupParent) {
@ -154,7 +155,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
// Non-groups only
v1Shapes.forEach((v1Shape) => {
// Skip groups for now, we'll create groups via the app's API
if (v1Shape.type === TDShapeType.Group) {
if (v1Shape.type === TLV1ShapeType.Group) {
return
}
@ -183,7 +184,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
}
switch (v1Shape.type) {
case TDShapeType.Sticky: {
case TLV1ShapeType.Sticky: {
editor.createShapes<TLNoteShape>([
{
...inCommon,
@ -199,7 +200,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
])
break
}
case TDShapeType.Rectangle: {
case TLV1ShapeType.Rectangle: {
editor.createShapes<TLGeoShape>([
{
...inCommon,
@ -255,7 +256,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
}
break
}
case TDShapeType.Triangle: {
case TLV1ShapeType.Triangle: {
editor.createShapes<TLGeoShape>([
{
...inCommon,
@ -310,7 +311,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
}
break
}
case TDShapeType.Ellipse: {
case TLV1ShapeType.Ellipse: {
editor.createShapes<TLGeoShape>([
{
...inCommon,
@ -366,7 +367,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
break
}
case TDShapeType.Draw: {
case TLV1ShapeType.Draw: {
if (v1Shape.points.length === 0) {
decideNotToCreateShape(v1Shape)
break
@ -389,7 +390,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
])
break
}
case TDShapeType.Arrow: {
case TLV1ShapeType.Arrow: {
const v1Bend = coerceNumber(v1Shape.bend)
const v1Start = getV2Point(v1Shape.handles.start.point)
const v1End = getV2Point(v1Shape.handles.end.point)
@ -425,7 +426,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
break
}
case TDShapeType.Text: {
case TLV1ShapeType.Text: {
editor.createShapes<TLTextShape>([
{
...inCommon,
@ -442,7 +443,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
])
break
}
case TDShapeType.Image: {
case TLV1ShapeType.Image: {
const assetId = v1AssetIdsToV2AssetIds.get(v1Shape.assetId)
if (!assetId) {
@ -463,7 +464,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
])
break
}
case TDShapeType.Video: {
case TLV1ShapeType.Video: {
const assetId = v1AssetIdsToV2AssetIds.get(v1Shape.assetId)
if (!assetId) {
@ -512,7 +513,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
// Bind arrows to shapes
v1Shapes.forEach((v1Shape) => {
if (v1Shape.type !== TDShapeType.Arrow) {
if (v1Shape.type !== TLV1ShapeType.Arrow) {
return
}
@ -651,7 +652,7 @@ async function tryMigrateAsset(editor: Editor, placeholderAsset: TLAsset) {
}
}
function migrate(document: LegacyTldrawDocument, newVersion: number): LegacyTldrawDocument {
function migrate(document: TLV1Document, newVersion: number): TLV1Document {
const { version = 0 } = document
if (!document.assets) {
@ -675,7 +676,7 @@ function migrate(document: LegacyTldrawDocument, newVersion: number): LegacyTldr
shape.parentId = page.id
}
if (shape.type === TDShapeType.Group && children) {
if (shape.type === TLV1ShapeType.Group && children) {
children.forEach((childId) => {
if (!page.shapes[childId]) {
console.warn('Encountered a parent with a missing child!', shape.id, childId)
@ -698,10 +699,10 @@ function migrate(document: LegacyTldrawDocument, newVersion: number): LegacyTldr
if (version < 14) {
Object.values(document.pages).forEach((page) => {
Object.values(page.shapes)
.filter((shape) => shape.type === TDShapeType.Text)
.filter((shape) => shape.type === TLV1ShapeType.Text)
.forEach((shape) => {
if ((shape as TextShape).style.font === undefined) {
;(shape as TextShape).style.font === FontStyle.Script
if ((shape as TLV1TextShape).style.font === undefined) {
;(shape as TLV1TextShape).style.font === TLV1FontStyle.Script
}
})
})
@ -722,13 +723,13 @@ function migrate(document: LegacyTldrawDocument, newVersion: number): LegacyTldr
}
})
if (shape.type === TDShapeType.Arrow) {
if (shape.type === TLV1ShapeType.Arrow) {
if (shape.decorations) {
Object.entries(shape.decorations).forEach(([id, decoration]) => {
if ((decoration as unknown) === 'Arrow') {
shape.decorations = {
...shape.decorations,
[id]: Decoration.Arrow,
[id]: TLV1Decoration.Arrow,
}
}
})
@ -751,7 +752,7 @@ function migrate(document: LegacyTldrawDocument, newVersion: number): LegacyTldr
Object.values(page.shapes).forEach((shape) => {
if (version < 15.2) {
if (
(shape.type === TDShapeType.Image || shape.type === TDShapeType.Video) &&
(shape.type === TLV1ShapeType.Image || shape.type === TLV1ShapeType.Video) &&
shape.style.isFilled == null
) {
shape.style.isFilled = true
@ -760,10 +761,10 @@ function migrate(document: LegacyTldrawDocument, newVersion: number): LegacyTldr
if (version < 15.3) {
if (
shape.type === TDShapeType.Rectangle ||
shape.type === TDShapeType.Triangle ||
shape.type === TDShapeType.Ellipse ||
shape.type === TDShapeType.Arrow
shape.type === TLV1ShapeType.Rectangle ||
shape.type === TLV1ShapeType.Triangle ||
shape.type === TLV1ShapeType.Ellipse ||
shape.type === TLV1ShapeType.Arrow
) {
if ('text' in shape && typeof shape.text === 'string') {
shape.label = shape.text
@ -798,37 +799,24 @@ function migrate(document: LegacyTldrawDocument, newVersion: number): LegacyTldr
/* -------------------- TLV1 Types -------------------- */
interface TLV1Handle {
/** @internal */
export interface TLV1Handle {
id: string
index: number
point: number[]
canBind?: boolean
bindingId?: string
}
interface TLV1Binding {
/** @internal */
export interface TLV1BaseBinding {
id: string
toId: string
fromId: string
}
interface TLV1Shape {
id: string
type: string
parentId: string
childIndex: number
name: string
point: number[]
assetId?: string
rotation?: number
children?: string[]
handles?: Record<string, TLV1Handle>
isGhost?: boolean
isHidden?: boolean
isLocked?: boolean
isGenerated?: boolean
isAspectRatioLocked?: boolean
}
enum TDShapeType {
/** @internal */
export enum TLV1ShapeType {
Sticky = 'sticky',
Ellipse = 'ellipse',
Rectangle = 'rectangle',
@ -841,7 +829,8 @@ enum TDShapeType {
Video = 'video',
}
enum ColorStyle {
/** @internal */
export enum TLV1ColorStyle {
White = 'white',
LightGray = 'lightGray',
Gray = 'gray',
@ -856,121 +845,144 @@ enum ColorStyle {
Yellow = 'yellow',
}
enum SizeStyle {
/** @internal */
export enum TLV1SizeStyle {
Small = 'small',
Medium = 'medium',
Large = 'large',
}
enum DashStyle {
/** @internal */
export enum TLV1DashStyle {
Draw = 'draw',
Solid = 'solid',
Dashed = 'dashed',
Dotted = 'dotted',
}
enum AlignStyle {
/** @internal */
export enum TLV1AlignStyle {
Start = 'start',
Middle = 'middle',
End = 'end',
Justify = 'justify',
}
enum FontStyle {
/** @internal */
export enum TLV1FontStyle {
Script = 'script',
Sans = 'sans',
Serif = 'serif',
Mono = 'mono',
}
interface ShapeStyles {
color: ColorStyle
size: SizeStyle
dash: DashStyle
font?: FontStyle
textAlign?: AlignStyle
/** @internal */
export interface TLV1ShapeStyles {
color: TLV1ColorStyle
size: TLV1SizeStyle
dash: TLV1DashStyle
font?: TLV1FontStyle
textAlign?: TLV1AlignStyle
isFilled?: boolean
scale?: number
}
interface TDBaseShape extends TLV1Shape {
style: ShapeStyles
type: TDShapeType
/** @internal */
export interface TLV1BaseShape {
id: string
parentId: string
childIndex: number
name: string
point: number[]
assetId?: string
rotation?: number
children?: string[]
isGhost?: boolean
isHidden?: boolean
isLocked?: boolean
isGenerated?: boolean
isAspectRatioLocked?: boolean
style: TLV1ShapeStyles
type: TLV1ShapeType
label?: string
handles?: Record<string, TDHandle>
handles?: Record<string, TLV1Handle>
}
interface DrawShape extends TDBaseShape {
type: TDShapeType.Draw
/** @internal */
export interface TLV1DrawShape extends TLV1BaseShape {
type: TLV1ShapeType.Draw
points: number[][]
isComplete: boolean
}
// The extended handle (used for arrows)
interface TDHandle extends TLV1Handle {
canBind?: boolean
bindingId?: string
}
interface RectangleShape extends TDBaseShape {
type: TDShapeType.Rectangle
/** @internal */
export interface TLV1RectangleShape extends TLV1BaseShape {
type: TLV1ShapeType.Rectangle
size: number[]
label?: string
labelPoint?: number[]
}
interface EllipseShape extends TDBaseShape {
type: TDShapeType.Ellipse
/** @internal */
export interface TLV1EllipseShape extends TLV1BaseShape {
type: TLV1ShapeType.Ellipse
radius: number[]
label?: string
labelPoint?: number[]
}
interface TriangleShape extends TDBaseShape {
type: TDShapeType.Triangle
/** @internal */
export interface TLV1TriangleShape extends TLV1BaseShape {
type: TLV1ShapeType.Triangle
size: number[]
label?: string
labelPoint?: number[]
}
enum Decoration {
/** @internal */
export enum TLV1Decoration {
Arrow = 'arrow',
}
// The shape created with the arrow tool
interface ArrowShape extends TDBaseShape {
type: TDShapeType.Arrow
/** @internal */
export interface TLV1ArrowShape extends TLV1BaseShape {
type: TLV1ShapeType.Arrow
bend: number
handles: {
start: TDHandle
bend: TDHandle
end: TDHandle
start: TLV1Handle
bend: TLV1Handle
end: TLV1Handle
}
decorations?: {
start?: Decoration
end?: Decoration
middle?: Decoration
start?: TLV1Decoration
end?: TLV1Decoration
middle?: TLV1Decoration
}
label?: string
labelPoint?: number[]
}
interface ArrowBinding extends TLV1Binding {
handleId: keyof ArrowShape['handles']
/** @internal */
export interface TLV1ArrowBinding extends TLV1BaseBinding {
handleId: keyof TLV1ArrowShape['handles']
distance: number
point: number[]
}
type TDBinding = ArrowBinding
/** @internal */
export type TLV1Binding = TLV1ArrowBinding
interface ImageShape extends TDBaseShape {
type: TDShapeType.Image
/** @internal */
export interface TLV1ImageShape extends TLV1BaseShape {
type: TLV1ShapeType.Image
size: number[]
assetId: string
}
interface VideoShape extends TDBaseShape {
type: TDShapeType.Video
/** @internal */
export interface TLV1VideoShape extends TLV1BaseShape {
type: TLV1ShapeType.Video
size: number[]
assetId: string
isPlaying: boolean
@ -978,46 +990,52 @@ interface VideoShape extends TDBaseShape {
}
// The shape created by the text tool
interface TextShape extends TDBaseShape {
type: TDShapeType.Text
/** @internal */
export interface TLV1TextShape extends TLV1BaseShape {
type: TLV1ShapeType.Text
text: string
}
// The shape created by the sticky tool
interface StickyShape extends TDBaseShape {
type: TDShapeType.Sticky
/** @internal */
export interface TLV1StickyShape extends TLV1BaseShape {
type: TLV1ShapeType.Sticky
size: number[]
text: string
}
// The shape created when multiple shapes are grouped
interface GroupShape extends TDBaseShape {
type: TDShapeType.Group
/** @internal */
export interface TLV1GroupShape extends TLV1BaseShape {
type: TLV1ShapeType.Group
size: number[]
children: string[]
}
type TDShape =
| RectangleShape
| EllipseShape
| TriangleShape
| DrawShape
| ArrowShape
| TextShape
| GroupShape
| StickyShape
| ImageShape
| VideoShape
/** @internal */
export type TLV1Shape =
| TLV1RectangleShape
| TLV1EllipseShape
| TLV1TriangleShape
| TLV1DrawShape
| TLV1ArrowShape
| TLV1TextShape
| TLV1GroupShape
| TLV1StickyShape
| TLV1ImageShape
| TLV1VideoShape
interface TDPage {
/** @internal */
export interface TLV1Page {
id: string
name?: string
childIndex?: number
shapes: Record<string, TDShape>
bindings: Record<string, TDBinding>
shapes: Record<string, TLV1Shape>
bindings: Record<string, TLV1Binding>
}
interface TLV1Bounds {
/** @internal */
export interface TLV1Bounds {
minX: number
minY: number
maxX: number
@ -1027,7 +1045,8 @@ interface TLV1Bounds {
rotation?: number
}
interface TLV1PageState {
/** @internal */
export interface TLV1PageState {
id: string
selectedIds: string[]
camera: {
@ -1041,126 +1060,129 @@ interface TLV1PageState {
bindingId?: string | null
}
enum TDAssetType {
/** @internal */
export enum TLV1AssetType {
Image = 'image',
Video = 'video',
}
interface TDImageAsset extends TLV1Asset {
type: TDAssetType.Image
/** @internal */
export interface TLV1ImageAsset extends TLV1BaseAsset {
type: TLV1AssetType.Image
fileName: string
src: string
size: number[]
}
interface TDVideoAsset extends TLV1Asset {
type: TDAssetType.Video
/** @internal */
export interface TLV1VideoAsset extends TLV1BaseAsset {
type: TLV1AssetType.Video
fileName: string
src: string
size: number[]
}
interface TLV1Asset {
/** @internal */
export interface TLV1BaseAsset {
id: string
type: string
}
type TDAsset = TDImageAsset | TDVideoAsset
type TDAssets = Record<string, TDAsset>
/** @internal */
export type TLV1Asset = TLV1ImageAsset | TLV1VideoAsset
/** @internal */
export interface LegacyTldrawDocument {
export interface TLV1Document {
id: string
name: string
version: number
pages: Record<string, TDPage>
pages: Record<string, TLV1Page>
pageStates: Record<string, TLV1PageState>
assets: TDAssets
assets: Record<string, TLV1Asset>
}
/* ------------------ Translations ------------------ */
const v1ColorsToV2Colors: Record<ColorStyle, TLDefaultColorStyle> = {
[ColorStyle.White]: 'black',
[ColorStyle.Black]: 'black',
[ColorStyle.LightGray]: 'grey',
[ColorStyle.Gray]: 'grey',
[ColorStyle.Green]: 'light-green',
[ColorStyle.Cyan]: 'green',
[ColorStyle.Blue]: 'light-blue',
[ColorStyle.Indigo]: 'blue',
[ColorStyle.Orange]: 'orange',
[ColorStyle.Yellow]: 'yellow',
[ColorStyle.Red]: 'red',
[ColorStyle.Violet]: 'light-violet',
const v1ColorsToV2Colors: Record<TLV1ColorStyle, TLDefaultColorStyle> = {
[TLV1ColorStyle.White]: 'black',
[TLV1ColorStyle.Black]: 'black',
[TLV1ColorStyle.LightGray]: 'grey',
[TLV1ColorStyle.Gray]: 'grey',
[TLV1ColorStyle.Green]: 'light-green',
[TLV1ColorStyle.Cyan]: 'green',
[TLV1ColorStyle.Blue]: 'light-blue',
[TLV1ColorStyle.Indigo]: 'blue',
[TLV1ColorStyle.Orange]: 'orange',
[TLV1ColorStyle.Yellow]: 'yellow',
[TLV1ColorStyle.Red]: 'red',
[TLV1ColorStyle.Violet]: 'light-violet',
}
const v1FontsToV2Fonts: Record<FontStyle, TLDefaultFontStyle> = {
[FontStyle.Mono]: 'mono',
[FontStyle.Sans]: 'sans',
[FontStyle.Script]: 'draw',
[FontStyle.Serif]: 'serif',
const v1FontsToV2Fonts: Record<TLV1FontStyle, TLDefaultFontStyle> = {
[TLV1FontStyle.Mono]: 'mono',
[TLV1FontStyle.Sans]: 'sans',
[TLV1FontStyle.Script]: 'draw',
[TLV1FontStyle.Serif]: 'serif',
}
const v1AlignsToV2Aligns: Record<AlignStyle, TLDefaultHorizontalAlignStyle> = {
[AlignStyle.Start]: 'start',
[AlignStyle.Middle]: 'middle',
[AlignStyle.End]: 'end',
[AlignStyle.Justify]: 'start',
const v1AlignsToV2Aligns: Record<TLV1AlignStyle, TLDefaultHorizontalAlignStyle> = {
[TLV1AlignStyle.Start]: 'start',
[TLV1AlignStyle.Middle]: 'middle',
[TLV1AlignStyle.End]: 'end',
[TLV1AlignStyle.Justify]: 'start',
}
const v1TextAlignsToV2TextAligns: Record<AlignStyle, TLDefaultTextAlignStyle> = {
[AlignStyle.Start]: 'start',
[AlignStyle.Middle]: 'middle',
[AlignStyle.End]: 'end',
[AlignStyle.Justify]: 'start',
const v1TextAlignsToV2TextAligns: Record<TLV1AlignStyle, TLDefaultTextAlignStyle> = {
[TLV1AlignStyle.Start]: 'start',
[TLV1AlignStyle.Middle]: 'middle',
[TLV1AlignStyle.End]: 'end',
[TLV1AlignStyle.Justify]: 'start',
}
const v1TextSizesToV2TextSizes: Record<SizeStyle, TLDefaultSizeStyle> = {
[SizeStyle.Small]: 's',
[SizeStyle.Medium]: 'l',
[SizeStyle.Large]: 'xl',
const v1TextSizesToV2TextSizes: Record<TLV1SizeStyle, TLDefaultSizeStyle> = {
[TLV1SizeStyle.Small]: 's',
[TLV1SizeStyle.Medium]: 'l',
[TLV1SizeStyle.Large]: 'xl',
}
const v1SizesToV2Sizes: Record<SizeStyle, TLDefaultSizeStyle> = {
[SizeStyle.Small]: 'm',
[SizeStyle.Medium]: 'l',
[SizeStyle.Large]: 'xl',
const v1SizesToV2Sizes: Record<TLV1SizeStyle, TLDefaultSizeStyle> = {
[TLV1SizeStyle.Small]: 'm',
[TLV1SizeStyle.Medium]: 'l',
[TLV1SizeStyle.Large]: 'xl',
}
const v1DashesToV2Dashes: Record<DashStyle, TLDefaultDashStyle> = {
[DashStyle.Solid]: 'solid',
[DashStyle.Dashed]: 'dashed',
[DashStyle.Dotted]: 'dotted',
[DashStyle.Draw]: 'draw',
const v1DashesToV2Dashes: Record<TLV1DashStyle, TLDefaultDashStyle> = {
[TLV1DashStyle.Solid]: 'solid',
[TLV1DashStyle.Dashed]: 'dashed',
[TLV1DashStyle.Dotted]: 'dotted',
[TLV1DashStyle.Draw]: 'draw',
}
function getV2Color(color: ColorStyle | undefined): TLDefaultColorStyle {
function getV2Color(color: TLV1ColorStyle | undefined): TLDefaultColorStyle {
return color ? v1ColorsToV2Colors[color] ?? 'black' : 'black'
}
function getV2Font(font: FontStyle | undefined): TLDefaultFontStyle {
function getV2Font(font: TLV1FontStyle | undefined): TLDefaultFontStyle {
return font ? v1FontsToV2Fonts[font] ?? 'draw' : 'draw'
}
function getV2Align(align: AlignStyle | undefined): TLDefaultHorizontalAlignStyle {
function getV2Align(align: TLV1AlignStyle | undefined): TLDefaultHorizontalAlignStyle {
return align ? v1AlignsToV2Aligns[align] ?? 'middle' : 'middle'
}
function getV2TextAlign(align: AlignStyle | undefined): TLDefaultTextAlignStyle {
function getV2TextAlign(align: TLV1AlignStyle | undefined): TLDefaultTextAlignStyle {
return align ? v1TextAlignsToV2TextAligns[align] ?? 'middle' : 'middle'
}
function getV2TextSize(size: SizeStyle | undefined): TLDefaultSizeStyle {
function getV2TextSize(size: TLV1SizeStyle | undefined): TLDefaultSizeStyle {
return size ? v1TextSizesToV2TextSizes[size] ?? 'm' : 'm'
}
function getV2Size(size: SizeStyle | undefined): TLDefaultSizeStyle {
function getV2Size(size: TLV1SizeStyle | undefined): TLDefaultSizeStyle {
return size ? v1SizesToV2Sizes[size] ?? 'l' : 'l'
}
function getV2Dash(dash: DashStyle | undefined): TLDefaultDashStyle {
function getV2Dash(dash: TLV1DashStyle | undefined): TLDefaultDashStyle {
return dash ? v1DashesToV2Dashes[dash] ?? 'draw' : 'draw'
}
@ -1172,13 +1194,13 @@ function getV2Point(point: number[]): VecModel {
}
}
function getV2Arrowhead(decoration: Decoration | undefined): TLArrowShapeArrowheadStyle {
return decoration === Decoration.Arrow ? 'arrow' : 'none'
function getV2Arrowhead(decoration: TLV1Decoration | undefined): TLArrowShapeArrowheadStyle {
return decoration === TLV1Decoration.Arrow ? 'arrow' : 'none'
}
function getV2Fill(isFilled: boolean | undefined, color: ColorStyle) {
function getV2Fill(isFilled: boolean | undefined, color: TLV1ColorStyle) {
return isFilled
? color === ColorStyle.Black || color === ColorStyle.White
? color === TLV1ColorStyle.Black || color === TLV1ColorStyle.White
? 'semi'
: 'solid'
: 'none'

View file

@ -19,6 +19,7 @@ import { StandaloneDependsOn } from '@tldraw/store';
import { Store } from '@tldraw/store';
import { StoreSchema } from '@tldraw/store';
import { StoreSnapshot } from '@tldraw/store';
import { StoreValidator } from '@tldraw/store';
import { T } from '@tldraw/validate';
import { UnknownRecord } from '@tldraw/store';
@ -102,13 +103,25 @@ export const CameraRecordType: RecordType<TLCamera, never>;
export const canvasUiColorTypeValidator: T.Validator<"accent" | "black" | "laser" | "muted-1" | "selection-fill" | "selection-stroke" | "white">;
// @public
export function createAssetValidator<Type extends string, Props extends JsonObject>(type: Type, props: T.Validator<Props>): T.ObjectValidator<{ [P in "id" | "meta" | "typeName" | (undefined extends Props ? never : "props") | (undefined extends Type ? never : "type")]: {
export function createAssetValidator<Type extends string, Props extends JsonObject>(type: Type, props: T.Validator<Props>): T.ObjectValidator<{ [P in T.ExtractRequiredKeys<{
id: TLAssetId;
meta: JsonObject;
props: Props;
type: Type;
typeName: 'asset';
}[P]; } & { [P_1 in (undefined extends Props ? "props" : never) | (undefined extends Type ? "type" : never)]?: {
}>]: {
id: TLAssetId;
meta: JsonObject;
props: Props;
type: Type;
typeName: 'asset';
}[P]; } & { [P_1 in T.ExtractOptionalKeys<{
id: TLAssetId;
meta: JsonObject;
props: Props;
type: Type;
typeName: 'asset';
}>]?: {
id: TLAssetId;
meta: JsonObject;
props: Props;
@ -132,7 +145,7 @@ export function createBindingValidator<Type extends string, Props extends JsonOb
[K in keyof Props]: T.Validatable<Props[K]>;
}, meta?: {
[K in keyof Meta]: T.Validatable<Meta[K]>;
}): T.ObjectValidator<{ [P in "fromId" | "id" | "meta" | "toId" | "typeName" | (undefined extends Props ? never : "props") | (undefined extends Type ? never : "type")]: TLBaseBinding<Type, Props>[P]; } & { [P_1 in (undefined extends Props ? "props" : never) | (undefined extends Type ? "type" : never)]?: TLBaseBinding<Type, Props>[P_1] | undefined; }>;
}): T.ObjectValidator<{ [P in T.ExtractRequiredKeys<TLBaseBinding<Type, Props>>]: TLBaseBinding<Type, Props>[P]; } & { [P_1 in T.ExtractOptionalKeys<TLBaseBinding<Type, Props>>]?: TLBaseBinding<Type, Props>[P_1] | undefined; }>;
// @public
export const createPresenceStateDerivation: ($user: Signal<{
@ -157,7 +170,7 @@ export function createShapeValidator<Type extends string, Props extends JsonObje
[K in keyof Props]: T.Validatable<Props[K]>;
}, meta?: {
[K in keyof Meta]: T.Validatable<Meta[K]>;
}): T.ObjectValidator<{ [P in "id" | "index" | "isLocked" | "meta" | "opacity" | "parentId" | "rotation" | "typeName" | "x" | "y" | (undefined extends Props ? never : "props") | (undefined extends Type ? never : "type")]: TLBaseShape<Type, Props>[P]; } & { [P_1 in (undefined extends Props ? "props" : never) | (undefined extends Type ? "type" : never)]?: TLBaseShape<Type, Props>[P_1] | undefined; }>;
}): T.ObjectValidator<{ [P in T.ExtractRequiredKeys<TLBaseShape<Type, Props>>]: TLBaseShape<Type, Props>[P]; } & { [P_1 in T.ExtractOptionalKeys<TLBaseShape<Type, Props>>]?: TLBaseShape<Type, Props>[P_1] | undefined; }>;
// @public
export function createTLSchema({ shapes, bindings, migrations, }?: {
@ -166,6 +179,9 @@ export function createTLSchema({ shapes, bindings, migrations, }?: {
shapes?: Record<string, SchemaPropsInfo>;
}): TLSchema;
// @public (undocumented)
export const defaultColorNames: readonly ["black", "grey", "light-violet", "violet", "blue", "light-blue", "yellow", "orange", "green", "light-green", "light-red", "red", "white"];
// @public (undocumented)
export const DefaultColorStyle: EnumStyleProp<"black" | "blue" | "green" | "grey" | "light-blue" | "light-green" | "light-red" | "light-violet" | "orange" | "red" | "violet" | "white" | "yellow">;
@ -223,10 +239,7 @@ export const drawShapeProps: {
isClosed: T.Validator<boolean>;
isComplete: T.Validator<boolean>;
isPen: T.Validator<boolean>;
segments: T.ArrayOfValidator<{
points: VecModel[];
type: "free" | "straight";
} & {}>;
segments: T.ArrayOfValidator<TLDrawShapeSegment>;
size: EnumStyleProp<"l" | "m" | "s" | "xl">;
};
@ -560,16 +573,19 @@ export const highlightShapeProps: {
color: EnumStyleProp<"black" | "blue" | "green" | "grey" | "light-blue" | "light-green" | "light-red" | "light-violet" | "orange" | "red" | "violet" | "white" | "yellow">;
isComplete: T.Validator<boolean>;
isPen: T.Validator<boolean>;
segments: T.ArrayOfValidator<{
points: VecModel[];
type: "free" | "straight";
} & {}>;
segments: T.ArrayOfValidator<TLDrawShapeSegment>;
size: EnumStyleProp<"l" | "m" | "s" | "xl">;
};
// @public (undocumented)
export function idValidator<Id extends RecordId<UnknownRecord>>(prefix: Id['__type__']['typeName']): T.Validator<Id>;
// @public (undocumented)
export const ImageShapeCrop: T.ObjectValidator<{
bottomRight: VecModel;
topLeft: VecModel;
} & {}>;
// @public (undocumented)
export const imageShapeMigrations: TLPropsMigrations;
@ -796,16 +812,19 @@ export const rootShapeMigrations: MigrationSequence;
// @public (undocumented)
export interface SchemaPropsInfo {
// (undocumented)
meta?: Record<string, AnyValidator>;
meta?: Record<string, StoreValidator<any>>;
// (undocumented)
migrations?: LegacyMigrations | MigrationSequence | TLPropsMigrations;
// (undocumented)
props?: Record<string, AnyValidator>;
props?: Record<string, StoreValidator<any>>;
}
// @public (undocumented)
export const scribbleValidator: T.Validator<TLScribble>;
// @public (undocumented)
export type SetValue<T extends Set<any>> = T extends Set<infer U> ? U : never;
// @public (undocumented)
export const shapeIdValidator: T.Validator<TLShapeId>;
@ -854,6 +873,15 @@ export const textShapeProps: {
// @public
export const TL_CANVAS_UI_COLOR_TYPES: Set<"accent" | "black" | "laser" | "muted-1" | "selection-fill" | "selection-stroke" | "white">;
// @public
export const TL_CURSOR_TYPES: Set<string>;
// @public
export const TL_HANDLE_TYPES: Set<"clone" | "create" | "vertex" | "virtual">;
// @public
export const TL_SCRIBBLE_STATES: Set<"active" | "paused" | "starting" | "stopping">;
// @public (undocumented)
export type TLArrowBinding = TLBaseBinding<'arrow', TLArrowBindingProps>;
@ -985,6 +1013,9 @@ export type TLBookmarkAsset = TLBaseAsset<'bookmark', {
// @public (undocumented)
export type TLBookmarkShape = TLBaseShape<'bookmark', TLBookmarkShapeProps>;
// @public (undocumented)
export type TLBookmarkShapeProps = RecordPropsType<typeof bookmarkShapeProps>;
// @public
export interface TLCamera extends BaseRecord<'camera', TLCameraId> {
// (undocumented)
@ -1026,7 +1057,7 @@ export type TLDefaultColorTheme = Expand<{
id: 'dark' | 'light';
solid: string;
text: string;
} & Record<(typeof colors)[number], TLDefaultColorThemeColor>>;
} & Record<(typeof defaultColorNames)[number], TLDefaultColorThemeColor>>;
// @public (undocumented)
export interface TLDefaultColorThemeColor {
@ -1089,7 +1120,15 @@ export const TLDOCUMENT_ID: RecordId<TLDocument>;
export type TLDrawShape = TLBaseShape<'draw', TLDrawShapeProps>;
// @public (undocumented)
export type TLDrawShapeSegment = T.TypeOf<typeof DrawShapeSegment>;
export type TLDrawShapeProps = RecordPropsType<typeof drawShapeProps>;
// @public (undocumented)
export interface TLDrawShapeSegment {
// (undocumented)
points: VecModel[];
// (undocumented)
type: 'free' | 'straight';
}
// @public (undocumented)
export type TLEmbedShape = TLBaseShape<'embed', TLEmbedShapeProps>;
@ -1099,15 +1138,29 @@ export type TLEmbedShapePermissions = {
[K in keyof typeof embedShapePermissionDefaults]?: boolean;
};
// @public (undocumented)
export type TLEmbedShapeProps = RecordPropsType<typeof embedShapeProps>;
// @public (undocumented)
export type TLFrameShape = TLBaseShape<'frame', TLFrameShapeProps>;
// @public (undocumented)
export type TLFrameShapeProps = RecordPropsType<typeof frameShapeProps>;
// @public (undocumented)
export type TLGeoShape = TLBaseShape<'geo', TLGeoShapeProps>;
// @public (undocumented)
export type TLGeoShapeProps = RecordPropsType<typeof geoShapeProps>;
// @public (undocumented)
export type TLGroupShape = TLBaseShape<'group', TLGroupShapeProps>;
// @public (undocumented)
export type TLGroupShapeProps = {
[key in never]: undefined;
};
// @public
export interface TLHandle {
// (undocumented)
@ -1129,6 +1182,9 @@ export type TLHandleType = SetValue<typeof TL_HANDLE_TYPES>;
// @public (undocumented)
export type TLHighlightShape = TLBaseShape<'highlight', TLHighlightShapeProps>;
// @public (undocumented)
export type TLHighlightShapeProps = RecordPropsType<typeof highlightShapeProps>;
// @public
export type TLImageAsset = TLBaseAsset<'image', {
h: number;
@ -1240,6 +1296,9 @@ export interface TLInstancePageState extends BaseRecord<'instance_page_state', T
selectedShapeIds: TLShapeId[];
}
// @public (undocumented)
export type TLInstancePageStateId = RecordId<TLInstancePageState>;
// @public (undocumented)
export interface TLInstancePresence extends BaseRecord<'instance_presence', TLInstancePresenceID> {
// (undocumented)
@ -1281,15 +1340,24 @@ export interface TLInstancePresence extends BaseRecord<'instance_presence', TLIn
userName: string;
}
// @public (undocumented)
export type TLInstancePresenceID = RecordId<TLInstancePresence>;
// @public (undocumented)
export type TLLanguage = (typeof LANGUAGES)[number];
// @public (undocumented)
export type TLLineShape = TLBaseShape<'line', TLLineShapeProps>;
// @public (undocumented)
export type TLLineShapeProps = RecordPropsType<typeof lineShapeProps>;
// @public (undocumented)
export type TLNoteShape = TLBaseShape<'note', TLNoteShapeProps>;
// @public (undocumented)
export type TLNoteShapeProps = RecordPropsType<typeof noteShapeProps>;
// @public (undocumented)
export type TLOpacityType = number;
@ -1309,15 +1377,29 @@ export type TLPageId = RecordId<TLPage>;
// @public (undocumented)
export type TLParentId = TLPageId | TLShapeId;
// @public
export interface TLPointer extends BaseRecord<'pointer', TLPointerId> {
// (undocumented)
lastActivityTimestamp: number;
// (undocumented)
meta: JsonObject;
// (undocumented)
x: number;
// (undocumented)
y: number;
}
// @public (undocumented)
export const TLPOINTER_ID: TLPointerId;
// @public (undocumented)
export type TLPointerId = RecordId<TLPointer>;
// @public (undocumented)
export interface TLPropsMigration {
// (undocumented)
readonly dependsOn?: MigrationId[];
// (undocumented)
readonly down?: ((props: any) => any) | typeof NO_DOWN_MIGRATION | typeof RETIRED_DOWN_MIGRATION;
readonly down?: 'none' | 'retired' | ((props: any) => any);
// (undocumented)
readonly id: MigrationId;
// (undocumented)
@ -1415,6 +1497,9 @@ export type TLVideoAsset = TLBaseAsset<'video', {
// @public (undocumented)
export type TLVideoShape = TLBaseShape<'video', TLVideoShapeProps>;
// @public (undocumented)
export type TLVideoShapeProps = RecordPropsType<typeof videoShapeProps>;
// @public
export interface VecModel {
// (undocumented)

View file

@ -1,4 +1,4 @@
import { LegacyMigrations, MigrationSequence, StoreSchema } from '@tldraw/store'
import { LegacyMigrations, MigrationSequence, StoreSchema, StoreValidator } from '@tldraw/store'
import { objectMapValues } from '@tldraw/utils'
import { TLStoreProps, createIntegrityChecker, onValidationFailure } from './TLStore'
import { bookmarkAssetMigrations } from './assets/TLBookmarkAsset'
@ -39,16 +39,11 @@ import { videoShapeMigrations, videoShapeProps } from './shapes/TLVideoShape'
import { storeMigrations } from './store-migrations'
import { StyleProp } from './styles/StyleProp'
interface AnyValidator {
validate: (prop: any) => any
validateUsingKnownGoodVersion?: (prevVersion: any, newVersion: any) => any
}
/** @public */
export interface SchemaPropsInfo {
migrations?: LegacyMigrations | TLPropsMigrations | MigrationSequence
props?: Record<string, AnyValidator>
meta?: Record<string, AnyValidator>
props?: Record<string, StoreValidator<any>>
meta?: Record<string, StoreValidator<any>>
}
/** @public */

View file

@ -32,10 +32,10 @@ export {
canvasUiColorTypeValidator,
type TLCanvasUiColor,
} from './misc/TLColor'
export { type TLCursor, type TLCursorType } from './misc/TLCursor'
export { type TLHandle, type TLHandleType } from './misc/TLHandle'
export { TL_CURSOR_TYPES, type TLCursor, type TLCursorType } from './misc/TLCursor'
export { TL_HANDLE_TYPES, type TLHandle, type TLHandleType } from './misc/TLHandle'
export { opacityValidator, type TLOpacityType } from './misc/TLOpacity'
export { scribbleValidator, type TLScribble } from './misc/TLScribble'
export { TL_SCRIBBLE_STATES, scribbleValidator, type TLScribble } from './misc/TLScribble'
export {
boxModelValidator,
vecModelValidator,
@ -81,9 +81,22 @@ export {
type TLPage,
type TLPageId,
} from './records/TLPage'
export { InstancePageStateRecordType, type TLInstancePageState } from './records/TLPageState'
export { PointerRecordType, TLPOINTER_ID } from './records/TLPointer'
export { InstancePresenceRecordType, type TLInstancePresence } from './records/TLPresence'
export {
InstancePageStateRecordType,
type TLInstancePageState,
type TLInstancePageStateId,
} from './records/TLPageState'
export {
PointerRecordType,
TLPOINTER_ID,
type TLPointer,
type TLPointerId,
} from './records/TLPointer'
export {
InstancePresenceRecordType,
type TLInstancePresence,
type TLInstancePresenceID,
} from './records/TLPresence'
export { type TLRecord } from './records/TLRecord'
export {
createShapeId,
@ -125,11 +138,13 @@ export {
bookmarkShapeMigrations,
bookmarkShapeProps,
type TLBookmarkShape,
type TLBookmarkShapeProps,
} from './shapes/TLBookmarkShape'
export {
drawShapeMigrations,
drawShapeProps,
type TLDrawShape,
type TLDrawShapeProps,
type TLDrawShapeSegment,
} from './shapes/TLDrawShape'
export {
@ -140,21 +155,35 @@ export {
type EmbedDefinition,
type TLEmbedShape,
type TLEmbedShapePermissions,
type TLEmbedShapeProps,
} from './shapes/TLEmbedShape'
export { frameShapeMigrations, frameShapeProps, type TLFrameShape } from './shapes/TLFrameShape'
export {
frameShapeMigrations,
frameShapeProps,
type TLFrameShape,
type TLFrameShapeProps,
} from './shapes/TLFrameShape'
export {
GeoShapeGeoStyle,
geoShapeMigrations,
geoShapeProps,
type TLGeoShape,
type TLGeoShapeProps,
} from './shapes/TLGeoShape'
export { groupShapeMigrations, groupShapeProps, type TLGroupShape } from './shapes/TLGroupShape'
export {
groupShapeMigrations,
groupShapeProps,
type TLGroupShape,
type TLGroupShapeProps,
} from './shapes/TLGroupShape'
export {
highlightShapeMigrations,
highlightShapeProps,
type TLHighlightShape,
type TLHighlightShapeProps,
} from './shapes/TLHighlightShape'
export {
ImageShapeCrop,
imageShapeMigrations,
imageShapeProps,
type TLImageShape,
@ -166,19 +195,31 @@ export {
lineShapeMigrations,
lineShapeProps,
type TLLineShape,
type TLLineShapeProps,
} from './shapes/TLLineShape'
export { noteShapeMigrations, noteShapeProps, type TLNoteShape } from './shapes/TLNoteShape'
export {
noteShapeMigrations,
noteShapeProps,
type TLNoteShape,
type TLNoteShapeProps,
} from './shapes/TLNoteShape'
export {
textShapeMigrations,
textShapeProps,
type TLTextShape,
type TLTextShapeProps,
} from './shapes/TLTextShape'
export { videoShapeMigrations, videoShapeProps, type TLVideoShape } from './shapes/TLVideoShape'
export {
videoShapeMigrations,
videoShapeProps,
type TLVideoShape,
type TLVideoShapeProps,
} from './shapes/TLVideoShape'
export { EnumStyleProp, StyleProp, type StylePropValue } from './styles/StyleProp'
export {
DefaultColorStyle,
DefaultColorThemePalette,
defaultColorNames,
getDefaultColorTheme,
type TLDefaultColorStyle,
type TLDefaultColorTheme,
@ -206,3 +247,4 @@ export {
getDefaultTranslationLocale,
type TLLanguage,
} from './translations/translations'
export { type SetValue } from './util-types'

View file

@ -21,17 +21,6 @@ export type RecordPropsType<Config extends Record<string, T.Validatable<any>>> =
[K in keyof Config]: T.TypeOf<Config[K]>
}>
export const NO_DOWN_MIGRATION = 'none' as const
/**
* If a down migration was deployed more than a couple of months ago it should be safe to retire it.
* We only really need them to smooth over the transition between versions, and some folks do keep
* browser tabs open for months without refreshing, but at a certain point that kind of behavior is
* on them. Plus anyway recently chrome has started to actually kill tabs that are open for too long
* rather than just suspending them, so if other browsers follow suit maybe it's less of a concern.
*/
export const RETIRED_DOWN_MIGRATION = 'retired' as const
/**
* @public
*/
@ -39,7 +28,16 @@ export interface TLPropsMigration {
readonly id: MigrationId
readonly dependsOn?: MigrationId[]
readonly up: (props: any) => any
readonly down?: typeof NO_DOWN_MIGRATION | typeof RETIRED_DOWN_MIGRATION | ((props: any) => any)
/**
* If a down migration was deployed more than a couple of months ago it should be safe to retire it.
* We only really need them to smooth over the transition between versions, and some folks do keep
* browser tabs open for months without refreshing, but at a certain point that kind of behavior is
* on them. Plus anyway recently chrome has started to actually kill tabs that are open for too long
* rather than just suspending them, so if other browsers follow suit maybe it's less of a concern.
*
* @public
*/
readonly down?: 'none' | 'retired' | ((props: any) => any)
}
/**

View file

@ -4,12 +4,7 @@ import { TLArrowBinding } from '../bindings/TLArrowBinding'
import { VecModel, vecModelValidator } from '../misc/geometry-types'
import { createBindingId } from '../records/TLBinding'
import { TLShapeId, createShapePropsMigrationIds } from '../records/TLShape'
import {
RETIRED_DOWN_MIGRATION,
RecordPropsType,
TLPropsMigration,
createPropsMigration,
} from '../recordsWithProps'
import { RecordPropsType, TLPropsMigration, createPropsMigration } from '../recordsWithProps'
import { StyleProp } from '../styles/StyleProp'
import { DefaultColorStyle, DefaultLabelColorStyle } from '../styles/TLColorStyle'
import { DefaultDashStyle } from '../styles/TLDashStyle'
@ -88,7 +83,7 @@ export const arrowShapeMigrations = createMigrationSequence({
up: (props) => {
props.labelColor = 'black'
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
}),
propsMigration({

View file

@ -1,7 +1,7 @@
import { T } from '@tldraw/validate'
import { assetIdValidator } from '../assets/TLBaseAsset'
import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'
import { RETIRED_DOWN_MIGRATION, RecordPropsType } from '../recordsWithProps'
import { RecordPropsType } from '../recordsWithProps'
import { TLBaseShape } from './TLBaseShape'
/** @public */
@ -35,7 +35,7 @@ export const bookmarkShapeMigrations = createShapePropsMigrationSequence({
props.assetId = null
}
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: Versions.MakeUrlsValid,

View file

@ -1,21 +1,24 @@
import { T } from '@tldraw/validate'
import { vecModelValidator } from '../misc/geometry-types'
import { VecModel, vecModelValidator } from '../misc/geometry-types'
import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'
import { RETIRED_DOWN_MIGRATION, RecordPropsType } from '../recordsWithProps'
import { RecordPropsType } from '../recordsWithProps'
import { DefaultColorStyle } from '../styles/TLColorStyle'
import { DefaultDashStyle } from '../styles/TLDashStyle'
import { DefaultFillStyle } from '../styles/TLFillStyle'
import { DefaultSizeStyle } from '../styles/TLSizeStyle'
import { TLBaseShape } from './TLBaseShape'
export const DrawShapeSegment = T.object({
/** @public */
export interface TLDrawShapeSegment {
type: 'free' | 'straight'
points: VecModel[]
}
export const DrawShapeSegment: T.Validator<TLDrawShapeSegment> = T.object<TLDrawShapeSegment>({
type: T.literalEnum('free', 'straight'),
points: T.arrayOf(vecModelValidator),
})
/** @public */
export type TLDrawShapeSegment = T.TypeOf<typeof DrawShapeSegment>
/** @public */
export const drawShapeProps = {
color: DefaultColorStyle,
@ -66,7 +69,7 @@ export const drawShapeMigrations = createShapePropsMigrationSequence({
}
props.isPen = isPen
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
],
})

View file

@ -1,6 +1,6 @@
import { T } from '@tldraw/validate'
import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'
import { RETIRED_DOWN_MIGRATION, RecordPropsType } from '../recordsWithProps'
import { RecordPropsType } from '../recordsWithProps'
import { TLBaseShape } from './TLBaseShape'
// Only allow multiplayer embeds. If we add additional routes later for example '/help' this won't match
@ -694,28 +694,28 @@ export const embedShapeMigrations = createShapePropsMigrationSequence({
props.tmpOldUrl = props.url
}
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: Versions.RemoveDoesResize,
up: (props) => {
delete props.doesResize
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: Versions.RemoveTmpOldUrl,
up: (props) => {
delete props.tmpOldUrl
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: Versions.RemovePermissionOverrides,
up: (props) => {
delete props.overridePermissions
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
],
})

View file

@ -10,7 +10,8 @@ export const frameShapeProps = {
name: T.string,
}
type TLFrameShapeProps = RecordPropsType<typeof frameShapeProps>
/** @public */
export type TLFrameShapeProps = RecordPropsType<typeof frameShapeProps>
/** @public */
export type TLFrameShape = TLBaseShape<'frame', TLFrameShapeProps>

View file

@ -1,6 +1,6 @@
import { T } from '@tldraw/validate'
import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'
import { RETIRED_DOWN_MIGRATION, RecordPropsType } from '../recordsWithProps'
import { RecordPropsType } from '../recordsWithProps'
import { StyleProp } from '../styles/StyleProp'
import { DefaultColorStyle, DefaultLabelColorStyle } from '../styles/TLColorStyle'
import { DefaultDashStyle } from '../styles/TLDashStyle'
@ -89,14 +89,14 @@ export const geoShapeMigrations = createShapePropsMigrationSequence({
up: (props) => {
props.url = ''
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: geoShapeVersions.AddLabelColor,
up: (props) => {
props.labelColor = 'black'
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: geoShapeVersions.RemoveJustify,
@ -105,21 +105,21 @@ export const geoShapeMigrations = createShapePropsMigrationSequence({
props.align = 'start'
}
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: geoShapeVersions.AddCheckBox,
up: (_props) => {
// noop
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: geoShapeVersions.AddVerticalAlign,
up: (props) => {
props.verticalAlign = 'middle'
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: geoShapeVersions.MigrateLegacyAlign,
@ -138,14 +138,14 @@ export const geoShapeMigrations = createShapePropsMigrationSequence({
}
props.align = newAlign
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: geoShapeVersions.AddCloud,
up: (_props) => {
// noop
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: geoShapeVersions.MakeUrlsValid,

View file

@ -2,7 +2,7 @@ import { T } from '@tldraw/validate'
import { assetIdValidator } from '../assets/TLBaseAsset'
import { vecModelValidator } from '../misc/geometry-types'
import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'
import { RETIRED_DOWN_MIGRATION, RecordPropsType } from '../recordsWithProps'
import { RecordPropsType } from '../recordsWithProps'
import { TLBaseShape } from './TLBaseShape'
/** @public */
@ -45,7 +45,7 @@ export const imageShapeMigrations = createShapePropsMigrationSequence({
up: (props) => {
props.url = ''
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: Versions.AddCropProp,

View file

@ -1,7 +1,7 @@
import { IndexKey, getIndices, objectMapFromEntries, sortByIndex } from '@tldraw/utils'
import { T } from '@tldraw/validate'
import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'
import { RETIRED_DOWN_MIGRATION, RecordPropsType } from '../recordsWithProps'
import { RecordPropsType } from '../recordsWithProps'
import { StyleProp } from '../styles/StyleProp'
import { DefaultColorStyle } from '../styles/TLColorStyle'
import { DefaultDashStyle } from '../styles/TLDashStyle'
@ -57,7 +57,7 @@ export const lineShapeMigrations = createShapePropsMigrationSequence({
;(handle as any).canSnap = true
}
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: lineShapeVersions.RemoveExtraHandleProps,

View file

@ -1,6 +1,6 @@
import { T } from '@tldraw/validate'
import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'
import { RETIRED_DOWN_MIGRATION, RecordPropsType } from '../recordsWithProps'
import { RecordPropsType } from '../recordsWithProps'
import { DefaultColorStyle } from '../styles/TLColorStyle'
import { DefaultFontStyle } from '../styles/TLFontStyle'
import { DefaultHorizontalAlignStyle } from '../styles/TLHorizontalAlignStyle'
@ -46,7 +46,7 @@ export const noteShapeMigrations = createShapePropsMigrationSequence({
up: (props) => {
props.url = ''
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: Versions.RemoveJustify,
@ -55,7 +55,7 @@ export const noteShapeMigrations = createShapePropsMigrationSequence({
props.align = 'start'
}
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: Versions.MigrateLegacyAlign,
@ -72,14 +72,14 @@ export const noteShapeMigrations = createShapePropsMigrationSequence({
return
}
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: Versions.AddVerticalAlign,
up: (props) => {
props.verticalAlign = 'middle'
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: Versions.MakeUrlsValid,

View file

@ -1,6 +1,6 @@
import { T } from '@tldraw/validate'
import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'
import { RETIRED_DOWN_MIGRATION, RecordPropsType } from '../recordsWithProps'
import { RecordPropsType } from '../recordsWithProps'
import { DefaultColorStyle } from '../styles/TLColorStyle'
import { DefaultFontStyle } from '../styles/TLFontStyle'
import { DefaultSizeStyle } from '../styles/TLSizeStyle'
@ -42,7 +42,7 @@ export const textShapeMigrations = createShapePropsMigrationSequence({
props.align = 'start'
}
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: Versions.AddTextAlign,

View file

@ -1,7 +1,7 @@
import { T } from '@tldraw/validate'
import { assetIdValidator } from '../assets/TLBaseAsset'
import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'
import { RETIRED_DOWN_MIGRATION, RecordPropsType } from '../recordsWithProps'
import { RecordPropsType } from '../recordsWithProps'
import { TLBaseShape } from './TLBaseShape'
/** @public */
@ -35,7 +35,7 @@ export const videoShapeMigrations = createShapePropsMigrationSequence({
up: (props) => {
props.url = ''
},
down: RETIRED_DOWN_MIGRATION,
down: 'retired',
},
{
id: Versions.MakeUrlsValid,

View file

@ -2,7 +2,8 @@ import { Expand } from '@tldraw/utils'
import { T } from '@tldraw/validate'
import { StyleProp } from './StyleProp'
const colors = [
/** @public */
export const defaultColorNames = [
'black',
'grey',
'light-violet',
@ -40,7 +41,7 @@ export type TLDefaultColorTheme = Expand<
text: string
background: string
solid: string
} & Record<(typeof colors)[number], TLDefaultColorThemeColor>
} & Record<(typeof defaultColorNames)[number], TLDefaultColorThemeColor>
>
/** @public */
@ -409,13 +410,13 @@ export function getDefaultColorTheme(opts: { isDarkMode: boolean }): TLDefaultCo
/** @public */
export const DefaultColorStyle = StyleProp.defineEnum('tldraw:color', {
defaultValue: 'black',
values: colors,
values: defaultColorNames,
})
/** @public */
export const DefaultLabelColorStyle = StyleProp.defineEnum('tldraw:labelColor', {
defaultValue: 'black',
values: colors,
values: defaultColorNames,
})
/** @public */

View file

@ -11,7 +11,7 @@ export function annotateError(error: unknown, annotations: Partial<ErrorAnnotati
export function areArraysShallowEqual<T>(arr1: readonly T[], arr2: readonly T[]): boolean;
// @internal (undocumented)
export function areObjectsShallowEqual<T extends Record<string, unknown>>(obj1: T, obj2: T): boolean;
export function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean;
// @internal (undocumented)
export const assert: (value: unknown, message?: string) => asserts value;
@ -52,6 +52,14 @@ export function deleteFromLocalStorage(key: string): void;
// @internal
export function deleteFromSessionStorage(key: string): void;
// @public (undocumented)
export interface ErrorAnnotations {
// (undocumented)
extras: Record<string, unknown>;
// (undocumented)
tags: Record<string, bigint | boolean | null | number | string | symbol | undefined>;
}
// @public (undocumented)
export interface ErrorResult<E> {
// (undocumented)
@ -228,7 +236,7 @@ export function minBy<T>(arr: readonly T[], fn: (item: T) => number): T | undefi
export function modulate(value: number, rangeA: number[], rangeB: number[], clamp?: boolean): number;
// @internal
export function noop(): void;
export const noop: () => void;
// @internal
export function objectMapEntries<Key extends string, Value>(object: {
@ -316,7 +324,9 @@ export type RecursivePartial<T> = {
};
// @internal (undocumented)
type Required_2<T, K extends keyof T> = Expand<Omit<T, K> & _Required<Pick<T, K>>>;
type Required_2<T, K extends keyof T> = Expand<Omit<T, K> & {
[P in K]-?: T[P];
}>;
export { Required_2 as Required }
// @public (undocumented)

View file

@ -19,7 +19,7 @@ export {
type OkResult,
} from './lib/control'
export { debounce } from './lib/debounce'
export { annotateError, getErrorAnnotations } from './lib/error'
export { annotateError, getErrorAnnotations, type ErrorAnnotations } from './lib/error'
export { FileHelpers } from './lib/file'
export { noop, omitFromStackTrace, throttle } from './lib/function'
export { getHashForBuffer, getHashForObject, getHashForString, lns } from './lib/hash'

View file

@ -1,4 +1,5 @@
interface ErrorAnnotations {
/** @public */
export interface ErrorAnnotations {
tags: Record<string, number | string | boolean | bigint | symbol | null | undefined>
extras: Record<string, unknown>
}

View file

@ -58,4 +58,4 @@ export function omitFromStackTrace<Args extends Array<unknown>, Return>(
* @internal
*/
// eslint-disable-next-line @typescript-eslint/no-empty-function
export function noop(): void {}
export const noop: () => void = () => {}

View file

@ -105,17 +105,14 @@ export function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(
}
/** @internal */
export function areObjectsShallowEqual<T extends Record<string, unknown>>(
obj1: T,
obj2: T
): boolean {
export function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {
if (obj1 === obj2) return true
const keys1 = new Set(Object.keys(obj1))
const keys2 = new Set(Object.keys(obj2))
if (keys1.size !== keys2.size) return false
for (const key of keys1) {
if (!keys2.has(key)) return false
if (!Object.is(obj1[key], obj2[key])) return false
if (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false
}
return true
}

View file

@ -6,7 +6,5 @@ export type RecursivePartial<T> = {
/** @public */
export type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
type _Required<T> = { [K in keyof T]-?: T[K] }
/** @internal */
export type Required<T, K extends keyof T> = Expand<Omit<T, K> & _Required<Pick<T, K>>>
export type Required<T, K extends keyof T> = Expand<Omit<T, K> & { [P in K]-?: T[P] }>

View file

@ -45,6 +45,16 @@ export class DictValidator<Key extends string, Value> extends Validator<Record<K
readonly valueValidator: Validatable<Value>;
}
// @public (undocumented)
export type ExtractOptionalKeys<T extends object> = {
[K in keyof T]: undefined extends T[K] ? K : never;
}[keyof T];
// @public (undocumented)
export type ExtractRequiredKeys<T extends object> = {
[K in keyof T]: undefined extends T[K] ? never : K;
}[keyof T];
// @public
const indexKey: Validator<IndexKey>;
@ -151,6 +161,7 @@ declare namespace T {
Validator,
ArrayOfValidator,
ObjectValidator,
UnionValidatorConfig,
UnionValidator,
DictValidator,
unknown,
@ -166,6 +177,8 @@ declare namespace T {
bigint,
array,
unknownObject,
ExtractRequiredKeys,
ExtractOptionalKeys,
jsonValue,
linkUrl,
srcUrl,
@ -187,6 +200,15 @@ export class UnionValidator<Key extends string, Config extends UnionValidatorCon
validateUnknownVariants<Unknown>(unknownValueValidation: (value: object, variant: string) => Unknown): UnionValidator<Key, Config, Unknown>;
}
// @public (undocumented)
export type UnionValidatorConfig<Key extends string, Config> = {
readonly [Variant in keyof Config]: Validatable<any> & {
validate: (input: any) => {
readonly [K in Key]: Variant;
};
};
};
// @public
const unknown: Validator<unknown>;

View file

@ -6,5 +6,8 @@ export {
ObjectValidator,
UnionValidator,
Validator,
type ExtractOptionalKeys,
type ExtractRequiredKeys,
type UnionValidatorConfig,
} from './lib/validation'
export { T }

View file

@ -380,7 +380,8 @@ export class ObjectValidator<Shape extends object> extends Validator<Shape> {
}
// pass this into itself e.g. Config extends UnionObjectSchemaConfig<Key, Config>
type UnionValidatorConfig<Key extends string, Config> = {
/** @public */
export type UnionValidatorConfig<Key extends string, Config> = {
readonly [Variant in keyof Config]: Validatable<any> & {
validate: (input: any) => { readonly [K in Key]: Variant }
}
@ -677,11 +678,13 @@ export const unknownObject = new Validator<Record<string, unknown>>((value) => {
return value as Record<string, unknown>
})
type ExtractRequiredKeys<T extends object> = {
/** @public */
export type ExtractRequiredKeys<T extends object> = {
[K in keyof T]: undefined extends T[K] ? never : K
}[keyof T]
type ExtractOptionalKeys<T extends object> = {
/** @public */
export type ExtractOptionalKeys<T extends object> = {
[K in keyof T]: undefined extends T[K] ? K : never
}[keyof T]