tldraw/packages/editor/api-report.md

2827 lines
95 KiB
Markdown
Raw Normal View History

2023-04-25 11:01:25 +00:00
## API Report File for "@tldraw/editor"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
/// <reference types="react" />
import { Atom } from '@tldraw/state';
import { atom } from '@tldraw/state';
2023-04-25 11:01:25 +00:00
import { Box2d } from '@tldraw/primitives';
import { Box2dModel } from '@tldraw/tlschema';
import { Computed } from '@tldraw/state';
import { computed } from '@tldraw/state';
import { ComputedCache } from '@tldraw/store';
2023-04-25 11:01:25 +00:00
import { CubicSpline2d } from '@tldraw/primitives';
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
import { defineMigrations } from '@tldraw/store';
2023-04-25 11:01:25 +00:00
import { EASINGS } from '@tldraw/primitives';
import { EmbedDefinition } from '@tldraw/tlschema';
import { EventEmitter } from 'eventemitter3';
import { getHashForString } from '@tldraw/utils';
import { HistoryEntry } from '@tldraw/store';
2023-04-25 11:01:25 +00:00
import { MatLike } from '@tldraw/primitives';
import { Matrix2d } from '@tldraw/primitives';
import { Matrix2dModel } from '@tldraw/primitives';
import { Migrations } from '@tldraw/store';
2023-04-25 11:01:25 +00:00
import { Polyline2d } from '@tldraw/primitives';
import { react } from '@tldraw/state';
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
import { default as React_2 } from 'react';
import * as React_3 from 'react';
import { RecursivePartial } from '@tldraw/utils';
2023-04-25 11:01:25 +00:00
import { RotateCorner } from '@tldraw/primitives';
import { SelectionCorner } from '@tldraw/primitives';
import { SelectionEdge } from '@tldraw/primitives';
import { SelectionHandle } from '@tldraw/primitives';
import { SerializedSchema } from '@tldraw/store';
import { ShapeProps } from '@tldraw/tlschema';
import { Signal } from '@tldraw/state';
import { StoreSchema } from '@tldraw/store';
import { StoreSnapshot } from '@tldraw/store';
2023-04-25 11:01:25 +00:00
import { StrokePoint } from '@tldraw/primitives';
import { StyleProp } from '@tldraw/tlschema';
2023-04-25 11:01:25 +00:00
import { TLArrowShape } from '@tldraw/tlschema';
import { TLArrowShapeArrowheadStyle } from '@tldraw/tlschema';
2023-04-25 11:01:25 +00:00
import { TLAsset } from '@tldraw/tlschema';
import { TLAssetId } from '@tldraw/tlschema';
import { TLAssetPartial } from '@tldraw/tlschema';
import { TLBaseShape } from '@tldraw/tlschema';
import { TLBookmarkAsset } from '@tldraw/tlschema';
import { TLBookmarkShape } from '@tldraw/tlschema';
import { TLCamera } from '@tldraw/tlschema';
import { TLCursor } from '@tldraw/tlschema';
import { TLDefaultHorizontalAlignStyle } from '@tldraw/tlschema';
2023-04-25 11:01:25 +00:00
import { TLDocument } from '@tldraw/tlschema';
import { TLDrawShape } from '@tldraw/tlschema';
import { TLEmbedShape } from '@tldraw/tlschema';
import { TLFrameShape } from '@tldraw/tlschema';
import { TLGeoShape } from '@tldraw/tlschema';
import { TLGroupShape } from '@tldraw/tlschema';
import { TLHandle } from '@tldraw/tlschema';
import { TLHighlightShape } from '@tldraw/tlschema';
2023-04-25 11:01:25 +00:00
import { TLImageAsset } from '@tldraw/tlschema';
import { TLImageShape } from '@tldraw/tlschema';
import { TLInstance } from '@tldraw/tlschema';
import { TLInstancePageState } from '@tldraw/tlschema';
derived presence state (#1204) This PR adds - A new `TLInstancePresence` record type, to collect info about the presence state in a particular instance of the editor. This will eventually be used to sync presence data instead of sending instance-only state across the wire. - **Record Scopes** `RecordType` now has a `scope` property which can be one of three things: - `document`: the record belongs to the document and should be synced and persisted freely. Currently: `TLDocument`, `TLPage`, `TLShape`, and `TLAsset` - `instance`: the record belongs to a single instance of the store and should not be synced at all. It should not be persisted directly in most cases, but rather compiled into a kind of 'instance configuration' to store alongside the local document data so that when reopening the associated document it can remember some of the previous instance state. Currently: `TLInstance`, `TLInstancePageState`, `TLCamera`, `TLUser`, `TLUserDocument`, `TLUserPresence` - `presence`: the record belongs to a single instance of the store and should not be persisted, but may be synced using the special presence sync protocol. Currently just `TLInstancePresence` This sets us up for the following changes, which are gonna be pretty high-impact in terms of integrating tldraw into existing systems: - Removing `instanceId` as a config option. Each instance gets a randomly generated ID. - We'd replace it with an `instanceConfig` option that has stuff like selectedIds, camera positions, and so on. Then it's up to library users to get and reinstate the instance config at persistence boundaries. - Removing `userId` as config option, and removing the `TLUser` type altogether. - We might need to revisit when doing auth-enabled features like locking shapes, but I suspect that will be separate.
2023-04-27 18:03:19 +00:00
import { TLInstancePresence } from '@tldraw/tlschema';
2023-04-25 11:01:25 +00:00
import { TLLineShape } from '@tldraw/tlschema';
import { TLNoteShape } from '@tldraw/tlschema';
import { TLPage } from '@tldraw/tlschema';
import { TLPageId } from '@tldraw/tlschema';
import { TLParentId } from '@tldraw/tlschema';
import { TLRecord } from '@tldraw/tlschema';
import { TLScribble } from '@tldraw/tlschema';
import { TLShape } from '@tldraw/tlschema';
import { TLShapeId } from '@tldraw/tlschema';
import { TLShapePartial } from '@tldraw/tlschema';
import { TLStore } from '@tldraw/tlschema';
import { TLStoreProps } from '@tldraw/tlschema';
2023-04-25 11:01:25 +00:00
import { TLTextShape } from '@tldraw/tlschema';
import { TLUnknownShape } from '@tldraw/tlschema';
import { TLVideoAsset } from '@tldraw/tlschema';
import { TLVideoShape } from '@tldraw/tlschema';
import { track } from '@tldraw/state';
Independent instance state persistence (#1493) This PR - Removes UserDocumentRecordType - moving isSnapMode to user preferences - moving isGridMode and isPenMode to InstanceRecordType - deleting the other properties which are no longer needed. - Creates a separate pipeline for persisting instance state. Previously the instance state records were stored alongside the document state records, and in order to load the state for a particular instance (in our case, a particular tab) you needed to pass the 'instanceId' prop. This prop ended up totally pervading the public API and people ran into all kinds of issues with it, e.g. using the same instance id in multiple editor instances. There was also an issue whereby it was hard for us to clean up old instance state so the idb table ended up bloating over time. This PR makes it so that rather than passing an instanceId, you load the instance state yourself while creating the store. It provides tools to make that easy. - Undoes the assumption that we might have more than one instance's state in the store. - Like `document`, `instance` now has a singleton id `instance:instance`. - Page state ids and camera ids are no longer random, but rather derive from the page they belong to. This is like having a foreign primary key in SQL databases. It's something i'd love to support fully as part of the RecordType/Store api. Tests to do - [x] Test Migrations - [x] Test Store.listen filtering - [x] Make type sets in Store public and readonly - [x] Test RecordType.createId - [x] Test Instance state snapshot loading/exporting - [x] Manual test File I/O - [x] Manual test Vscode extension with multiple tabs - [x] Audit usages of store.query - [x] Audit usages of changed types: InstanceRecordType, 'instance', InstancePageStateRecordType, 'instance_page_state', 'user_document', 'camera', CameraRecordType, InstancePresenceRecordType, 'instance_presence' - [x] Test user preferences - [x] Manual test isSnapMode and isGridMode and isPenMode - [ ] Test indexedDb functions - [x] Add instanceId stuff back ### Change Type - [x] `major` — Breaking Change ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] Webdriver tests ### Release Notes - Add a brief release note for your PR here.
2023-06-05 14:11:07 +00:00
import { UnknownRecord } from '@tldraw/store';
import { useComputed } from '@tldraw/state';
import { useQuickReactor } from '@tldraw/state';
import { useReactor } from '@tldraw/state';
import { useValue } from '@tldraw/state';
2023-04-25 11:01:25 +00:00
import { Vec2d } from '@tldraw/primitives';
import { Vec2dModel } from '@tldraw/tlschema';
import { VecLike } from '@tldraw/primitives';
import { whyAmIRunning } from '@tldraw/state';
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export const ACCEPTED_ASSET_TYPE: string;
// @public (undocumented)
export const ACCEPTED_IMG_TYPE: string[];
// @public (undocumented)
export const ACCEPTED_VID_TYPE: string[];
// @internal (undocumented)
export const ANIMATION_MEDIUM_MS = 320;
// @internal (undocumented)
export const ANIMATION_SHORT_MS = 80;
// @public (undocumented)
export const ArrowShape: TLShapeInfo<TLArrowShape>;
// @public (undocumented)
export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
// (undocumented)
canBind: () => boolean;
// (undocumented)
canEdit: () => boolean;
// (undocumented)
canSnap: () => boolean;
// (undocumented)
component(shape: TLArrowShape): JSX.Element | null;
// (undocumented)
getArrowInfo(shape: TLArrowShape): ArrowInfo | undefined;
// (undocumented)
getBounds(shape: TLArrowShape): Box2d;
// (undocumented)
getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[];
// (undocumented)
getCenter(shape: TLArrowShape): Vec2d;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLArrowShape['props'];
// (undocumented)
getHandles(shape: TLArrowShape): TLHandle[];
// (undocumented)
getLabelBounds(shape: TLArrowShape): Box2d | null;
// (undocumented)
getOutline(shape: TLArrowShape): Vec2d[];
// (undocumented)
getOutlineWithoutLabel(shape: TLArrowShape): Vec2d[];
// (undocumented)
hideResizeHandles: TLShapeUtilFlag<TLArrowShape>;
// (undocumented)
hideRotateHandle: TLShapeUtilFlag<TLArrowShape>;
// (undocumented)
hideSelectionBoundsBg: TLShapeUtilFlag<TLArrowShape>;
// (undocumented)
hideSelectionBoundsFg: TLShapeUtilFlag<TLArrowShape>;
// (undocumented)
hitTestLineSegment(shape: TLArrowShape, A: VecLike, B: VecLike): boolean;
// (undocumented)
hitTestPoint(shape: TLArrowShape, point: VecLike): boolean;
// (undocumented)
indicator(shape: TLArrowShape): JSX.Element | null;
// (undocumented)
isClosed: () => boolean;
// (undocumented)
get labelBoundsCache(): ComputedCache<Box2d | null, TLArrowShape>;
// (undocumented)
onDoubleClickHandle: (shape: TLArrowShape, handle: TLHandle) => TLShapePartial<TLArrowShape> | void;
// (undocumented)
onEditEnd: TLOnEditEndHandler<TLArrowShape>;
// (undocumented)
onHandleChange: TLOnHandleChangeHandler<TLArrowShape>;
// (undocumented)
onResize: TLOnResizeHandler<TLArrowShape>;
// (undocumented)
onTranslateStart: TLOnTranslateStartHandler<TLArrowShape>;
// (undocumented)
snapPoints(_shape: TLArrowShape): Vec2d[];
// (undocumented)
toSvg(shape: TLArrowShape, ctx: SvgExportContext): SVGGElement;
// (undocumented)
static type: "arrow";
}
export { atom }
// @public (undocumented)
export abstract class BaseBoxShapeTool extends StateNode {
// (undocumented)
static children: () => (typeof Idle_4 | typeof Pointing_2)[];
// (undocumented)
static id: string;
// (undocumented)
static initial: string;
// (undocumented)
abstract shapeType: TLShapeUtilConstructor<any>;
}
// @public (undocumented)
export abstract class BaseBoxShapeUtil<Shape extends TLBaseBoxShape> extends ShapeUtil<Shape> {
// (undocumented)
getBounds(shape: Shape): Box2d;
// (undocumented)
getCenter(shape: Shape): Vec2d;
// (undocumented)
getOutline(shape: Shape): Vec2d[];
// (undocumented)
hitTestLineSegment(shape: Shape, A: VecLike, B: VecLike): boolean;
// (undocumented)
hitTestPoint(shape: Shape, point: VecLike): boolean;
// (undocumented)
onResize: TLOnResizeHandler<any>;
}
// @public (undocumented)
export function blobAsString(blob: Blob): Promise<string>;
// @public (undocumented)
export const BookmarkShape: TLShapeInfo<TLBookmarkShape>;
// @public (undocumented)
export class BookmarkShapeUtil extends BaseBoxShapeUtil<TLBookmarkShape> {
// (undocumented)
canResize: () => boolean;
// (undocumented)
component(shape: TLBookmarkShape): JSX.Element;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLBookmarkShape['props'];
// (undocumented)
hideSelectionBoundsBg: () => boolean;
// (undocumented)
hideSelectionBoundsFg: () => boolean;
// (undocumented)
indicator(shape: TLBookmarkShape): JSX.Element;
// (undocumented)
onBeforeCreate?: TLOnBeforeCreateHandler<TLBookmarkShape>;
// (undocumented)
onBeforeUpdate?: TLOnBeforeUpdateHandler<TLBookmarkShape>;
// (undocumented)
static type: "bookmark";
}
// @public (undocumented)
export const Canvas: React_2.MemoExoticComponent<() => JSX.Element>;
// @public (undocumented)
export const checkFlag: (flag: (() => boolean) | boolean | undefined) => boolean | undefined;
export { computed }
// @public
export function containBoxSize(originalSize: BoxWidthHeight, containBoxSize: BoxWidthHeight): BoxWidthHeight;
// @public (undocumented)
export const coreShapes: readonly [TLShapeInfo<TLGroupShape>, TLShapeInfo<TLEmbedShape>, TLShapeInfo<TLBookmarkShape>, TLShapeInfo<TLImageShape>, TLShapeInfo<TLTextShape>];
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function correctSpacesToNbsp(input: string): string;
Independent instance state persistence (#1493) This PR - Removes UserDocumentRecordType - moving isSnapMode to user preferences - moving isGridMode and isPenMode to InstanceRecordType - deleting the other properties which are no longer needed. - Creates a separate pipeline for persisting instance state. Previously the instance state records were stored alongside the document state records, and in order to load the state for a particular instance (in our case, a particular tab) you needed to pass the 'instanceId' prop. This prop ended up totally pervading the public API and people ran into all kinds of issues with it, e.g. using the same instance id in multiple editor instances. There was also an issue whereby it was hard for us to clean up old instance state so the idb table ended up bloating over time. This PR makes it so that rather than passing an instanceId, you load the instance state yourself while creating the store. It provides tools to make that easy. - Undoes the assumption that we might have more than one instance's state in the store. - Like `document`, `instance` now has a singleton id `instance:instance`. - Page state ids and camera ids are no longer random, but rather derive from the page they belong to. This is like having a foreign primary key in SQL databases. It's something i'd love to support fully as part of the RecordType/Store api. Tests to do - [x] Test Migrations - [x] Test Store.listen filtering - [x] Make type sets in Store public and readonly - [x] Test RecordType.createId - [x] Test Instance state snapshot loading/exporting - [x] Manual test File I/O - [x] Manual test Vscode extension with multiple tabs - [x] Audit usages of store.query - [x] Audit usages of changed types: InstanceRecordType, 'instance', InstancePageStateRecordType, 'instance_page_state', 'user_document', 'camera', CameraRecordType, InstancePresenceRecordType, 'instance_presence' - [x] Test user preferences - [x] Manual test isSnapMode and isGridMode and isPenMode - [ ] Test indexedDb functions - [x] Add instanceId stuff back ### Change Type - [x] `major` — Breaking Change ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] Webdriver tests ### Release Notes - Add a brief release note for your PR here.
2023-06-05 14:11:07 +00:00
// @public
export function createSessionStateSnapshotSignal(store: TLStore): Signal<null | TLSessionStateSnapshot>;
// @public
export function createTLStore({ initialData, defaultName, ...rest }: TLStoreOptions): TLStore;
// @public (undocumented)
export function createTLUser(opts?: {
derivePresenceState?: ((store: TLStore) => Signal<null | TLInstancePresence>) | undefined;
userPreferences?: Signal<TLUserPreferences, unknown> | undefined;
setUserPreferences?: ((userPreferences: TLUserPreferences) => void) | undefined;
}): TLUser;
// @public (undocumented)
export function dataTransferItemAsString(item: DataTransferItem): Promise<string>;
// @public (undocumented)
export function dataUrlToFile(url: string, filename: string, mimeType: string): Promise<File>;
// @internal (undocumented)
export type DebugFlag<T> = DebugFlagDef<T> & Atom<T>;
// @internal (undocumented)
export const debugFlags: {
preventDefaultLogging: DebugFlag<boolean>;
pointerCaptureLogging: DebugFlag<boolean>;
pointerCaptureTracking: DebugFlag<boolean>;
pointerCaptureTrackingObject: DebugFlag<Map<Element, number>>;
elementRemovalLogging: DebugFlag<boolean>;
debugSvg: DebugFlag<boolean>;
throwToBlob: DebugFlag<boolean>;
logMessages: DebugFlag<never[]>;
resetConnectionEveryPing: DebugFlag<boolean>;
debugCursors: DebugFlag<boolean>;
forceSrgb: DebugFlag<boolean>;
};
// @internal (undocumented)
export const DEFAULT_ANIMATION_OPTIONS: {
duration: number;
easing: (t: number) => number;
};
// @public (undocumented)
export let defaultEditorAssetUrls: TLEditorAssetUrls;
// @public (undocumented)
export function defaultEmptyAs(str: string, dflt: string): string;
// @internal (undocumented)
export const DefaultErrorFallback: TLErrorFallbackComponent;
// @public (undocumented)
export const defaultShapes: readonly [TLShapeInfo<TLDrawShape>, TLShapeInfo<TLGeoShape>, TLShapeInfo<TLLineShape>, TLShapeInfo<TLNoteShape>, TLShapeInfo<TLFrameShape>, TLShapeInfo<TLArrowShape>, TLShapeInfo<TLHighlightShape>, TLShapeInfo<TLVideoShape>];
// @public (undocumented)
export const defaultTools: TLStateNodeConstructor[];
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
export { defineMigrations }
// @public (undocumented)
export function defineShape<T extends TLUnknownShape>(type: T['type'], opts: Omit<TLShapeInfo<T>, 'type'>): TLShapeInfo<T>;
// @internal (undocumented)
export const DOUBLE_CLICK_DURATION = 450;
// @public (undocumented)
export function downloadDataURLAsFile(dataUrl: string, filename: string): void;
// @internal (undocumented)
export const DRAG_DISTANCE = 4;
// @public (undocumented)
export const DrawShape: TLShapeInfo<TLDrawShape>;
// @public (undocumented)
export class DrawShapeUtil extends ShapeUtil<TLDrawShape> {
// (undocumented)
component(shape: TLDrawShape): JSX.Element;
// (undocumented)
expandSelectionOutlinePx(shape: TLDrawShape): number;
// (undocumented)
getBounds(shape: TLDrawShape): Box2d;
// (undocumented)
getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[];
// (undocumented)
getCenter(shape: TLDrawShape): Vec2d;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLDrawShape['props'];
// (undocumented)
getOutline(shape: TLDrawShape): Vec2d[];
// (undocumented)
hideResizeHandles: (shape: TLDrawShape) => boolean;
// (undocumented)
hideRotateHandle: (shape: TLDrawShape) => boolean;
// (undocumented)
hideSelectionBoundsBg: (shape: TLDrawShape) => boolean;
// (undocumented)
hideSelectionBoundsFg: (shape: TLDrawShape) => boolean;
// (undocumented)
hitTestLineSegment(shape: TLDrawShape, A: VecLike, B: VecLike): boolean;
// (undocumented)
hitTestPoint(shape: TLDrawShape, point: VecLike): boolean;
// (undocumented)
indicator(shape: TLDrawShape): JSX.Element;
// (undocumented)
isClosed: (shape: TLDrawShape) => boolean;
// (undocumented)
onResize: TLOnResizeHandler<TLDrawShape>;
// (undocumented)
toSvg(shape: TLDrawShape, ctx: SvgExportContext): SVGGElement;
// (undocumented)
static type: "draw";
}
// @public (undocumented)
export class Editor extends EventEmitter<TLEventMap> {
constructor({ store, user, shapes, tools, getContainer }: TLEditorOptions);
addOpenMenu(id: string): this;
2023-04-25 11:01:25 +00:00
alignShapes(operation: 'bottom' | 'center-horizontal' | 'center-vertical' | 'left' | 'right' | 'top', ids?: TLShapeId[]): this;
get allShapesCommonBounds(): Box2d | null;
animateCamera(x: number, y: number, z?: number, opts?: TLAnimationOptions): this;
2023-04-25 11:01:25 +00:00
animateShapes(partials: (null | TLShapePartial | undefined)[], options?: {
duration?: number;
ease?: (t: number) => number;
}): this;
animateToShape(shapeId: TLShapeId, opts?: TLAnimationOptions): this;
animateToUser(userId: string): void;
get animationSpeed(): number;
2023-04-25 11:01:25 +00:00
// @internal (undocumented)
annotateError(error: unknown, { origin, willCrashApp, tags, extras, }: {
origin: string;
willCrashApp: boolean;
tags?: Record<string, boolean | number | string>;
extras?: Record<string, unknown>;
}): void;
get assets(): (TLBookmarkAsset | TLImageAsset | TLVideoAsset)[];
bail(): this;
bailToMark(id: string): this;
batch(fn: () => void): this;
blur(): this;
bringForward(ids?: TLShapeId[]): this;
bringToFront(ids?: TLShapeId[]): this;
get brush(): Box2dModel | null;
get camera(): TLCamera;
get cameraState(): "idle" | "moving";
2023-04-25 11:01:25 +00:00
cancel(): this;
cancelDoubleClick(): void;
get canMoveCamera(): boolean;
set canMoveCamera(canMove: boolean);
get canRedo(): boolean;
get canUndo(): boolean;
// @internal (undocumented)
capturedPointerId: null | number;
centerOnPoint(x: number, y: number, opts?: TLAnimationOptions): this;
2023-04-25 11:01:25 +00:00
// @internal
protected _clickManager: ClickManager;
complete(): this;
// @internal (undocumented)
crash(error: unknown): void;
// @internal
get crashingError(): unknown;
createAssets(assets: TLAsset[]): this;
// @internal (undocumented)
createErrorAnnotations(origin: string, willCrashApp: 'unknown' | boolean): {
tags: {
origin: string;
willCrashApp: 'unknown' | boolean;
};
extras: {
activeStateNode?: string;
selectedShapes?: TLUnknownShape[];
editingShape?: TLUnknownShape;
inputs?: Record<string, unknown>;
};
};
createPage(title: string, id?: TLPageId, belowPageIndex?: string): this;
createShapes<T extends TLUnknownShape>(partials: TLShapePartial<T>[], select?: boolean): this;
2023-04-25 11:01:25 +00:00
get croppingId(): null | TLShapeId;
get currentPage(): TLPage;
get currentPageId(): TLPageId;
get currentPageShapeIds(): Set<TLShapeId>;
2023-04-25 11:01:25 +00:00
get currentToolId(): string;
get cursor(): TLCursor;
deleteAssets(ids: TLAssetId[]): this;
deleteOpenMenu(id: string): this;
2023-04-25 11:01:25 +00:00
deletePage(id: TLPageId): void;
deleteShapes(ids?: TLShapeId[]): this;
deselect(...ids: TLShapeId[]): this;
get devicePixelRatio(): number;
dispatch(info: TLEventInfo): this;
2023-04-25 11:01:25 +00:00
readonly disposables: Set<() => void>;
dispose(): void;
distributeShapes(operation: 'horizontal' | 'vertical', ids?: TLShapeId[]): this;
get documentSettings(): TLDocument;
duplicatePage(id?: TLPageId, createId?: TLPageId): this;
2023-04-25 11:01:25 +00:00
duplicateShapes(ids?: TLShapeId[], offset?: VecLike): this;
get editingId(): null | TLShapeId;
// (undocumented)
get editingShape(): null | TLUnknownShape;
get erasingIds(): TLShapeId[];
get erasingIdsSet(): Set<TLShapeId>;
`ExternalContentManager` for handling external content (files, images, etc) (#1550) This PR improves the editor's APIs around creating assets and files. This allows end user developers to replace behavior that might occur, for example, when pasting images or dragging files onto the canvas. Here, we: - remove `onCreateAssetFromFile` prop - remove `onCreateBookmarkFromUrl` prop - introduce `onEditorReady` prop - introduce `onEditorWillDispose` prop - introduce `ExternalContentManager` The `ExternalContentManager` (ECM) is used in circumstances where we're turning external content (text, images, urls, etc) into assets or shapes. It is designed to allow certain methods to be overwritten by other developers as a kind of weakly supported hack. For example, when a user drags an image onto the canvas, the event handler passes a `TLExternalContent` object to the editor's `putExternalContent` method. This method runs the ECM's handler for this content type. That handler may in turn run other methods, such as `createAssetFromFile` or `createShapesForAssets`, which will lead to the image being created on the canvas. If a developer wanted to change the way that assets are created from files, then they could overwrite that method at runtime. ```ts const handleEditorReady = (editor: Editor) => { editor.externalContentManager.createAssetFromFile = myHandler } function Example() { return <Tldraw onEditorReady={handleEditorReady}/> } ``` If you wanted to go even deeper, you could override the editor's `putExternalContent` method. ```ts const handleEditorReady = (editor: Editor) => { const handleExternalContent = (info: TLExternalContent): Promise<void> => { if (info.type === 'files') { // do something here } else { // do the normal thing editor.externalContentManager.handleContent(info) } } ``` ### Change Type - [x] `major` ### Test Plan 1. Drag images, urls, etc. onto the canvas 2. Use copy and paste for single and multiple files 3. Use bookmark / embed shapes and convert between eachother ### Release Notes - [editor] add `ExternalContentManager` for plopping content onto the canvas - [editor] remove `onCreateAssetFromFile` prop - [editor] remove `onCreateBookmarkFromUrl` prop - [editor] introduce `onEditorReady` prop - [editor] introduce `onEditorWillDispose` prop - [editor] introduce `ExternalContentManager`
2023-06-08 14:53:11 +00:00
// (undocumented)
externalContentManager: PlopManager;
2023-04-25 11:01:25 +00:00
findAncestor(shape: TLShape, predicate: (parent: TLShape) => boolean): TLShape | undefined;
findCommonAncestor(shapes: TLShape[], predicate?: (shape: TLShape) => boolean): TLShapeId | undefined;
flipShapes(operation: 'horizontal' | 'vertical', ids?: TLShapeId[]): this;
focus(): this;
get focusLayerId(): TLPageId | TLShapeId;
get focusLayerShape(): TLShape | undefined;
getAncestorPageId(shape?: TLShape): TLPageId | undefined;
2023-04-25 11:01:25 +00:00
getAncestors(shape: TLShape, acc?: TLShape[]): TLShape[];
getAncestorsById(id: TLShapeId, acc?: TLShape[]): TLShape[];
getArrowsBoundTo(shapeId: TLShapeId): {
arrowId: TLShapeId;
handleId: "end" | "start";
}[];
getAssetById(id: TLAssetId): TLAsset | undefined;
getAssetBySrc(src: string): TLBookmarkAsset | TLImageAsset | TLVideoAsset | undefined;
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getBounds<T extends TLShape>(shape: T): Box2d;
getBoundsById<T extends TLShape>(id: T['id']): Box2d | undefined;
2023-04-25 11:01:25 +00:00
getClipPathById(id: TLShapeId): string | undefined;
getContainer: () => HTMLElement;
getContent(ids?: TLShapeId[]): TLContent | undefined;
2023-04-25 11:01:25 +00:00
getDeltaInParentSpace(shape: TLShape, delta: VecLike): Vec2d;
getDeltaInShapeSpace(shape: TLShape, delta: VecLike): Vec2d;
getDroppingShape(point: VecLike, droppingShapes?: TLShape[]): TLUnknownShape | undefined;
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getHandles<T extends TLShape>(shape: T): TLHandle[] | undefined;
getHandlesById<T extends TLShape>(id: T['id']): TLHandle[] | undefined;
2023-04-25 11:01:25 +00:00
getHighestIndexForParent(parentId: TLPageId | TLShapeId): string;
getMaskedPageBounds(shape: TLShape): Box2d | undefined;
getMaskedPageBoundsById(id: TLShapeId): Box2d | undefined;
getOutermostSelectableShape(shape: TLShape, filter?: (shape: TLShape) => boolean): TLShape;
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getOutline<T extends TLShape>(shape: T): Vec2d[];
getOutlineById(id: TLShapeId): Vec2d[];
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getOutlineSegments<T extends TLShape>(shape: T): Vec2d[][];
getOutlineSegmentsById(id: TLShapeId): Vec2d[][];
2023-04-25 11:01:25 +00:00
getPageBounds(shape: TLShape): Box2d | undefined;
getPageBoundsById(id: TLShapeId): Box2d | undefined;
getPageById(id: TLPageId): TLPage | undefined;
2023-04-25 11:01:25 +00:00
getPageCenter(shape: TLShape): null | Vec2d;
getPageCenterById(id: TLShapeId): null | Vec2d;
getPageCorners(shape: TLShape): Vec2d[];
getPageInfoById(id: TLPage['id']): TLPage | undefined;
getPageMaskById(id: TLShapeId): undefined | VecLike[];
getPagePointById(id: TLShapeId): undefined | Vec2d;
getPageRotation(shape: TLShape): number;
getPageRotationById(id: TLShapeId): number;
getPageStateByPageId(id: TLPageId): TLInstancePageState | undefined;
getPageTransform(shape: TLShape): Matrix2d | undefined;
getPageTransformById(id: TLShapeId): Matrix2d | undefined;
getParentIdForNewShapeAtPoint(point: VecLike, shapeType: TLShape['type']): TLPageId | TLShapeId;
2023-04-25 11:01:25 +00:00
getParentShape(shape?: TLShape): TLShape | undefined;
getParentsMappedToChildren(ids: TLShapeId[]): Map<TLParentId, Set<TLShape>>;
getParentTransform(shape: TLShape): Matrix2d;
getPointInParentSpace(shapeId: TLShapeId, point: VecLike): Vec2d;
getPointInShapeSpace(shape: TLShape, point: VecLike): Vec2d;
getShapeAndDescendantIds(ids: TLShapeId[]): Set<TLShapeId>;
getShapeById<T extends TLShape = TLShape>(id: TLParentId): T | undefined;
getShapeIdsInPage(pageId: TLPageId): Set<TLShapeId>;
2023-04-25 11:01:25 +00:00
getShapesAtPoint(point: VecLike): TLShape[];
// (undocumented)
getShapeStyleIfExists<T>(shape: TLShape, style: StyleProp<T>): T | undefined;
getShapeUtil<C extends {
new (...args: any[]): ShapeUtil<any>;
type: string;
}>(util: C): InstanceType<C>;
getShapeUtil<S extends TLUnknownShape>(shape: S | TLShapePartial<S>): ShapeUtil<S>;
2023-04-25 11:01:25 +00:00
getSortedChildIds(parentId: TLParentId): TLShapeId[];
getStateDescendant(path: string): StateNode | undefined;
// @internal (undocumented)
getStyleForNextShape<T>(style: StyleProp<T>): T;
2023-04-25 11:01:25 +00:00
getSvg(ids?: TLShapeId[], opts?: Partial<{
scale: number;
background: boolean;
padding: number;
darkMode?: boolean | undefined;
preserveAspectRatio: React.SVGAttributes<SVGSVGElement>['preserveAspectRatio'];
}>): Promise<SVGSVGElement | undefined>;
getTransform(shape: TLShape): Matrix2d;
get gridSize(): number;
groupShapes(ids?: TLShapeId[], groupId?: TLShapeId): this;
hasAncestor(shape: TLShape | undefined, ancestorId: TLShapeId): boolean;
get hintingIds(): TLShapeId[];
readonly history: HistoryManager<this>;
get hoveredId(): null | TLShapeId;
get hoveredShape(): null | TLUnknownShape;
inputs: {
originPagePoint: Vec2d;
originScreenPoint: Vec2d;
previousPagePoint: Vec2d;
previousScreenPoint: Vec2d;
currentPagePoint: Vec2d;
currentScreenPoint: Vec2d;
keys: Set<string>;
buttons: Set<number>;
isPen: boolean;
shiftKey: boolean;
ctrlKey: boolean;
altKey: boolean;
isDragging: boolean;
isPointing: boolean;
isPinching: boolean;
isEditing: boolean;
isPanning: boolean;
pointerVelocity: Vec2d;
};
get instanceState(): TLInstance;
interrupt(): this;
get isChangingStyle(): boolean;
set isChangingStyle(v: boolean);
readonly isChromeForIos: boolean;
get isCoarsePointer(): boolean;
set isCoarsePointer(v: boolean);
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
get isDarkMode(): boolean;
2023-04-25 11:01:25 +00:00
get isFocused(): boolean;
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
get isFocusMode(): boolean;
2023-04-25 11:01:25 +00:00
get isGridMode(): boolean;
isIn(path: string): boolean;
isInAny(...paths: string[]): boolean;
readonly isIos: boolean;
get isMenuOpen(): boolean;
get isPenMode(): boolean;
isPointInShape(point: VecLike, shape: TLShape): boolean;
get isReadOnly(): boolean;
readonly isSafari: boolean;
isSelected(id: TLShapeId): boolean;
isShapeInPage(shape: TLShape, pageId?: TLPageId): boolean;
isShapeOfType<T extends TLUnknownShape>(shape: TLUnknownShape, util: {
new (...args: any): ShapeUtil<T>;
type: string;
}): shape is T;
isShapeOrAncestorLocked(shape?: TLShape): boolean;
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
get isSnapMode(): boolean;
get isToolLocked(): boolean;
2023-04-25 11:01:25 +00:00
isWithinSelection(id: TLShapeId): boolean;
get locale(): string;
2023-04-25 11:01:25 +00:00
mark(reason?: string, onUndo?: boolean, onRedo?: boolean): string;
moveShapesToPage(ids: TLShapeId[], pageId: TLPageId): this;
nudgeShapes(ids: TLShapeId[], direction: Vec2dModel, major?: boolean, ephemeral?: boolean): this;
get onlySelectedShape(): null | TLShape;
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
get openMenus(): string[];
2023-04-25 11:01:25 +00:00
packShapes(ids?: TLShapeId[], padding?: number): this;
get pages(): TLPage[];
get pageState(): TLInstancePageState;
pageToScreen(x: number, y: number, z?: number, camera?: Vec2dModel): {
x: number;
y: number;
z: number;
};
pan(dx: number, dy: number, opts?: TLAnimationOptions): this;
panZoomIntoView(ids: TLShapeId[], opts?: TLAnimationOptions): this;
2023-04-25 11:01:25 +00:00
popFocusLayer(): this;
Add support for project names (#1340) This PR adds some things that we need for the Project Name feature on tldraw.com. It should be reviewed alongside https://github.com/tldraw/tldraw-lite/pull/1814 ## Name Property This PR adds a `name` property to `TLDocument`. We use this to store a project's name. <img width="454" alt="Screenshot 2023-05-09 at 15 47 26" src="https://github.com/tldraw/tldraw/assets/15892272/f3be438e-aa0f-4dec-8f51-8dfd9f9d0ced"> ## Top Zone This PR adds a `topZone` area of the UI that we can add stuff to, similar to how `shareZone` works. It also adds an example to show where the `topZone` and `shareZone` are: <img width="1511" alt="Screenshot 2023-05-12 at 10 57 40" src="https://github.com/tldraw/tldraw/assets/15892272/f5e1cd33-017e-4aaf-bfee-4d85119e2974"> ## Breakpoints This PR change's the UI's breakpoints a little bit. It moves the action bar to the bottom a little bit earlier. (This gives us more space at the top for the project name). ![2023-05-12 at 11 08 26 - Fuchsia Bison](https://github.com/tldraw/tldraw/assets/15892272/34563cea-b1d1-47be-ac5e-5650ee0ba02d) ![2023-05-12 at 13 45 04 - Tan Mole](https://github.com/tldraw/tldraw/assets/15892272/ab190bd3-51d4-4a8b-88de-c72ab14bcba6) ## Input Blur This PR adds an `onBlur` parameter to `Input`. This was needed because 'clicking off' the input wasn't firing `onComplete` or `onCancel`. <img width="620" alt="Screenshot 2023-05-09 at 16 12 58" src="https://github.com/tldraw/tldraw/assets/15892272/3b28da74-0a74-4063-8053-e59e47027caf"> ## Create Project Name This PR adds an internal `createProjectName` property to `TldrawEditorConfig`. Similar to `derivePresenceState`, you can pass a custom function to it. It lets you control what gets used as the default project name. We use it to set different names in our local projects compared to shared projects. In the future, when we add more advanced project features, we could handle this better within the UI. <img width="454" alt="Screenshot 2023-05-09 at 15 47 26" src="https://github.com/tldraw/tldraw/assets/15892272/da9a4699-ac32-40d9-a97c-6c682acfac41"> ### Test Plan 1. Gradually reduce the width of the browser window. 2. Check that the actions menu jumps to the bottom before the style panel moves to the bottom. --- 1. In the examples app, open the `/zones` example. 2. Check that there's a 'top zone' at the top. - [ ] Unit Tests - [ ] Webdriver tests ### Release Note - [dev] Added a `topZone` area where you can put stuff. - [dev] Added a `name` property to `TLDocument` - and `app` methods for it. - [dev] Added an internal `createProjectName` config property for controlling the default project name. - [dev] Added an `onBlur` parameter to `Input`. - Moved the actions bar to the bottom on medium-sized screens. --------- Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
2023-06-01 18:46:26 +00:00
// @internal (undocumented)
get projectName(): string;
putContent(content: TLContent, options?: {
2023-04-25 11:01:25 +00:00
point?: VecLike;
select?: boolean;
preservePosition?: boolean;
preserveIds?: boolean;
}): this;
`ExternalContentManager` for handling external content (files, images, etc) (#1550) This PR improves the editor's APIs around creating assets and files. This allows end user developers to replace behavior that might occur, for example, when pasting images or dragging files onto the canvas. Here, we: - remove `onCreateAssetFromFile` prop - remove `onCreateBookmarkFromUrl` prop - introduce `onEditorReady` prop - introduce `onEditorWillDispose` prop - introduce `ExternalContentManager` The `ExternalContentManager` (ECM) is used in circumstances where we're turning external content (text, images, urls, etc) into assets or shapes. It is designed to allow certain methods to be overwritten by other developers as a kind of weakly supported hack. For example, when a user drags an image onto the canvas, the event handler passes a `TLExternalContent` object to the editor's `putExternalContent` method. This method runs the ECM's handler for this content type. That handler may in turn run other methods, such as `createAssetFromFile` or `createShapesForAssets`, which will lead to the image being created on the canvas. If a developer wanted to change the way that assets are created from files, then they could overwrite that method at runtime. ```ts const handleEditorReady = (editor: Editor) => { editor.externalContentManager.createAssetFromFile = myHandler } function Example() { return <Tldraw onEditorReady={handleEditorReady}/> } ``` If you wanted to go even deeper, you could override the editor's `putExternalContent` method. ```ts const handleEditorReady = (editor: Editor) => { const handleExternalContent = (info: TLExternalContent): Promise<void> => { if (info.type === 'files') { // do something here } else { // do the normal thing editor.externalContentManager.handleContent(info) } } ``` ### Change Type - [x] `major` ### Test Plan 1. Drag images, urls, etc. onto the canvas 2. Use copy and paste for single and multiple files 3. Use bookmark / embed shapes and convert between eachother ### Release Notes - [editor] add `ExternalContentManager` for plopping content onto the canvas - [editor] remove `onCreateAssetFromFile` prop - [editor] remove `onCreateBookmarkFromUrl` prop - [editor] introduce `onEditorReady` prop - [editor] introduce `onEditorWillDispose` prop - [editor] introduce `ExternalContentManager`
2023-06-08 14:53:11 +00:00
putExternalContent(info: TLExternalContent): Promise<void>;
2023-04-25 11:01:25 +00:00
redo(): this;
renamePage(id: TLPageId, name: string, squashing?: boolean): this;
get renderingBounds(): Box2d;
// @internal (undocumented)
readonly _renderingBounds: Atom<Box2d, unknown>;
get renderingBoundsExpanded(): Box2d;
// @internal (undocumented)
readonly _renderingBoundsExpanded: Atom<Box2d, unknown>;
2023-04-25 11:01:25 +00:00
get renderingShapes(): {
id: TLShapeId;
index: number;
backgroundIndex: number;
2023-04-25 11:01:25 +00:00
opacity: number;
isCulled: boolean;
isInViewport: boolean;
maskedPageBounds: Box2d | undefined;
2023-04-25 11:01:25 +00:00
}[];
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
reorderShapes(operation: 'backward' | 'forward' | 'toBack' | 'toFront', ids: TLShapeId[]): this;
2023-04-25 11:01:25 +00:00
reparentShapesById(ids: TLShapeId[], parentId: TLParentId, insertIndex?: string): this;
replaceStoreContentsWithRecordsForOtherDocument(records: TLRecord[]): void;
resetZoom(point?: Vec2d, opts?: TLAnimationOptions): this;
2023-04-25 11:01:25 +00:00
resizeShape(id: TLShapeId, scale: VecLike, options?: {
initialBounds?: Box2d;
scaleOrigin?: VecLike;
scaleAxisRotation?: number;
initialShape?: TLShape;
initialPageTransform?: MatLike;
dragHandle?: TLResizeHandle;
mode?: TLResizeMode;
}): this;
readonly root: RootState;
rotateShapesBy(ids: TLShapeId[], delta: number): this;
screenToPage(x: number, y: number, z?: number, camera?: Vec2dModel): {
x: number;
y: number;
z: number;
};
get scribble(): null | TLScribble;
select(...ids: TLShapeId[]): this;
selectAll(): this;
get selectedIds(): TLShapeId[];
get selectedIdsSet(): ReadonlySet<TLShapeId>;
get selectedPageBounds(): Box2d | null;
get selectedShapes(): TLShape[];
2023-04-25 11:01:25 +00:00
get selectionBounds(): Box2d | undefined;
get selectionPageCenter(): null | Vec2d;
get selectionRotation(): number;
selectNone(): this;
sendBackward(ids?: TLShapeId[]): this;
sendToBack(ids?: TLShapeId[]): this;
setAnimationSpeed(animationSpeed: number): this;
2023-04-25 11:01:25 +00:00
setBrush(brush?: Box2dModel | null): this;
setCamera(x: number, y: number, z?: number, { stopFollowing }?: TLViewportOptions): this;
2023-04-25 11:01:25 +00:00
setCroppingId(id: null | TLShapeId): this;
setCurrentPageId(pageId: TLPageId, { stopFollowing }?: TLViewportOptions): this;
2023-04-25 11:01:25 +00:00
setCursor(cursor: Partial<TLCursor>): this;
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
setDarkMode(isDarkMode: boolean): this;
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
setDevicePixelRatio(dpr: number): this;
2023-04-25 11:01:25 +00:00
setEditingId(id: null | TLShapeId): this;
setErasingIds(ids?: TLShapeId[]): this;
setFocusLayer(next: null | TLShapeId): this;
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
setFocusMode(isFocusMode: boolean): this;
setGridMode(isGridMode: boolean): this;
2023-04-25 11:01:25 +00:00
setHintingIds(ids: TLShapeId[]): this;
setHoveredId(id?: null | TLShapeId): this;
setLocale(locale: string): void;
setOpacity(opacity: number, ephemeral?: boolean, squashing?: boolean): this;
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
setPageState(partial: Partial<TLInstancePageState>, ephemeral?: boolean): void;
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
setPenMode(isPenMode: boolean): this;
Add support for project names (#1340) This PR adds some things that we need for the Project Name feature on tldraw.com. It should be reviewed alongside https://github.com/tldraw/tldraw-lite/pull/1814 ## Name Property This PR adds a `name` property to `TLDocument`. We use this to store a project's name. <img width="454" alt="Screenshot 2023-05-09 at 15 47 26" src="https://github.com/tldraw/tldraw/assets/15892272/f3be438e-aa0f-4dec-8f51-8dfd9f9d0ced"> ## Top Zone This PR adds a `topZone` area of the UI that we can add stuff to, similar to how `shareZone` works. It also adds an example to show where the `topZone` and `shareZone` are: <img width="1511" alt="Screenshot 2023-05-12 at 10 57 40" src="https://github.com/tldraw/tldraw/assets/15892272/f5e1cd33-017e-4aaf-bfee-4d85119e2974"> ## Breakpoints This PR change's the UI's breakpoints a little bit. It moves the action bar to the bottom a little bit earlier. (This gives us more space at the top for the project name). ![2023-05-12 at 11 08 26 - Fuchsia Bison](https://github.com/tldraw/tldraw/assets/15892272/34563cea-b1d1-47be-ac5e-5650ee0ba02d) ![2023-05-12 at 13 45 04 - Tan Mole](https://github.com/tldraw/tldraw/assets/15892272/ab190bd3-51d4-4a8b-88de-c72ab14bcba6) ## Input Blur This PR adds an `onBlur` parameter to `Input`. This was needed because 'clicking off' the input wasn't firing `onComplete` or `onCancel`. <img width="620" alt="Screenshot 2023-05-09 at 16 12 58" src="https://github.com/tldraw/tldraw/assets/15892272/3b28da74-0a74-4063-8053-e59e47027caf"> ## Create Project Name This PR adds an internal `createProjectName` property to `TldrawEditorConfig`. Similar to `derivePresenceState`, you can pass a custom function to it. It lets you control what gets used as the default project name. We use it to set different names in our local projects compared to shared projects. In the future, when we add more advanced project features, we could handle this better within the UI. <img width="454" alt="Screenshot 2023-05-09 at 15 47 26" src="https://github.com/tldraw/tldraw/assets/15892272/da9a4699-ac32-40d9-a97c-6c682acfac41"> ### Test Plan 1. Gradually reduce the width of the browser window. 2. Check that the actions menu jumps to the bottom before the style panel moves to the bottom. --- 1. In the examples app, open the `/zones` example. 2. Check that there's a 'top zone' at the top. - [ ] Unit Tests - [ ] Webdriver tests ### Release Note - [dev] Added a `topZone` area where you can put stuff. - [dev] Added a `name` property to `TLDocument` - and `app` methods for it. - [dev] Added an internal `createProjectName` config property for controlling the default project name. - [dev] Added an `onBlur` parameter to `Input`. - Moved the actions bar to the bottom on medium-sized screens. --------- Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
2023-06-01 18:46:26 +00:00
// @internal (undocumented)
setProjectName(name: string): void;
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
setReadOnly(isReadOnly: boolean): this;
2023-04-25 11:01:25 +00:00
setScribble(scribble?: null | TLScribble): this;
setSelectedIds(ids: TLShapeId[], squashing?: boolean): this;
setSelectedTool(id: string, info?: {}): this;
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
setSnapMode(isSnapMode: boolean): this;
setStyle<T>(style: StyleProp<T>, value: T, ephemeral?: boolean, squashing?: boolean): this;
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
setToolLocked(isToolLocked: boolean): this;
2023-04-25 11:01:25 +00:00
setZoomBrush(zoomBrush?: Box2dModel | null): this;
get shapesArray(): TLShape[];
shapeUtils: {
readonly [K in string]?: ShapeUtil<TLUnknownShape>;
2023-04-25 11:01:25 +00:00
};
get sharedOpacity(): SharedStyle<number>;
get sharedStyles(): ReadonlySharedStyleMap;
2023-04-25 11:01:25 +00:00
slideCamera(opts?: {
speed: number;
direction: Vec2d;
friction: number;
speedThreshold?: number | undefined;
}): this | undefined;
2023-04-25 11:01:25 +00:00
readonly snaps: SnapManager;
get sortedShapesArray(): TLShape[];
stackShapes(operation: 'horizontal' | 'vertical', ids?: TLShapeId[], gap?: number): this;
startFollowingUser(userId: string): this | undefined;
2023-04-25 11:01:25 +00:00
stopCameraAnimation(): this;
stopFollowingUser(): this;
2023-04-25 11:01:25 +00:00
readonly store: TLStore;
stretchShapes(operation: 'horizontal' | 'vertical', ids?: TLShapeId[]): this;
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
readonly textMeasure: TextManager;
toggleLock(ids?: TLShapeId[]): this;
2023-04-25 11:01:25 +00:00
undo(): HistoryManager<this>;
ungroupShapes(ids?: TLShapeId[]): this;
updateAssets(assets: TLAssetPartial[]): this;
Add support for project names (#1340) This PR adds some things that we need for the Project Name feature on tldraw.com. It should be reviewed alongside https://github.com/tldraw/tldraw-lite/pull/1814 ## Name Property This PR adds a `name` property to `TLDocument`. We use this to store a project's name. <img width="454" alt="Screenshot 2023-05-09 at 15 47 26" src="https://github.com/tldraw/tldraw/assets/15892272/f3be438e-aa0f-4dec-8f51-8dfd9f9d0ced"> ## Top Zone This PR adds a `topZone` area of the UI that we can add stuff to, similar to how `shareZone` works. It also adds an example to show where the `topZone` and `shareZone` are: <img width="1511" alt="Screenshot 2023-05-12 at 10 57 40" src="https://github.com/tldraw/tldraw/assets/15892272/f5e1cd33-017e-4aaf-bfee-4d85119e2974"> ## Breakpoints This PR change's the UI's breakpoints a little bit. It moves the action bar to the bottom a little bit earlier. (This gives us more space at the top for the project name). ![2023-05-12 at 11 08 26 - Fuchsia Bison](https://github.com/tldraw/tldraw/assets/15892272/34563cea-b1d1-47be-ac5e-5650ee0ba02d) ![2023-05-12 at 13 45 04 - Tan Mole](https://github.com/tldraw/tldraw/assets/15892272/ab190bd3-51d4-4a8b-88de-c72ab14bcba6) ## Input Blur This PR adds an `onBlur` parameter to `Input`. This was needed because 'clicking off' the input wasn't firing `onComplete` or `onCancel`. <img width="620" alt="Screenshot 2023-05-09 at 16 12 58" src="https://github.com/tldraw/tldraw/assets/15892272/3b28da74-0a74-4063-8053-e59e47027caf"> ## Create Project Name This PR adds an internal `createProjectName` property to `TldrawEditorConfig`. Similar to `derivePresenceState`, you can pass a custom function to it. It lets you control what gets used as the default project name. We use it to set different names in our local projects compared to shared projects. In the future, when we add more advanced project features, we could handle this better within the UI. <img width="454" alt="Screenshot 2023-05-09 at 15 47 26" src="https://github.com/tldraw/tldraw/assets/15892272/da9a4699-ac32-40d9-a97c-6c682acfac41"> ### Test Plan 1. Gradually reduce the width of the browser window. 2. Check that the actions menu jumps to the bottom before the style panel moves to the bottom. --- 1. In the examples app, open the `/zones` example. 2. Check that there's a 'top zone' at the top. - [ ] Unit Tests - [ ] Webdriver tests ### Release Note - [dev] Added a `topZone` area where you can put stuff. - [dev] Added a `name` property to `TLDocument` - and `app` methods for it. - [dev] Added an internal `createProjectName` config property for controlling the default project name. - [dev] Added an `onBlur` parameter to `Input`. - Moved the actions bar to the bottom on medium-sized screens. --------- Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
2023-06-01 18:46:26 +00:00
updateDocumentSettings(settings: Partial<TLDocument>): void;
Independent instance state persistence (#1493) This PR - Removes UserDocumentRecordType - moving isSnapMode to user preferences - moving isGridMode and isPenMode to InstanceRecordType - deleting the other properties which are no longer needed. - Creates a separate pipeline for persisting instance state. Previously the instance state records were stored alongside the document state records, and in order to load the state for a particular instance (in our case, a particular tab) you needed to pass the 'instanceId' prop. This prop ended up totally pervading the public API and people ran into all kinds of issues with it, e.g. using the same instance id in multiple editor instances. There was also an issue whereby it was hard for us to clean up old instance state so the idb table ended up bloating over time. This PR makes it so that rather than passing an instanceId, you load the instance state yourself while creating the store. It provides tools to make that easy. - Undoes the assumption that we might have more than one instance's state in the store. - Like `document`, `instance` now has a singleton id `instance:instance`. - Page state ids and camera ids are no longer random, but rather derive from the page they belong to. This is like having a foreign primary key in SQL databases. It's something i'd love to support fully as part of the RecordType/Store api. Tests to do - [x] Test Migrations - [x] Test Store.listen filtering - [x] Make type sets in Store public and readonly - [x] Test RecordType.createId - [x] Test Instance state snapshot loading/exporting - [x] Manual test File I/O - [x] Manual test Vscode extension with multiple tabs - [x] Audit usages of store.query - [x] Audit usages of changed types: InstanceRecordType, 'instance', InstancePageStateRecordType, 'instance_page_state', 'user_document', 'camera', CameraRecordType, InstancePresenceRecordType, 'instance_presence' - [x] Test user preferences - [x] Manual test isSnapMode and isGridMode and isPenMode - [ ] Test indexedDb functions - [x] Add instanceId stuff back ### Change Type - [x] `major` — Breaking Change ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] Webdriver tests ### Release Notes - Add a brief release note for your PR here.
2023-06-05 14:11:07 +00:00
updateInstanceState(partial: Partial<Omit<TLInstance, 'currentPageId'>>, ephemeral?: boolean, squashing?: boolean): this;
2023-04-25 11:01:25 +00:00
updatePage(partial: RequiredKeys<TLPage, 'id'>, squashing?: boolean): this;
// @internal
updateRenderingBounds(): this;
updateShapes<T extends TLUnknownShape>(partials: (null | TLShapePartial<T> | undefined)[], squashing?: boolean): this;
2023-04-25 11:01:25 +00:00
updateViewportScreenBounds(center?: boolean): this;
readonly user: UserPreferencesManager;
2023-04-25 11:01:25 +00:00
get viewportPageBounds(): Box2d;
get viewportPageCenter(): Vec2d;
get viewportScreenBounds(): Box2d;
get viewportScreenCenter(): Vec2d;
visitDescendants(parentId: TLParentId, visitor: (id: TLShapeId) => false | void): void;
get zoomBrush(): Box2dModel | null;
zoomIn(point?: Vec2d, opts?: TLAnimationOptions): this;
2023-04-25 11:01:25 +00:00
get zoomLevel(): number;
zoomOut(point?: Vec2d, opts?: TLAnimationOptions): this;
zoomToBounds(x: number, y: number, width: number, height: number, targetZoom?: number, opts?: TLAnimationOptions): this;
[feature] ui events (#1326) This PR updates the editor events: - adds types to the events emitted by the app (by `app.emit`) - removes a few events emitted by the app (e.g. `move-to-page`, `change-camera`) - adds `onEvent` prop to the <TldrawUi> / <Tldraw> components - call the `onEvent` when actions occur or tools are selected - does some superficial cleanup on editor app APIs ### Release Note - Fix layout bug in error dialog - (ui) Add `TLEventMap` for types emitted from editor app - (editor) Update `crash` event emitted from editor app to include error - (editor) Update `change-history` event emitted from editor app - (editor) Remove `change-camera` event from editor app - (editor) Remove `move-to-page` event from editor app - (ui) Add `onEvent` prop and events to <Tldraw> / <TldrawUi> - (editor) Replace `app.openMenus` plain Set with computed value - (editor) Add `addOpenMenu` method - (editor) Add `removeOpenMenu` method - (editor) Add `setFocusMode` method - (editor) Add `setToolLocked` method - (editor) Add `setSnapMode` method - (editor) Add `isSnapMode` method - (editor) Update `setGridMode` method return type to editor app - (editor) Update `setReadOnly` method return type to editor app - (editor) Update `setPenMode` method return type to editor app - (editor) Update `selectNone` method return type to editor app - (editor) Rename `backToContent` to `zoomToContent` - (editor) Remove `TLReorderOperation` type --------- Co-authored-by: Orange Mug <orangemug@users.noreply.github.com>
2023-05-11 22:14:58 +00:00
zoomToContent(): this;
zoomToFit(opts?: TLAnimationOptions): this;
zoomToSelection(opts?: TLAnimationOptions): this;
2023-04-25 11:01:25 +00:00
}
// @public (undocumented)
export const EmbedShape: TLShapeInfo<TLEmbedShape>;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
// (undocumented)
canEdit: TLShapeUtilFlag<TLEmbedShape>;
// (undocumented)
canResize: (shape: TLEmbedShape) => boolean;
// (undocumented)
canUnmount: TLShapeUtilFlag<TLEmbedShape>;
// (undocumented)
component(shape: TLEmbedShape): JSX.Element;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLEmbedShape['props'];
// (undocumented)
hideSelectionBoundsBg: TLShapeUtilFlag<TLEmbedShape>;
// (undocumented)
hideSelectionBoundsFg: TLShapeUtilFlag<TLEmbedShape>;
// (undocumented)
indicator(shape: TLEmbedShape): JSX.Element;
// (undocumented)
isAspectRatioLocked: TLShapeUtilFlag<TLEmbedShape>;
// (undocumented)
onResize: TLOnResizeHandler<TLEmbedShape>;
// (undocumented)
static type: "embed";
}
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export class ErrorBoundary extends React_3.Component<React_3.PropsWithRef<React_3.PropsWithChildren<TLErrorBoundaryProps>>, TLErrorBoundaryState> {
2023-04-25 11:01:25 +00:00
// (undocumented)
componentDidCatch(error: unknown): void;
// (undocumented)
static getDerivedStateFromError(error: Error): {
error: Error;
};
// (undocumented)
render(): boolean | JSX.Element | null | number | React_3.ReactFragment | string | undefined;
2023-04-25 11:01:25 +00:00
// (undocumented)
state: TLErrorBoundaryState;
2023-04-25 11:01:25 +00:00
}
// @public (undocumented)
export function ErrorScreen({ children }: {
children: any;
}): JSX.Element;
// @public (undocumented)
export const EVENT_NAME_MAP: Record<Exclude<TLEventName, TLPinchEventName>, keyof TLEventHandlers>;
Independent instance state persistence (#1493) This PR - Removes UserDocumentRecordType - moving isSnapMode to user preferences - moving isGridMode and isPenMode to InstanceRecordType - deleting the other properties which are no longer needed. - Creates a separate pipeline for persisting instance state. Previously the instance state records were stored alongside the document state records, and in order to load the state for a particular instance (in our case, a particular tab) you needed to pass the 'instanceId' prop. This prop ended up totally pervading the public API and people ran into all kinds of issues with it, e.g. using the same instance id in multiple editor instances. There was also an issue whereby it was hard for us to clean up old instance state so the idb table ended up bloating over time. This PR makes it so that rather than passing an instanceId, you load the instance state yourself while creating the store. It provides tools to make that easy. - Undoes the assumption that we might have more than one instance's state in the store. - Like `document`, `instance` now has a singleton id `instance:instance`. - Page state ids and camera ids are no longer random, but rather derive from the page they belong to. This is like having a foreign primary key in SQL databases. It's something i'd love to support fully as part of the RecordType/Store api. Tests to do - [x] Test Migrations - [x] Test Store.listen filtering - [x] Make type sets in Store public and readonly - [x] Test RecordType.createId - [x] Test Instance state snapshot loading/exporting - [x] Manual test File I/O - [x] Manual test Vscode extension with multiple tabs - [x] Audit usages of store.query - [x] Audit usages of changed types: InstanceRecordType, 'instance', InstancePageStateRecordType, 'instance_page_state', 'user_document', 'camera', CameraRecordType, InstancePresenceRecordType, 'instance_presence' - [x] Test user preferences - [x] Manual test isSnapMode and isGridMode and isPenMode - [ ] Test indexedDb functions - [x] Add instanceId stuff back ### Change Type - [x] `major` — Breaking Change ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] Webdriver tests ### Release Notes - Add a brief release note for your PR here.
2023-06-05 14:11:07 +00:00
// @internal (undocumented)
export function extractSessionStateFromLegacySnapshot(store: Record<string, UnknownRecord>): null | TLSessionStateSnapshot;
// @internal (undocumented)
export const featureFlags: {
peopleMenu: DebugFlag<boolean>;
highlighterTool: DebugFlag<boolean>;
};
2023-04-25 11:01:25 +00:00
// @public
export function fileToBase64(file: Blob): Promise<string>;
// @public (undocumented)
export const FrameShape: TLShapeInfo<TLFrameShape>;
// @public (undocumented)
export class FrameShapeUtil extends BaseBoxShapeUtil<TLFrameShape> {
// (undocumented)
canBind: () => boolean;
// (undocumented)
canDropShapes: (shape: TLFrameShape, _shapes: TLShape[]) => boolean;
// (undocumented)
canEdit: () => boolean;
// (undocumented)
canReceiveNewChildrenOfType: (shape: TLShape, _type: TLShape['type']) => boolean;
// (undocumented)
component(shape: TLFrameShape): JSX.Element;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLFrameShape['props'];
// (undocumented)
indicator(shape: TLFrameShape): JSX.Element;
// (undocumented)
onDragShapesOut: (_shape: TLFrameShape, shapes: TLShape[]) => void;
// (undocumented)
onDragShapesOver: (frame: TLFrameShape, shapes: TLShape[]) => {
shouldHint: boolean;
};
// (undocumented)
onResizeEnd: TLOnResizeEndHandler<TLFrameShape>;
// (undocumented)
providesBackgroundForChildren(): boolean;
// (undocumented)
toSvg(shape: TLFrameShape): Promise<SVGElement> | SVGElement;
// (undocumented)
static type: "frame";
}
// @public (undocumented)
export const GeoShape: TLShapeInfo<TLGeoShape>;
// @public (undocumented)
export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
// (undocumented)
canEdit: () => boolean;
// (undocumented)
component(shape: TLGeoShape): JSX.Element;
// (undocumented)
getBounds(shape: TLGeoShape): Box2d;
// (undocumented)
getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[];
// (undocumented)
getCenter(shape: TLGeoShape): Vec2d;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLGeoShape['props'];
// (undocumented)
getOutline(shape: TLGeoShape): Vec2d[];
// (undocumented)
hitTestLineSegment(shape: TLGeoShape, A: VecLike, B: VecLike): boolean;
// (undocumented)
hitTestPoint(shape: TLGeoShape, point: VecLike): boolean;
// (undocumented)
indicator(shape: TLGeoShape): JSX.Element;
// (undocumented)
onBeforeCreate: (shape: TLGeoShape) => {
props: {
growY: number;
geo: "arrow-down" | "arrow-left" | "arrow-right" | "arrow-up" | "check-box" | "diamond" | "ellipse" | "hexagon" | "octagon" | "oval" | "pentagon" | "rectangle" | "rhombus-2" | "rhombus" | "star" | "trapezoid" | "triangle" | "x-box";
labelColor: "black" | "blue" | "green" | "grey" | "light-blue" | "light-green" | "light-red" | "light-violet" | "orange" | "red" | "violet" | "yellow";
color: "black" | "blue" | "green" | "grey" | "light-blue" | "light-green" | "light-red" | "light-violet" | "orange" | "red" | "violet" | "yellow";
fill: "none" | "pattern" | "semi" | "solid";
dash: "dashed" | "dotted" | "draw" | "solid";
size: "l" | "m" | "s" | "xl";
font: "draw" | "mono" | "sans" | "serif";
align: "end-legacy" | "end" | "middle-legacy" | "middle" | "start-legacy" | "start";
verticalAlign: "end" | "middle" | "start";
url: string;
w: number;
h: number;
text: string;
};
type: "geo";
x: number;
y: number;
rotation: number;
index: string;
parentId: TLParentId;
isLocked: boolean;
opacity: number;
id: TLShapeId;
typeName: "shape";
} | undefined;
// (undocumented)
onBeforeUpdate: (prev: TLGeoShape, next: TLGeoShape) => {
props: {
growY: number;
geo: "arrow-down" | "arrow-left" | "arrow-right" | "arrow-up" | "check-box" | "diamond" | "ellipse" | "hexagon" | "octagon" | "oval" | "pentagon" | "rectangle" | "rhombus-2" | "rhombus" | "star" | "trapezoid" | "triangle" | "x-box";
labelColor: "black" | "blue" | "green" | "grey" | "light-blue" | "light-green" | "light-red" | "light-violet" | "orange" | "red" | "violet" | "yellow";
color: "black" | "blue" | "green" | "grey" | "light-blue" | "light-green" | "light-red" | "light-violet" | "orange" | "red" | "violet" | "yellow";
fill: "none" | "pattern" | "semi" | "solid";
dash: "dashed" | "dotted" | "draw" | "solid";
size: "l" | "m" | "s" | "xl";
font: "draw" | "mono" | "sans" | "serif";
align: "end-legacy" | "end" | "middle-legacy" | "middle" | "start-legacy" | "start";
verticalAlign: "end" | "middle" | "start";
url: string;
w: number;
h: number;
text: string;
};
type: "geo";
x: number;
y: number;
rotation: number;
index: string;
parentId: TLParentId;
isLocked: boolean;
opacity: number;
id: TLShapeId;
typeName: "shape";
} | undefined;
// (undocumented)
onDoubleClick: (shape: TLGeoShape) => {
props: {
geo: "check-box";
};
type: "geo";
x: number;
y: number;
rotation: number;
index: string;
parentId: TLParentId;
isLocked: boolean;
opacity: number;
id: TLShapeId;
typeName: "shape";
} | {
props: {
geo: "rectangle";
};
type: "geo";
x: number;
y: number;
rotation: number;
index: string;
parentId: TLParentId;
isLocked: boolean;
opacity: number;
id: TLShapeId;
typeName: "shape";
} | undefined;
// (undocumented)
onEditEnd: TLOnEditEndHandler<TLGeoShape>;
// (undocumented)
onResize: TLOnResizeHandler<TLGeoShape>;
// (undocumented)
toSvg(shape: TLGeoShape, ctx: SvgExportContext): SVGElement;
// (undocumented)
static type: "geo";
}
// @public
export function getEmbedInfo(inputUrl: string): TLEmbedResult;
// @public
export function getEmbedInfoUnsafely(inputUrl: string): TLEmbedResult;
// @public
export function getFileMetaData(file: File): Promise<{
isAnimated: boolean;
}>;
// @public (undocumented)
export function getFreshUserPreferences(): TLUserPreferences;
export { getHashForString }
// @public
export function getImageSizeFromSrc(dataURL: string): Promise<{
w: number;
h: number;
}>;
// @public
export function getIncrementedName(name: string, others: string[]): string;
// @public
export function getMediaAssetFromFile(file: File): Promise<TLAsset>;
// @internal (undocumented)
export function getPointerInfo(e: PointerEvent | React.PointerEvent, container: HTMLElement): {
point: {
x: number;
y: number;
z: number;
};
shiftKey: boolean;
altKey: boolean;
ctrlKey: boolean;
pointerId: number;
button: number;
isPen: boolean;
};
// @public
export function getResizedImageDataUrl(dataURLForImage: string, width: number, height: number): Promise<string>;
// @public (undocumented)
export function getRotatedBoxShadow(rotation: number): string;
// @public (undocumented)
export function getSplineForLineShape(shape: TLLineShape): NonNullable<CubicSpline2d | Polyline2d>;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function getSvgAsDataUrl(svg: SVGElement): Promise<string>;
// @public (undocumented)
export function getSvgAsDataUrlSync(node: SVGElement): string;
// @public (undocumented)
export function getSvgAsImage(svg: SVGElement, options: {
type: TLCopyType | TLExportType;
quality: number;
scale: number;
}): Promise<Blob | null>;
// @public (undocumented)
export function getSvgAsString(svg: SVGElement): string;
// @public
export function getSvgPathFromStroke(points: Vec2d[], closed?: boolean): string;
// @public
export function getSvgPathFromStrokePoints(points: StrokePoint[], closed?: boolean): string;
// @public (undocumented)
export function getTextBoundingBox(text: SVGTextElement): DOMRect;
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
// @public (undocumented)
export function getUserPreferences(): TLUserPreferences;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export const getValidHttpURLList: (url: string) => string[] | undefined;
// @public
export function getVideoSizeFromSrc(src: string): Promise<{
w: number;
h: number;
}>;
// @internal (undocumented)
export const GRID_INCREMENT = 5;
// @public (undocumented)
export const GRID_STEPS: {
min: number;
mid: number;
step: number;
}[];
// @public (undocumented)
export const GroupShape: TLShapeInfo<TLGroupShape>;
// @public (undocumented)
export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
// (undocumented)
canBind: () => boolean;
// (undocumented)
component(shape: TLGroupShape): JSX.Element | null;
// (undocumented)
getBounds(shape: TLGroupShape): Box2d;
// (undocumented)
getCenter(shape: TLGroupShape): Vec2d;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLGroupShape['props'];
// (undocumented)
getOutline(shape: TLGroupShape): Vec2d[];
// (undocumented)
hideSelectionBoundsBg: () => boolean;
// (undocumented)
hideSelectionBoundsFg: () => boolean;
// (undocumented)
indicator(shape: TLGroupShape): JSX.Element;
// (undocumented)
onChildrenChange: TLOnChildrenChangeHandler<TLGroupShape>;
// (undocumented)
static type: "group";
// (undocumented)
type: "group";
}
2023-04-25 11:01:25 +00:00
// @internal (undocumented)
export const HAND_TOOL_FRICTION = 0.09;
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
// @public
export function hardReset({ shouldReload }?: {
shouldReload?: boolean | undefined;
}): Promise<void>;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function hardResetEditor(): void;
2023-04-25 11:01:25 +00:00
// @internal (undocumented)
export const HASH_PATTERN_ZOOM_NAMES: Record<string, string>;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export const HighlightShape: TLShapeInfo<TLHighlightShape>;
// @public (undocumented)
export class HighlightShapeUtil extends ShapeUtil<TLHighlightShape> {
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
backgroundComponent(shape: TLHighlightShape): JSX.Element;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
component(shape: TLHighlightShape): JSX.Element;
// (undocumented)
expandSelectionOutlinePx(shape: TLHighlightShape): number;
// (undocumented)
getBounds(shape: TLHighlightShape): Box2d;
// (undocumented)
getCenter(shape: TLHighlightShape): Vec2d;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLHighlightShape['props'];
// (undocumented)
getOutline(shape: TLHighlightShape): Vec2d[];
// (undocumented)
hideResizeHandles: (shape: TLHighlightShape) => boolean;
// (undocumented)
hideRotateHandle: (shape: TLHighlightShape) => boolean;
// (undocumented)
hideSelectionBoundsBg: (shape: TLHighlightShape) => boolean;
// (undocumented)
hideSelectionBoundsFg: (shape: TLHighlightShape) => boolean;
// (undocumented)
hitTestLineSegment(shape: TLHighlightShape, A: VecLike, B: VecLike): boolean;
// (undocumented)
hitTestPoint(shape: TLHighlightShape, point: VecLike): boolean;
// (undocumented)
indicator(shape: TLHighlightShape): JSX.Element;
// (undocumented)
onResize: TLOnResizeHandler<TLHighlightShape>;
// (undocumented)
toBackgroundSvg(shape: TLHighlightShape): SVGPathElement;
// (undocumented)
toSvg(shape: TLHighlightShape): SVGPathElement;
// (undocumented)
static type: "highlight";
}
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function HTMLContainer({ children, className, ...rest }: HTMLContainerProps): JSX.Element;
// @public (undocumented)
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
export type HTMLContainerProps = React_3.HTMLAttributes<HTMLDivElement>;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export const ImageShape: TLShapeInfo<TLImageShape>;
[improvement] refactor paste to support multi-line text (#1398) This PR refactors our clipboard handlers. It should simplify the way that things work and better handle the difference between how the native API events are handled vs. the browser's clipboard API events. ![Kapture 2023-05-17 at 13 26 34](https://github.com/tldraw/tldraw/assets/23072548/5dedcc25-a1d2-423f-8bc2-415f761b643b) Everything that used to be supported now also still works. In addition, we now have several useful features: ### Multiline text can be pasted into the app When pasting text that contains more than one line, the text is pasted correctly; even if the clipboard also includes HTML data. Previously, we would try to paste HTML data if we found it, because that data might contain tldraw's own content as a comment; but if that failed, we would paste the data as text instead. This led to pasting text that lost lots of information from that text, such as line breaks and indentations. ### Multiline text shapes are aligned correctly When pasting raw text that has more than one line, the text will be left aligned—or right aligned if the text is likely from a RTL language. ![Kapture 2023-05-17 at 13 42 54](https://github.com/tldraw/tldraw/assets/23072548/f705acd5-136c-4144-80da-6e97ff766a58) ### Common minimum indentation is removed from each line ![Kapture 2023-05-17 at 13 56 28](https://github.com/tldraw/tldraw/assets/23072548/d45c95f6-6d28-4c9f-8cd3-8078700ce928) This is something that absolutely every app should implement, but here we go. When multiline text has "common indentation" on each line, which is often the case when pasting text from code, then that indentation is removed from each line. ### Auto wrapping for big pastes When a line has no text breaks but a lot of text, we now set the width of the text shape. ![Kapture 2023-05-17 at 14 00 04](https://github.com/tldraw/tldraw/assets/23072548/0b7f69c3-bcf9-42e9-a1ed-df026f868793) ## How it works A `ClipboardThing` is the common interface for things that we found on the clipboard, native or otherwise. Both `handlePasteFromClipboardApi` and `handlePasteFromEventClipboardData` parse out `ClipboardThing`s and pass them to `handleClipboardThings`. <img width="905" alt="image" src="https://github.com/tldraw/tldraw/assets/23072548/fd087539-edbb-4527-b5ff-ca7d7c1726b2"> A `ClipboardResult` is the result of processing a `ClipboardThing`, and usually contains text and other information about that text. We make decisions on what to create based on which `ClipboardResult`s we find. When pasting text, we check to see whether the result would be bigger than the viewport, or if the text is multiline, or if the text is of an RTL language by testing certain common RTL characters. We make some adjustments based on those factors, ensuring that the top-left corner of the text is on screen and reasonably positioned within the viewport if possible. ### Change Type - [x] `minor` — New Feature ### Test Plan 1. Copy and paste shapes 2. Copy and paste text from elsewhere into the app 3. Copy and paste images from elsewhere into the app 4. Try on different browsers ### Release Notes - Improves clipboard logic when pasting text - Adds support for pasting multi-line text - Adds maximum widths when pasting single-line text - Adds support for RTL languages when pasting multi-line or wrapped text - Strips leading indentation when pasting text
2023-05-17 16:32:25 +00:00
// @public (undocumented)
export class ImageShapeUtil extends BaseBoxShapeUtil<TLImageShape> {
// (undocumented)
canCrop: () => boolean;
// (undocumented)
component(shape: TLImageShape): JSX.Element;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLImageShape['props'];
// (undocumented)
indicator(shape: TLImageShape): JSX.Element | null;
// (undocumented)
isAspectRatioLocked: () => boolean;
// (undocumented)
onDoubleClick: (shape: TLImageShape) => void;
// (undocumented)
onDoubleClickEdge: TLOnDoubleClickHandler<TLImageShape>;
// (undocumented)
toSvg(shape: TLImageShape): Promise<SVGGElement>;
// (undocumented)
static type: "image";
}
// @public (undocumented)
export const INDENT = " ";
// @public
export function isAnimated(buffer: ArrayBuffer): boolean;
2023-04-25 11:01:25 +00:00
// @public
export function isGIF(buffer: ArrayBuffer): boolean;
// @public (undocumented)
export const isImage: (ext: string) => boolean;
// @public
export function isSerializable(value: any): boolean;
// @public (undocumented)
export const isSvgText: (text: string) => boolean;
// @public (undocumented)
export const isValidHttpURL: (url: string) => boolean;
// @public (undocumented)
export function isValidUrl(url: string): boolean;
// @public (undocumented)
export const LineShape: TLShapeInfo<TLLineShape>;
// @public (undocumented)
export class LineShapeUtil extends ShapeUtil<TLLineShape> {
// (undocumented)
component(shape: TLLineShape): JSX.Element | undefined;
// (undocumented)
getBounds(shape: TLLineShape): Box2d;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLLineShape['props'];
// (undocumented)
getHandles(shape: TLLineShape): TLHandle[];
// (undocumented)
getOutline(shape: TLLineShape): Vec2d[];
// (undocumented)
getOutlineSegments(shape: TLLineShape): Vec2d[][];
// (undocumented)
hideResizeHandles: () => boolean;
// (undocumented)
hideRotateHandle: () => boolean;
// (undocumented)
hideSelectionBoundsBg: () => boolean;
// (undocumented)
hideSelectionBoundsFg: () => boolean;
// (undocumented)
hitTestLineSegment(shape: TLLineShape, A: VecLike, B: VecLike): boolean;
// (undocumented)
hitTestPoint(shape: TLLineShape, point: Vec2d): boolean;
// (undocumented)
indicator(shape: TLLineShape): JSX.Element;
// (undocumented)
isClosed: () => boolean;
// (undocumented)
onHandleChange: TLOnHandleChangeHandler<TLLineShape>;
// (undocumented)
onResize: TLOnResizeHandler<TLLineShape>;
// (undocumented)
toSvg(shape: TLLineShape): SVGGElement;
// (undocumented)
static type: "line";
}
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function LoadingScreen({ children }: {
children: any;
}): JSX.Element;
Independent instance state persistence (#1493) This PR - Removes UserDocumentRecordType - moving isSnapMode to user preferences - moving isGridMode and isPenMode to InstanceRecordType - deleting the other properties which are no longer needed. - Creates a separate pipeline for persisting instance state. Previously the instance state records were stored alongside the document state records, and in order to load the state for a particular instance (in our case, a particular tab) you needed to pass the 'instanceId' prop. This prop ended up totally pervading the public API and people ran into all kinds of issues with it, e.g. using the same instance id in multiple editor instances. There was also an issue whereby it was hard for us to clean up old instance state so the idb table ended up bloating over time. This PR makes it so that rather than passing an instanceId, you load the instance state yourself while creating the store. It provides tools to make that easy. - Undoes the assumption that we might have more than one instance's state in the store. - Like `document`, `instance` now has a singleton id `instance:instance`. - Page state ids and camera ids are no longer random, but rather derive from the page they belong to. This is like having a foreign primary key in SQL databases. It's something i'd love to support fully as part of the RecordType/Store api. Tests to do - [x] Test Migrations - [x] Test Store.listen filtering - [x] Make type sets in Store public and readonly - [x] Test RecordType.createId - [x] Test Instance state snapshot loading/exporting - [x] Manual test File I/O - [x] Manual test Vscode extension with multiple tabs - [x] Audit usages of store.query - [x] Audit usages of changed types: InstanceRecordType, 'instance', InstancePageStateRecordType, 'instance_page_state', 'user_document', 'camera', CameraRecordType, InstancePresenceRecordType, 'instance_presence' - [x] Test user preferences - [x] Manual test isSnapMode and isGridMode and isPenMode - [ ] Test indexedDb functions - [x] Add instanceId stuff back ### Change Type - [x] `major` — Breaking Change ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] Webdriver tests ### Release Notes - Add a brief release note for your PR here.
2023-06-05 14:11:07 +00:00
// @public
export function loadSessionStateSnapshotIntoStore(store: TLStore, snapshot: TLSessionStateSnapshot): void;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function loopToHtmlElement(elm: Element): HTMLElement;
// @internal (undocumented)
export const MAJOR_NUDGE_FACTOR = 10;
// @public (undocumented)
export function matchEmbedUrl(url: string): {
definition: {
readonly type: "codepen";
readonly title: "Codepen";
readonly hostnames: readonly ["codepen.io"];
readonly minWidth: 300;
readonly minHeight: 300;
readonly width: 520;
readonly height: 400;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
2023-04-25 11:01:25 +00:00
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "codesandbox";
readonly title: "CodeSandbox";
readonly hostnames: readonly ["codesandbox.io"];
readonly minWidth: 300;
readonly minHeight: 300;
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "excalidraw";
readonly title: "Excalidraw";
readonly hostnames: readonly ["excalidraw.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "felt";
readonly title: "Felt";
readonly hostnames: readonly ["felt.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "figma";
readonly title: "Figma";
readonly hostnames: readonly ["figma.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "github_gist";
readonly title: "GitHub Gist";
readonly hostnames: readonly ["gist.github.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "google_calendar";
readonly title: "Google Calendar";
readonly hostnames: readonly ["calendar.google.*"];
readonly width: 720;
readonly height: 500;
readonly minWidth: 460;
readonly minHeight: 360;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly instructionLink: "https://support.google.com/calendar/answer/41207?hl=en";
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "google_maps";
readonly title: "Google Maps";
readonly hostnames: readonly ["google.*"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "google_slides";
readonly title: "Google Slides";
readonly hostnames: readonly ["docs.google.*"];
readonly width: 720;
readonly height: 500;
readonly minWidth: 460;
readonly minHeight: 360;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "observable";
readonly title: "Observable";
readonly hostnames: readonly ["observablehq.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly isAspectRatioLocked: false;
readonly backgroundColor: "#fff";
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "replit";
readonly title: "Replit";
readonly hostnames: readonly ["replit.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "scratch";
readonly title: "Scratch";
readonly hostnames: readonly ["scratch.mit.edu"];
readonly width: 520;
readonly height: 400;
readonly doesResize: false;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "spotify";
readonly title: "Spotify";
readonly hostnames: readonly ["open.spotify.com"];
readonly width: 720;
readonly height: 500;
readonly minHeight: 500;
readonly overrideOutlineRadius: 12;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "tldraw";
readonly title: "tldraw";
readonly hostnames: readonly ["beta.tldraw.com", "lite.tldraw.com", "www.tldraw.com"];
readonly minWidth: 300;
readonly minHeight: 300;
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
2023-04-25 11:01:25 +00:00
} | {
readonly type: "vimeo";
readonly title: "Vimeo";
readonly hostnames: readonly ["vimeo.com", "player.vimeo.com"];
readonly width: 640;
readonly height: 360;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "youtube";
readonly title: "YouTube";
readonly hostnames: readonly ["*.youtube.com", "youtube.com", "youtu.be"];
readonly width: 800;
readonly height: 450;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly overridePermissions: {
readonly 'allow-presentation': true;
};
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
};
url: string;
embedUrl: string;
} | undefined;
// @public (undocumented)
export function matchUrl(url: string): {
definition: {
readonly type: "codepen";
readonly title: "Codepen";
readonly hostnames: readonly ["codepen.io"];
readonly minWidth: 300;
readonly minHeight: 300;
readonly width: 520;
readonly height: 400;
readonly doesResize: true;
readonly canUnmount: false;
readonly toEmbedUrl: (url: string) => string | undefined;
2023-04-25 11:01:25 +00:00
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "codesandbox";
readonly title: "CodeSandbox";
readonly hostnames: readonly ["codesandbox.io"];
readonly minWidth: 300;
readonly minHeight: 300;
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "excalidraw";
readonly title: "Excalidraw";
readonly hostnames: readonly ["excalidraw.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "felt";
readonly title: "Felt";
readonly hostnames: readonly ["felt.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "figma";
readonly title: "Figma";
readonly hostnames: readonly ["figma.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "github_gist";
readonly title: "GitHub Gist";
readonly hostnames: readonly ["gist.github.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "google_calendar";
readonly title: "Google Calendar";
readonly hostnames: readonly ["calendar.google.*"];
readonly width: 720;
readonly height: 500;
readonly minWidth: 460;
readonly minHeight: 360;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly instructionLink: "https://support.google.com/calendar/answer/41207?hl=en";
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "google_maps";
readonly title: "Google Maps";
readonly hostnames: readonly ["google.*"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "google_slides";
readonly title: "Google Slides";
readonly hostnames: readonly ["docs.google.*"];
readonly width: 720;
readonly height: 500;
readonly minWidth: 460;
readonly minHeight: 360;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "observable";
readonly title: "Observable";
readonly hostnames: readonly ["observablehq.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly isAspectRatioLocked: false;
readonly backgroundColor: "#fff";
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "replit";
readonly title: "Replit";
readonly hostnames: readonly ["replit.com"];
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "scratch";
readonly title: "Scratch";
readonly hostnames: readonly ["scratch.mit.edu"];
readonly width: 520;
readonly height: 400;
readonly doesResize: false;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "spotify";
readonly title: "Spotify";
readonly hostnames: readonly ["open.spotify.com"];
readonly width: 720;
readonly height: 500;
readonly minHeight: 500;
readonly overrideOutlineRadius: 12;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "tldraw";
readonly title: "tldraw";
readonly hostnames: readonly ["beta.tldraw.com", "lite.tldraw.com", "www.tldraw.com"];
readonly minWidth: 300;
readonly minHeight: 300;
readonly width: 720;
readonly height: 500;
readonly doesResize: true;
readonly canUnmount: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
2023-04-25 11:01:25 +00:00
} | {
readonly type: "vimeo";
readonly title: "Vimeo";
readonly hostnames: readonly ["vimeo.com", "player.vimeo.com"];
readonly width: 640;
readonly height: 360;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
} | {
readonly type: "youtube";
readonly title: "YouTube";
readonly hostnames: readonly ["*.youtube.com", "youtube.com", "youtu.be"];
readonly width: 800;
readonly height: 450;
readonly doesResize: true;
readonly canUnmount: false;
2023-04-25 11:01:25 +00:00
readonly overridePermissions: {
readonly 'allow-presentation': true;
};
readonly isAspectRatioLocked: true;
readonly toEmbedUrl: (url: string) => string | undefined;
readonly fromEmbedUrl: (url: string) => string | undefined;
};
embedUrl: string;
url: string;
} | undefined;
// @internal (undocumented)
export const MAX_ASSET_HEIGHT = 1000;
// @internal (undocumented)
export const MAX_ASSET_WIDTH = 1000;
// @internal (undocumented)
export const MAX_PAGES = 40;
// @internal (undocumented)
export const MAX_SHAPES_PER_PAGE = 2000;
// @internal (undocumented)
export const MAX_ZOOM = 8;
// @internal (undocumented)
export const MIN_ZOOM = 0.1;
// @internal (undocumented)
export const MINOR_NUDGE_FACTOR = 1;
// @internal (undocumented)
export const MULTI_CLICK_DURATION = 200;
// @public (undocumented)
export function normalizeWheel(event: React.WheelEvent<HTMLElement> | WheelEvent): {
x: number;
y: number;
z: number;
};
// @public (undocumented)
export const NoteShape: TLShapeInfo<TLNoteShape>;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export class NoteShapeUtil extends ShapeUtil<TLNoteShape> {
// (undocumented)
canEdit: () => boolean;
// (undocumented)
component(shape: TLNoteShape): JSX.Element;
// (undocumented)
getBounds(shape: TLNoteShape): Box2d;
// (undocumented)
getCenter(_shape: TLNoteShape): Vec2d;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLNoteShape['props'];
// (undocumented)
getHeight(shape: TLNoteShape): number;
// (undocumented)
getOutline(shape: TLNoteShape): Vec2d[];
// (undocumented)
hideResizeHandles: () => boolean;
// (undocumented)
hideSelectionBoundsBg: () => boolean;
// (undocumented)
hideSelectionBoundsFg: () => boolean;
// (undocumented)
indicator(shape: TLNoteShape): JSX.Element;
// (undocumented)
onBeforeCreate: (next: TLNoteShape) => {
props: {
growY: number;
color: "black" | "blue" | "green" | "grey" | "light-blue" | "light-green" | "light-red" | "light-violet" | "orange" | "red" | "violet" | "yellow";
size: "l" | "m" | "s" | "xl";
font: "draw" | "mono" | "sans" | "serif";
align: "end-legacy" | "end" | "middle-legacy" | "middle" | "start-legacy" | "start";
verticalAlign: "end" | "middle" | "start";
url: string;
text: string;
};
type: "note";
x: number;
y: number;
rotation: number;
index: string;
parentId: TLParentId;
isLocked: boolean;
opacity: number;
id: TLShapeId;
typeName: "shape";
} | undefined;
// (undocumented)
onBeforeUpdate: (prev: TLNoteShape, next: TLNoteShape) => {
props: {
growY: number;
color: "black" | "blue" | "green" | "grey" | "light-blue" | "light-green" | "light-red" | "light-violet" | "orange" | "red" | "violet" | "yellow";
size: "l" | "m" | "s" | "xl";
font: "draw" | "mono" | "sans" | "serif";
align: "end-legacy" | "end" | "middle-legacy" | "middle" | "start-legacy" | "start";
verticalAlign: "end" | "middle" | "start";
url: string;
text: string;
};
type: "note";
x: number;
y: number;
rotation: number;
index: string;
parentId: TLParentId;
isLocked: boolean;
opacity: number;
id: TLShapeId;
typeName: "shape";
} | undefined;
// (undocumented)
onEditEnd: TLOnEditEndHandler<TLNoteShape>;
// (undocumented)
toSvg(shape: TLNoteShape, ctx: SvgExportContext): SVGGElement;
// (undocumented)
static type: "note";
}
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function openWindow(url: string, target?: string): void;
// @internal (undocumented)
export function OptionalErrorBoundary({ children, fallback, ...props }: Omit<TLErrorBoundaryProps, 'fallback'> & {
fallback: TLErrorFallbackComponent;
2023-04-25 11:01:25 +00:00
}): JSX.Element;
`ExternalContentManager` for handling external content (files, images, etc) (#1550) This PR improves the editor's APIs around creating assets and files. This allows end user developers to replace behavior that might occur, for example, when pasting images or dragging files onto the canvas. Here, we: - remove `onCreateAssetFromFile` prop - remove `onCreateBookmarkFromUrl` prop - introduce `onEditorReady` prop - introduce `onEditorWillDispose` prop - introduce `ExternalContentManager` The `ExternalContentManager` (ECM) is used in circumstances where we're turning external content (text, images, urls, etc) into assets or shapes. It is designed to allow certain methods to be overwritten by other developers as a kind of weakly supported hack. For example, when a user drags an image onto the canvas, the event handler passes a `TLExternalContent` object to the editor's `putExternalContent` method. This method runs the ECM's handler for this content type. That handler may in turn run other methods, such as `createAssetFromFile` or `createShapesForAssets`, which will lead to the image being created on the canvas. If a developer wanted to change the way that assets are created from files, then they could overwrite that method at runtime. ```ts const handleEditorReady = (editor: Editor) => { editor.externalContentManager.createAssetFromFile = myHandler } function Example() { return <Tldraw onEditorReady={handleEditorReady}/> } ``` If you wanted to go even deeper, you could override the editor's `putExternalContent` method. ```ts const handleEditorReady = (editor: Editor) => { const handleExternalContent = (info: TLExternalContent): Promise<void> => { if (info.type === 'files') { // do something here } else { // do the normal thing editor.externalContentManager.handleContent(info) } } ``` ### Change Type - [x] `major` ### Test Plan 1. Drag images, urls, etc. onto the canvas 2. Use copy and paste for single and multiple files 3. Use bookmark / embed shapes and convert between eachother ### Release Notes - [editor] add `ExternalContentManager` for plopping content onto the canvas - [editor] remove `onCreateAssetFromFile` prop - [editor] remove `onCreateBookmarkFromUrl` prop - [editor] introduce `onEditorReady` prop - [editor] introduce `onEditorWillDispose` prop - [editor] introduce `ExternalContentManager`
2023-06-08 14:53:11 +00:00
// @public (undocumented)
export class PlopManager {
constructor(editor: Editor);
createAssetFromFile(_editor: Editor, file: File): Promise<TLAsset>;
createAssetFromUrl(_editor: Editor, url: string): Promise<TLAsset>;
// (undocumented)
createShapesForAssets(editor: Editor, assets: TLAsset[], position: VecLike): Promise<void>;
// (undocumented)
editor: Editor;
// (undocumented)
handleContent: (info: TLExternalContent) => Promise<void>;
handleEmbed(editor: Editor, { point, url, embed }: Extract<TLExternalContent, {
type: 'embed';
}>): Promise<void>;
handleFiles(editor: Editor, { point, files }: Extract<TLExternalContent, {
type: 'files';
}>): Promise<void>;
handleSvgText(editor: Editor, { point, text }: Extract<TLExternalContent, {
type: 'svg-text';
}>): Promise<void>;
handleText(editor: Editor, { point, text }: Extract<TLExternalContent, {
type: 'text';
}>): Promise<void>;
handleUrl: (editor: Editor, { point, url }: Extract<TLExternalContent, {
type: 'url';
}>) => Promise<void>;
}
2023-04-25 11:01:25 +00:00
// @public
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
export function preventDefault(event: Event | React_2.BaseSyntheticEvent): void;
2023-04-25 11:01:25 +00:00
export { react }
// @public
export class ReadonlySharedStyleMap {
// (undocumented)
[Symbol.iterator](): IterableIterator<[StyleProp<unknown>, SharedStyle<unknown>]>;
constructor(entries?: Iterable<[StyleProp<unknown>, SharedStyle<unknown>]>);
// (undocumented)
entries(): IterableIterator<[StyleProp<unknown>, SharedStyle<unknown>]>;
// (undocumented)
equals(other: ReadonlySharedStyleMap): boolean;
// (undocumented)
get<T>(prop: StyleProp<T>): SharedStyle<T> | undefined;
// (undocumented)
getAsKnownValue<T>(prop: StyleProp<T>): T | undefined;
// (undocumented)
keys(): IterableIterator<StyleProp<unknown>>;
// @internal (undocumented)
protected map: Map<StyleProp<unknown>, SharedStyle<unknown>>;
// (undocumented)
get size(): number;
// (undocumented)
values(): IterableIterator<SharedStyle<unknown>>;
}
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function refreshPage(): void;
// @public (undocumented)
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
export function releasePointerCapture(element: Element, event: PointerEvent | React_2.PointerEvent<Element>): void;
2023-04-25 11:01:25 +00:00
// @internal (undocumented)
export const REMOVE_SYMBOL: unique symbol;
// @public (undocumented)
export type RequiredKeys<T, K extends keyof T> = Pick<T, K> & Partial<T>;
// @internal (undocumented)
export const RICH_TYPES: Record<string, boolean>;
// @public (undocumented)
export const runtime: {
openWindow: (url: string, target: string) => void;
refreshPage: () => void;
hardReset: () => void;
};
// @internal (undocumented)
export function setDefaultEditorAssetUrls(assetUrls: TLEditorAssetUrls): void;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
export function setPointerCapture(element: Element, event: PointerEvent | React_2.PointerEvent<Element>): void;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function setRuntimeOverrides(input: Partial<typeof runtime>): void;
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
// @public (undocumented)
export function setUserPreferences(user: TLUserPreferences): void;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
constructor(editor: Editor, type: Shape['type'], styleProps: ReadonlyMap<StyleProp<unknown>, string>);
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
// @internal
backgroundComponent?(shape: Shape): any;
canBind: <K>(_shape: Shape, _otherShape?: K | undefined) => boolean;
canCrop: TLShapeUtilFlag<Shape>;
canDropShapes(shape: Shape, shapes: TLShape[]): boolean;
canEdit: TLShapeUtilFlag<Shape>;
canReceiveNewChildrenOfType(shape: Shape, type: TLShape['type']): boolean;
canResize: TLShapeUtilFlag<Shape>;
canScroll: TLShapeUtilFlag<Shape>;
canSnap: TLShapeUtilFlag<Shape>;
canUnmount: TLShapeUtilFlag<Shape>;
center(shape: Shape): Vec2d;
abstract component(shape: Shape): any;
// (undocumented)
editor: Editor;
// @internal (undocumented)
expandSelectionOutlinePx(shape: Shape): number;
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
abstract getBounds(shape: Shape): Box2d;
getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[];
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getCenter(shape: Shape): Vec2d;
abstract getDefaultProps(): Shape['props'];
getHandles?(shape: Shape): TLHandle[];
getOutline(shape: Shape): Vec2d[];
getOutlineSegments(shape: Shape): Vec2d[][];
hideResizeHandles: TLShapeUtilFlag<Shape>;
hideRotateHandle: TLShapeUtilFlag<Shape>;
hideSelectionBoundsBg: TLShapeUtilFlag<Shape>;
hideSelectionBoundsFg: TLShapeUtilFlag<Shape>;
hitTestLineSegment(shape: Shape, A: VecLike, B: VecLike): boolean;
hitTestPoint(shape: Shape, point: VecLike): boolean;
abstract indicator(shape: Shape): any;
isAspectRatioLocked: TLShapeUtilFlag<Shape>;
isClosed: TLShapeUtilFlag<Shape>;
onBeforeCreate?: TLOnBeforeCreateHandler<Shape>;
onBeforeUpdate?: TLOnBeforeUpdateHandler<Shape>;
// @internal
onBindingChange?: TLOnBindingChangeHandler<Shape>;
onChildrenChange?: TLOnChildrenChangeHandler<Shape>;
onClick?: TLOnClickHandler<Shape>;
onDoubleClick?: TLOnDoubleClickHandler<Shape>;
onDoubleClickEdge?: TLOnDoubleClickHandler<Shape>;
onDoubleClickHandle?: TLOnDoubleClickHandleHandler<Shape>;
onDragShapesOut?: TLOnDragHandler<Shape>;
onDragShapesOver?: TLOnDragHandler<Shape, {
shouldHint: boolean;
}>;
onDropShapesOver?: TLOnDragHandler<Shape>;
onEditEnd?: TLOnEditEndHandler<Shape>;
onHandleChange?: TLOnHandleChangeHandler<Shape>;
onResize?: TLOnResizeHandler<Shape>;
onResizeEnd?: TLOnResizeEndHandler<Shape>;
onResizeStart?: TLOnResizeStartHandler<Shape>;
onRotate?: TLOnRotateHandler<Shape>;
onRotateEnd?: TLOnRotateEndHandler<Shape>;
onRotateStart?: TLOnRotateStartHandler<Shape>;
onTranslate?: TLOnTranslateHandler<Shape>;
onTranslateEnd?: TLOnTranslateEndHandler<Shape>;
onTranslateStart?: TLOnTranslateStartHandler<Shape>;
// @internal
providesBackgroundForChildren(shape: Shape): boolean;
// (undocumented)
setStyleInPartial<T>(style: StyleProp<T>, shape: TLShapePartial<Shape>, value: T): TLShapePartial<Shape>;
snapPoints(shape: Shape): Vec2d[];
// (undocumented)
readonly styleProps: ReadonlyMap<StyleProp<unknown>, string>;
toBackgroundSvg?(shape: Shape, ctx: SvgExportContext): null | Promise<SVGElement> | SVGElement;
toSvg?(shape: Shape, ctx: SvgExportContext): Promise<SVGElement> | SVGElement;
// (undocumented)
readonly type: Shape['type'];
static type: string;
}
2023-04-25 11:01:25 +00:00
// @public
export type SharedStyle<T> = {
readonly type: 'mixed';
} | {
readonly type: 'shared';
readonly value: T;
};
// @internal (undocumented)
export class SharedStyleMap extends ReadonlySharedStyleMap {
// (undocumented)
applyValue<T>(prop: StyleProp<T>, value: T): void;
// (undocumented)
set<T>(prop: StyleProp<T>, value: SharedStyle<T>): void;
}
// @public (undocumented)
export function snapToGrid(n: number, gridSize: number): number;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export abstract class StateNode implements Partial<TLEventHandlers> {
constructor(editor: Editor, parent?: StateNode);
2023-04-25 11:01:25 +00:00
// (undocumented)
static children?: () => TLStateNodeConstructor[];
2023-04-25 11:01:25 +00:00
// (undocumented)
children?: Record<string, StateNode>;
// (undocumented)
current: Atom<StateNode | undefined>;
// (undocumented)
editor: Editor;
// (undocumented)
2023-04-25 11:01:25 +00:00
enter(info: any, from: string): void;
// (undocumented)
exit(info: any, from: string): void;
// (undocumented)
handleEvent(info: Exclude<TLEventInfo, TLPinchEventInfo>): void;
// (undocumented)
static id: string;
// (undocumented)
id: string;
// (undocumented)
static initial?: string;
// (undocumented)
initial?: string;
// (undocumented)
isActive: boolean;
// (undocumented)
onCancel?: TLEventHandlers['onCancel'];
// (undocumented)
onComplete?: TLEventHandlers['onComplete'];
// (undocumented)
onDoubleClick?: TLEventHandlers['onDoubleClick'];
// (undocumented)
onEnter?: TLEnterEventHandler;
2023-04-25 11:01:25 +00:00
// (undocumented)
onExit?: TLExitEventHandler;
2023-04-25 11:01:25 +00:00
// (undocumented)
onInterrupt?: TLEventHandlers['onInterrupt'];
// (undocumented)
onKeyDown?: TLEventHandlers['onKeyDown'];
// (undocumented)
onKeyRepeat?: TLEventHandlers['onKeyRepeat'];
// (undocumented)
onKeyUp?: TLEventHandlers['onKeyUp'];
// (undocumented)
onMiddleClick?: TLEventHandlers['onMiddleClick'];
// (undocumented)
onPointerDown?: TLEventHandlers['onPointerDown'];
// (undocumented)
onPointerEnter?: TLEventHandlers['onPointerEnter'];
// (undocumented)
onPointerLeave?: TLEventHandlers['onPointerLeave'];
// (undocumented)
onPointerMove?: TLEventHandlers['onPointerMove'];
// (undocumented)
onPointerUp?: TLEventHandlers['onPointerUp'];
// (undocumented)
onQuadrupleClick?: TLEventHandlers['onQuadrupleClick'];
// (undocumented)
onRightClick?: TLEventHandlers['onRightClick'];
// (undocumented)
onTripleClick?: TLEventHandlers['onTripleClick'];
// (undocumented)
onWheel?: TLEventHandlers['onWheel'];
// (undocumented)
parent: StateNode;
// (undocumented)
path: Computed<string>;
// (undocumented)
shapeType?: TLShapeUtilConstructor<TLBaseShape<any, any>>;
2023-04-25 11:01:25 +00:00
// (undocumented)
transition(id: string, info: any): this;
// (undocumented)
type: TLStateNodeType;
2023-04-25 11:01:25 +00:00
}
// @internal (undocumented)
export const SVG_PADDING = 32;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function SVGContainer({ children, className, ...rest }: SVGContainerProps): JSX.Element;
// @public (undocumented)
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
export type SVGContainerProps = React_3.HTMLAttributes<SVGElement>;
2023-04-25 11:01:25 +00:00
Independent instance state persistence (#1493) This PR - Removes UserDocumentRecordType - moving isSnapMode to user preferences - moving isGridMode and isPenMode to InstanceRecordType - deleting the other properties which are no longer needed. - Creates a separate pipeline for persisting instance state. Previously the instance state records were stored alongside the document state records, and in order to load the state for a particular instance (in our case, a particular tab) you needed to pass the 'instanceId' prop. This prop ended up totally pervading the public API and people ran into all kinds of issues with it, e.g. using the same instance id in multiple editor instances. There was also an issue whereby it was hard for us to clean up old instance state so the idb table ended up bloating over time. This PR makes it so that rather than passing an instanceId, you load the instance state yourself while creating the store. It provides tools to make that easy. - Undoes the assumption that we might have more than one instance's state in the store. - Like `document`, `instance` now has a singleton id `instance:instance`. - Page state ids and camera ids are no longer random, but rather derive from the page they belong to. This is like having a foreign primary key in SQL databases. It's something i'd love to support fully as part of the RecordType/Store api. Tests to do - [x] Test Migrations - [x] Test Store.listen filtering - [x] Make type sets in Store public and readonly - [x] Test RecordType.createId - [x] Test Instance state snapshot loading/exporting - [x] Manual test File I/O - [x] Manual test Vscode extension with multiple tabs - [x] Audit usages of store.query - [x] Audit usages of changed types: InstanceRecordType, 'instance', InstancePageStateRecordType, 'instance_page_state', 'user_document', 'camera', CameraRecordType, InstancePresenceRecordType, 'instance_presence' - [x] Test user preferences - [x] Manual test isSnapMode and isGridMode and isPenMode - [ ] Test indexedDb functions - [x] Add instanceId stuff back ### Change Type - [x] `major` — Breaking Change ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] Webdriver tests ### Release Notes - Add a brief release note for your PR here.
2023-06-05 14:11:07 +00:00
// @public
export const TAB_ID: string;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export const TextShape: TLShapeInfo<TLTextShape>;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export class TextShapeUtil extends ShapeUtil<TLTextShape> {
2023-04-25 11:01:25 +00:00
// (undocumented)
canEdit: () => boolean;
// (undocumented)
component(shape: TLTextShape): JSX.Element;
// (undocumented)
getBounds(shape: TLTextShape): Box2d;
2023-04-25 11:01:25 +00:00
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLTextShape['props'];
2023-04-25 11:01:25 +00:00
// (undocumented)
getMinDimensions(shape: TLTextShape): {
height: number;
width: number;
};
2023-04-25 11:01:25 +00:00
// (undocumented)
getOutline(shape: TLTextShape): Vec2d[];
2023-04-25 11:01:25 +00:00
// (undocumented)
indicator(shape: TLTextShape): JSX.Element;
2023-04-25 11:01:25 +00:00
// (undocumented)
isAspectRatioLocked: TLShapeUtilFlag<TLTextShape>;
2023-04-25 11:01:25 +00:00
// (undocumented)
onBeforeCreate: (shape: TLTextShape) => {
x: number;
y: number;
type: "text";
rotation: number;
index: string;
parentId: TLParentId;
isLocked: boolean;
opacity: number;
props: {
color: "black" | "blue" | "green" | "grey" | "light-blue" | "light-green" | "light-red" | "light-violet" | "orange" | "red" | "violet" | "yellow";
size: "l" | "m" | "s" | "xl";
font: "draw" | "mono" | "sans" | "serif";
align: "end-legacy" | "end" | "middle-legacy" | "middle" | "start-legacy" | "start";
w: number;
text: string;
scale: number;
autoSize: boolean;
};
id: TLShapeId;
typeName: "shape";
} | undefined;
2023-04-25 11:01:25 +00:00
// (undocumented)
onBeforeUpdate: (prev: TLTextShape, next: TLTextShape) => {
x: number;
y: number;
props: {
w: number;
color: "black" | "blue" | "green" | "grey" | "light-blue" | "light-green" | "light-red" | "light-violet" | "orange" | "red" | "violet" | "yellow";
size: "l" | "m" | "s" | "xl";
font: "draw" | "mono" | "sans" | "serif";
align: "end-legacy" | "end" | "middle-legacy" | "middle" | "start-legacy" | "start";
text: string;
scale: number;
autoSize: boolean;
};
type: "text";
rotation: number;
index: string;
parentId: TLParentId;
isLocked: boolean;
opacity: number;
id: TLShapeId;
typeName: "shape";
} | undefined;
2023-04-25 11:01:25 +00:00
// (undocumented)
onDoubleClickEdge: (shape: TLTextShape) => {
id: TLShapeId;
type: "text";
props: {
autoSize: boolean;
scale?: undefined;
};
} | {
id: TLShapeId;
type: "text";
props: {
scale: number;
autoSize?: undefined;
};
} | undefined;
2023-04-25 11:01:25 +00:00
// (undocumented)
onEditEnd: TLOnEditEndHandler<TLTextShape>;
2023-04-25 11:01:25 +00:00
// (undocumented)
onResize: TLOnResizeHandler<TLTextShape>;
2023-04-25 11:01:25 +00:00
// (undocumented)
toSvg(shape: TLTextShape, ctx: SvgExportContext): SVGGElement;
2023-04-25 11:01:25 +00:00
// (undocumented)
static type: "text";
2023-04-25 11:01:25 +00:00
}
// @public (undocumented)
export type TLAnimationOptions = Partial<{
duration: number;
easing: typeof EASINGS.easeInOutCubic;
}>;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export type TLBaseBoxShape = TLBaseShape<string, {
2023-04-25 11:01:25 +00:00
w: number;
h: number;
}>;
// @public (undocumented)
export interface TLBaseEventInfo {
2023-04-25 11:01:25 +00:00
// (undocumented)
altKey: boolean;
2023-04-25 11:01:25 +00:00
// (undocumented)
ctrlKey: boolean;
2023-04-25 11:01:25 +00:00
// (undocumented)
shiftKey: boolean;
2023-04-25 11:01:25 +00:00
// (undocumented)
type: UiEventType;
2023-04-25 11:01:25 +00:00
}
// @public (undocumented)
export type TLCancelEvent = (info: TLCancelEventInfo) => void;
// @public (undocumented)
export type TLCancelEventInfo = {
type: 'misc';
name: 'cancel';
};
// @public (undocumented)
export type TLClickEvent = (info: TLClickEventInfo) => void;
// @public (undocumented)
export type TLClickEventInfo = TLBaseEventInfo & {
type: 'click';
name: TLCLickEventName;
point: VecLike;
pointerId: number;
button: number;
phase: 'down' | 'settle' | 'up';
} & TLPointerEventTarget;
// @public (undocumented)
export type TLCLickEventName = 'double_click' | 'quadruple_click' | 'triple_click';
// @public (undocumented)
export type TLCommand<Name extends string = any, Data = any> = {
type: 'command';
id: string;
data: Data;
name: Name;
preservesRedoStack?: boolean;
};
// @public (undocumented)
export type TLCommandHandler<Data> = {
do: (data: Data) => void;
undo: (data: Data) => void;
redo?: (data: Data) => void;
squash?: (prevData: Data, nextData: Data) => Data;
};
// @public (undocumented)
export type TLCompleteEvent = (info: TLCompleteEventInfo) => void;
// @public (undocumented)
export type TLCompleteEventInfo = {
type: 'misc';
name: 'complete';
};
// @public (undocumented)
export interface TLContent {
// (undocumented)
assets: TLAsset[];
// (undocumented)
rootShapeIds: TLShapeId[];
// (undocumented)
schema: SerializedSchema;
// (undocumented)
shapes: TLShape[];
}
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export type TLCopyType = 'jpeg' | 'json' | 'png' | 'svg';
// @public (undocumented)
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
export const TldrawEditor: React_2.NamedExoticComponent<TldrawEditorProps>;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
export type TldrawEditorProps = {
children?: any;
shapes?: readonly AnyTLShapeInfo[];
tools?: readonly TLStateNodeConstructor[];
assetUrls?: RecursivePartial<TLEditorAssetUrls>;
2023-04-25 11:01:25 +00:00
autoFocus?: boolean;
components?: Partial<TLEditorComponents>;
`ExternalContentManager` for handling external content (files, images, etc) (#1550) This PR improves the editor's APIs around creating assets and files. This allows end user developers to replace behavior that might occur, for example, when pasting images or dragging files onto the canvas. Here, we: - remove `onCreateAssetFromFile` prop - remove `onCreateBookmarkFromUrl` prop - introduce `onEditorReady` prop - introduce `onEditorWillDispose` prop - introduce `ExternalContentManager` The `ExternalContentManager` (ECM) is used in circumstances where we're turning external content (text, images, urls, etc) into assets or shapes. It is designed to allow certain methods to be overwritten by other developers as a kind of weakly supported hack. For example, when a user drags an image onto the canvas, the event handler passes a `TLExternalContent` object to the editor's `putExternalContent` method. This method runs the ECM's handler for this content type. That handler may in turn run other methods, such as `createAssetFromFile` or `createShapesForAssets`, which will lead to the image being created on the canvas. If a developer wanted to change the way that assets are created from files, then they could overwrite that method at runtime. ```ts const handleEditorReady = (editor: Editor) => { editor.externalContentManager.createAssetFromFile = myHandler } function Example() { return <Tldraw onEditorReady={handleEditorReady}/> } ``` If you wanted to go even deeper, you could override the editor's `putExternalContent` method. ```ts const handleEditorReady = (editor: Editor) => { const handleExternalContent = (info: TLExternalContent): Promise<void> => { if (info.type === 'files') { // do something here } else { // do the normal thing editor.externalContentManager.handleContent(info) } } ``` ### Change Type - [x] `major` ### Test Plan 1. Drag images, urls, etc. onto the canvas 2. Use copy and paste for single and multiple files 3. Use bookmark / embed shapes and convert between eachother ### Release Notes - [editor] add `ExternalContentManager` for plopping content onto the canvas - [editor] remove `onCreateAssetFromFile` prop - [editor] remove `onCreateBookmarkFromUrl` prop - [editor] introduce `onEditorReady` prop - [editor] introduce `onEditorWillDispose` prop - [editor] introduce `ExternalContentManager`
2023-06-08 14:53:11 +00:00
onMount?: (editor: Editor) => (() => void) | undefined | void;
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
} & ({
store: TLStore | TLStoreWithStatus;
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
} | {
store?: undefined;
initialData?: StoreSnapshot<TLRecord>;
persistenceKey?: string;
Independent instance state persistence (#1493) This PR - Removes UserDocumentRecordType - moving isSnapMode to user preferences - moving isGridMode and isPenMode to InstanceRecordType - deleting the other properties which are no longer needed. - Creates a separate pipeline for persisting instance state. Previously the instance state records were stored alongside the document state records, and in order to load the state for a particular instance (in our case, a particular tab) you needed to pass the 'instanceId' prop. This prop ended up totally pervading the public API and people ran into all kinds of issues with it, e.g. using the same instance id in multiple editor instances. There was also an issue whereby it was hard for us to clean up old instance state so the idb table ended up bloating over time. This PR makes it so that rather than passing an instanceId, you load the instance state yourself while creating the store. It provides tools to make that easy. - Undoes the assumption that we might have more than one instance's state in the store. - Like `document`, `instance` now has a singleton id `instance:instance`. - Page state ids and camera ids are no longer random, but rather derive from the page they belong to. This is like having a foreign primary key in SQL databases. It's something i'd love to support fully as part of the RecordType/Store api. Tests to do - [x] Test Migrations - [x] Test Store.listen filtering - [x] Make type sets in Store public and readonly - [x] Test RecordType.createId - [x] Test Instance state snapshot loading/exporting - [x] Manual test File I/O - [x] Manual test Vscode extension with multiple tabs - [x] Audit usages of store.query - [x] Audit usages of changed types: InstanceRecordType, 'instance', InstancePageStateRecordType, 'instance_page_state', 'user_document', 'camera', CameraRecordType, InstancePresenceRecordType, 'instance_presence' - [x] Test user preferences - [x] Manual test isSnapMode and isGridMode and isPenMode - [ ] Test indexedDb functions - [x] Add instanceId stuff back ### Change Type - [x] `major` — Breaking Change ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] Webdriver tests ### Release Notes - Add a brief release note for your PR here.
2023-06-05 14:11:07 +00:00
sessionId?: string;
Add support for project names (#1340) This PR adds some things that we need for the Project Name feature on tldraw.com. It should be reviewed alongside https://github.com/tldraw/tldraw-lite/pull/1814 ## Name Property This PR adds a `name` property to `TLDocument`. We use this to store a project's name. <img width="454" alt="Screenshot 2023-05-09 at 15 47 26" src="https://github.com/tldraw/tldraw/assets/15892272/f3be438e-aa0f-4dec-8f51-8dfd9f9d0ced"> ## Top Zone This PR adds a `topZone` area of the UI that we can add stuff to, similar to how `shareZone` works. It also adds an example to show where the `topZone` and `shareZone` are: <img width="1511" alt="Screenshot 2023-05-12 at 10 57 40" src="https://github.com/tldraw/tldraw/assets/15892272/f5e1cd33-017e-4aaf-bfee-4d85119e2974"> ## Breakpoints This PR change's the UI's breakpoints a little bit. It moves the action bar to the bottom a little bit earlier. (This gives us more space at the top for the project name). ![2023-05-12 at 11 08 26 - Fuchsia Bison](https://github.com/tldraw/tldraw/assets/15892272/34563cea-b1d1-47be-ac5e-5650ee0ba02d) ![2023-05-12 at 13 45 04 - Tan Mole](https://github.com/tldraw/tldraw/assets/15892272/ab190bd3-51d4-4a8b-88de-c72ab14bcba6) ## Input Blur This PR adds an `onBlur` parameter to `Input`. This was needed because 'clicking off' the input wasn't firing `onComplete` or `onCancel`. <img width="620" alt="Screenshot 2023-05-09 at 16 12 58" src="https://github.com/tldraw/tldraw/assets/15892272/3b28da74-0a74-4063-8053-e59e47027caf"> ## Create Project Name This PR adds an internal `createProjectName` property to `TldrawEditorConfig`. Similar to `derivePresenceState`, you can pass a custom function to it. It lets you control what gets used as the default project name. We use it to set different names in our local projects compared to shared projects. In the future, when we add more advanced project features, we could handle this better within the UI. <img width="454" alt="Screenshot 2023-05-09 at 15 47 26" src="https://github.com/tldraw/tldraw/assets/15892272/da9a4699-ac32-40d9-a97c-6c682acfac41"> ### Test Plan 1. Gradually reduce the width of the browser window. 2. Check that the actions menu jumps to the bottom before the style panel moves to the bottom. --- 1. In the examples app, open the `/zones` example. 2. Check that there's a 'top zone' at the top. - [ ] Unit Tests - [ ] Webdriver tests ### Release Note - [dev] Added a `topZone` area where you can put stuff. - [dev] Added a `name` property to `TLDocument` - and `app` methods for it. - [dev] Added an internal `createProjectName` config property for controlling the default project name. - [dev] Added an `onBlur` parameter to `Input`. - Moved the actions bar to the bottom on medium-sized screens. --------- Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
2023-06-01 18:46:26 +00:00
defaultName?: string;
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
});
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export type TLEditorAssetUrls = {
fonts: {
monospace: string;
serif: string;
sansSerif: string;
draw: string;
};
};
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export interface TLEditorComponents {
// (undocumented)
Background: null | TLBackgroundComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
Brush: null | TLBrushComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
CollaboratorBrush: null | TLBrushComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
CollaboratorCursor: null | TLCursorComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
CollaboratorHint: null | TLCollaboratorHintComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
CollaboratorScribble: null | TLScribbleComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
CollaboratorShapeIndicator: null | TLShapeIndicatorComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
Cursor: null | TLCursorComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
ErrorFallback: TLErrorFallbackComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
Grid: null | TLGridComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
Handle: null | TLHandleComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
Scribble: null | TLScribbleComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
ShapeErrorFallback: TLShapeErrorFallbackComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
ShapeIndicatorErrorFallback: TLShapeIndicatorErrorFallback;
2023-04-25 11:01:25 +00:00
// (undocumented)
SnapLine: null | TLSnapLineComponent;
2023-04-25 11:01:25 +00:00
// (undocumented)
Spinner: null | TLSpinnerComponent;
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
// (undocumented)
SvgDefs: null | TLSvgDefsComponent;
// (undocumented)
ZoomBrush: null | TLBrushComponent;
}
// @public (undocumented)
export interface TLEditorOptions {
getContainer: () => HTMLElement;
shapes: readonly AnyTLShapeInfo[];
store: TLStore;
tools: readonly TLStateNodeConstructor[];
user?: TLUser;
2023-04-25 11:01:25 +00:00
}
// @public (undocumented)
export type TLEmbedResult = {
definition: EmbedDefinition;
url: string;
embedUrl: string;
} | undefined;
// @public (undocumented)
export type TLEnterEventHandler = (info: any, from: string) => void;
// @public (undocumented)
export interface TLErrorBoundaryProps {
// (undocumented)
children: React_3.ReactNode;
// (undocumented)
fallback: (props: {
error: unknown;
}) => any;
// (undocumented)
onError?: ((error: unknown) => void) | null;
}
// @public (undocumented)
export interface TLEventHandlers {
// (undocumented)
onCancel: TLCancelEvent;
// (undocumented)
onComplete: TLCompleteEvent;
// (undocumented)
onDoubleClick: TLClickEvent;
// (undocumented)
onInterrupt: TLInterruptEvent;
// (undocumented)
onKeyDown: TLKeyboardEvent;
// (undocumented)
onKeyRepeat: TLKeyboardEvent;
// (undocumented)
onKeyUp: TLKeyboardEvent;
// (undocumented)
onMiddleClick: TLPointerEvent;
// (undocumented)
onPointerDown: TLPointerEvent;
// (undocumented)
onPointerEnter: TLPointerEvent;
// (undocumented)
onPointerLeave: TLPointerEvent;
// (undocumented)
onPointerMove: TLPointerEvent;
// (undocumented)
onPointerUp: TLPointerEvent;
// (undocumented)
onQuadrupleClick: TLClickEvent;
// (undocumented)
onRightClick: TLPointerEvent;
// (undocumented)
onTripleClick: TLClickEvent;
// (undocumented)
onWheel: TLWheelEvent;
}
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export type TLEventInfo = TLCancelEventInfo | TLClickEventInfo | TLCompleteEventInfo | TLInterruptEventInfo | TLKeyboardEventInfo | TLPinchEventInfo | TLPointerEventInfo | TLWheelEventInfo;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export interface TLEventMap {
2023-04-25 11:01:25 +00:00
// (undocumented)
'change-history': [{
reason: 'bail';
markId?: string;
} | {
reason: 'push' | 'redo' | 'undo';
}];
2023-04-25 11:01:25 +00:00
// (undocumented)
'mark-history': [{
id: string;
}];
2023-04-25 11:01:25 +00:00
// (undocumented)
'max-shapes': [{
name: string;
pageId: TLPageId;
count: number;
}];
2023-04-25 11:01:25 +00:00
// (undocumented)
'stop-camera-animation': [];
2023-04-25 11:01:25 +00:00
// (undocumented)
'stop-following': [];
2023-04-25 11:01:25 +00:00
// (undocumented)
change: [HistoryEntry<TLRecord>];
2023-04-25 11:01:25 +00:00
// (undocumented)
crash: [{
error: unknown;
}];
2023-04-25 11:01:25 +00:00
// (undocumented)
event: [TLEventInfo];
2023-04-25 11:01:25 +00:00
// (undocumented)
frame: [number];
// (undocumented)
mount: [];
// (undocumented)
tick: [number];
// (undocumented)
update: [];
2023-04-25 11:01:25 +00:00
}
// @public (undocumented)
export type TLEventMapHandler<T extends keyof TLEventMap> = (...args: TLEventMap[T]) => void;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export type TLEventName = 'cancel' | 'complete' | 'interrupt' | 'wheel' | TLCLickEventName | TLKeyboardEventName | TLPinchEventName | TLPointerEventName;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export type TLExitEventHandler = (info: any, to: string) => void;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export type TLExportType = 'jpeg' | 'json' | 'png' | 'svg' | 'webp';
2023-04-25 11:01:25 +00:00
`ExternalContentManager` for handling external content (files, images, etc) (#1550) This PR improves the editor's APIs around creating assets and files. This allows end user developers to replace behavior that might occur, for example, when pasting images or dragging files onto the canvas. Here, we: - remove `onCreateAssetFromFile` prop - remove `onCreateBookmarkFromUrl` prop - introduce `onEditorReady` prop - introduce `onEditorWillDispose` prop - introduce `ExternalContentManager` The `ExternalContentManager` (ECM) is used in circumstances where we're turning external content (text, images, urls, etc) into assets or shapes. It is designed to allow certain methods to be overwritten by other developers as a kind of weakly supported hack. For example, when a user drags an image onto the canvas, the event handler passes a `TLExternalContent` object to the editor's `putExternalContent` method. This method runs the ECM's handler for this content type. That handler may in turn run other methods, such as `createAssetFromFile` or `createShapesForAssets`, which will lead to the image being created on the canvas. If a developer wanted to change the way that assets are created from files, then they could overwrite that method at runtime. ```ts const handleEditorReady = (editor: Editor) => { editor.externalContentManager.createAssetFromFile = myHandler } function Example() { return <Tldraw onEditorReady={handleEditorReady}/> } ``` If you wanted to go even deeper, you could override the editor's `putExternalContent` method. ```ts const handleEditorReady = (editor: Editor) => { const handleExternalContent = (info: TLExternalContent): Promise<void> => { if (info.type === 'files') { // do something here } else { // do the normal thing editor.externalContentManager.handleContent(info) } } ``` ### Change Type - [x] `major` ### Test Plan 1. Drag images, urls, etc. onto the canvas 2. Use copy and paste for single and multiple files 3. Use bookmark / embed shapes and convert between eachother ### Release Notes - [editor] add `ExternalContentManager` for plopping content onto the canvas - [editor] remove `onCreateAssetFromFile` prop - [editor] remove `onCreateBookmarkFromUrl` prop - [editor] introduce `onEditorReady` prop - [editor] introduce `onEditorWillDispose` prop - [editor] introduce `ExternalContentManager`
2023-06-08 14:53:11 +00:00
// @public (undocumented)
export type TLExternalContent = {
type: 'embed';
url: string;
point?: VecLike;
embed: EmbedDefinition;
} | {
type: 'files';
files: File[];
point?: VecLike;
ignoreParent: boolean;
} | {
type: 'svg-text';
text: string;
point?: VecLike;
} | {
type: 'text';
point?: VecLike;
text: string;
} | {
type: 'url';
url: string;
point?: VecLike;
};
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export type TLHistoryEntry = TLCommand | TLHistoryMark;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export type TLHistoryMark = {
2023-04-25 11:01:25 +00:00
type: 'STOP';
id: string;
onUndo: boolean;
onRedo: boolean;
};
// @public (undocumented)
export type TLInterruptEvent = (info: TLInterruptEventInfo) => void;
// @public (undocumented)
export type TLInterruptEventInfo = {
type: 'misc';
name: 'interrupt';
};
// @public (undocumented)
export type TLKeyboardEvent = (info: TLKeyboardEventInfo) => void;
// @public (undocumented)
export type TLKeyboardEventInfo = TLBaseEventInfo & {
type: 'keyboard';
name: TLKeyboardEventName;
key: string;
code: string;
};
// @public (undocumented)
export type TLKeyboardEventName = 'key_down' | 'key_repeat' | 'key_up';
// @public (undocumented)
export type TLOnBeforeCreateHandler<T extends TLShape> = (next: T) => T | void;
// @public (undocumented)
export type TLOnBeforeUpdateHandler<T extends TLShape> = (prev: T, next: T) => T | void;
// @internal (undocumented)
export type TLOnBindingChangeHandler<T extends TLShape> = (shape: T) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnChildrenChangeHandler<T extends TLShape> = (shape: T) => TLShapePartial[] | void;
// @public (undocumented)
export type TLOnClickHandler<T extends TLShape> = (shape: T) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnDoubleClickHandleHandler<T extends TLShape> = (shape: T, handle: TLHandle) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnDoubleClickHandler<T extends TLShape> = (shape: T) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnDragHandler<T extends TLShape, R = void> = (shape: T, shapes: TLShape[]) => R;
// @public (undocumented)
export type TLOnEditEndHandler<T extends TLShape> = (shape: T) => void;
// @public (undocumented)
export type TLOnHandleChangeHandler<T extends TLShape> = (shape: T, info: {
handle: TLHandle;
isPrecise: boolean;
}) => TLShapePartial<T> | void;
// @public (undocumented)
export type TLOnResizeEndHandler<T extends TLShape> = TLEventChangeHandler<T>;
// @public (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
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>;
// @public (undocumented)
export type TLOnRotateEndHandler<T extends TLShape> = TLEventChangeHandler<T>;
// @public (undocumented)
export type TLOnRotateHandler<T extends TLShape> = TLEventChangeHandler<T>;
// @public (undocumented)
export type TLOnRotateStartHandler<T extends TLShape> = TLEventStartHandler<T>;
// @public (undocumented)
export type TLOnTranslateEndHandler<T extends TLShape> = TLEventChangeHandler<T>;
// @public (undocumented)
export type TLOnTranslateHandler<T extends TLShape> = TLEventChangeHandler<T>;
// @public (undocumented)
export type TLOnTranslateStartHandler<T extends TLShape> = TLEventStartHandler<T>;
// @public (undocumented)
2023-04-25 11:01:25 +00:00
export type TLPinchEvent = (info: TLPinchEventInfo) => void;
// @public (undocumented)
export type TLPinchEventInfo = TLBaseEventInfo & {
type: 'pinch';
name: TLPinchEventName;
point: Vec2dModel;
delta: Vec2dModel;
};
// @public (undocumented)
export type TLPinchEventName = 'pinch_end' | 'pinch_start' | 'pinch';
// @public (undocumented)
export type TLPointerEvent = (info: TLPointerEventInfo) => void;
// @public (undocumented)
export type TLPointerEventInfo = TLBaseEventInfo & {
type: 'pointer';
name: TLPointerEventName;
point: VecLike;
pointerId: number;
button: number;
isPen: boolean;
} & TLPointerEventTarget;
// @public (undocumented)
export type TLPointerEventName = 'middle_click' | 'pointer_down' | 'pointer_enter' | 'pointer_leave' | 'pointer_move' | 'pointer_up' | 'right_click';
// @public (undocumented)
export type TLPointerEventTarget = {
target: 'canvas';
shape?: undefined;
} | {
target: 'handle';
shape: TLShape;
handle: TLHandle;
} | {
target: 'selection';
handle?: TLSelectionHandle;
shape?: undefined;
} | {
target: 'shape';
shape: TLShape;
};
// @public (undocumented)
export type TLResizeHandle = SelectionCorner | SelectionEdge;
// @public
export type TLResizeInfo<T extends TLShape> = {
newPoint: Vec2d;
handle: TLResizeHandle;
mode: TLResizeMode;
scaleX: number;
scaleY: number;
initialBounds: Box2d;
initialShape: T;
};
2023-04-25 11:01:25 +00:00
// @public
export type TLResizeMode = 'resize_bounds' | 'scale_shape';
// @public (undocumented)
export type TLSelectionHandle = RotateCorner | SelectionCorner | SelectionEdge;
Independent instance state persistence (#1493) This PR - Removes UserDocumentRecordType - moving isSnapMode to user preferences - moving isGridMode and isPenMode to InstanceRecordType - deleting the other properties which are no longer needed. - Creates a separate pipeline for persisting instance state. Previously the instance state records were stored alongside the document state records, and in order to load the state for a particular instance (in our case, a particular tab) you needed to pass the 'instanceId' prop. This prop ended up totally pervading the public API and people ran into all kinds of issues with it, e.g. using the same instance id in multiple editor instances. There was also an issue whereby it was hard for us to clean up old instance state so the idb table ended up bloating over time. This PR makes it so that rather than passing an instanceId, you load the instance state yourself while creating the store. It provides tools to make that easy. - Undoes the assumption that we might have more than one instance's state in the store. - Like `document`, `instance` now has a singleton id `instance:instance`. - Page state ids and camera ids are no longer random, but rather derive from the page they belong to. This is like having a foreign primary key in SQL databases. It's something i'd love to support fully as part of the RecordType/Store api. Tests to do - [x] Test Migrations - [x] Test Store.listen filtering - [x] Make type sets in Store public and readonly - [x] Test RecordType.createId - [x] Test Instance state snapshot loading/exporting - [x] Manual test File I/O - [x] Manual test Vscode extension with multiple tabs - [x] Audit usages of store.query - [x] Audit usages of changed types: InstanceRecordType, 'instance', InstancePageStateRecordType, 'instance_page_state', 'user_document', 'camera', CameraRecordType, InstancePresenceRecordType, 'instance_presence' - [x] Test user preferences - [x] Manual test isSnapMode and isGridMode and isPenMode - [ ] Test indexedDb functions - [x] Add instanceId stuff back ### Change Type - [x] `major` — Breaking Change ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] Webdriver tests ### Release Notes - Add a brief release note for your PR here.
2023-06-05 14:11:07 +00:00
// @public
export interface TLSessionStateSnapshot {
// (undocumented)
currentPageId: TLPageId;
// (undocumented)
exportBackground: boolean;
// (undocumented)
isDebugMode: boolean;
// (undocumented)
isFocusMode: boolean;
// (undocumented)
isGridMode: boolean;
// (undocumented)
isToolLocked: boolean;
// (undocumented)
pageStates: Array<{
pageId: TLPageId;
camera: {
x: number;
y: number;
z: number;
};
selectedIds: TLShapeId[];
focusLayerId: null | TLShapeId;
}>;
// (undocumented)
version: number;
}
// @public (undocumented)
export type TLShapeInfo<T extends TLUnknownShape = TLUnknownShape> = {
type: T['type'];
util: TLShapeUtilConstructor<T>;
props?: ShapeProps<T>;
migrations?: Migrations;
tool?: TLStateNodeConstructor;
};
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export interface TLShapeUtilConstructor<T extends TLUnknownShape, U extends ShapeUtil<T> = ShapeUtil<T>> {
// (undocumented)
new (editor: Editor, type: T['type'], styleProps: ReadonlyMap<StyleProp<unknown>, string>): U;
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
// (undocumented)
type: T['type'];
2023-04-25 11:01:25 +00:00
}
// @public (undocumented)
export type TLShapeUtilFlag<T> = (shape: T) => boolean;
// @public (undocumented)
export interface TLStateNodeConstructor {
2023-04-25 11:01:25 +00:00
// (undocumented)
new (editor: Editor, parent?: StateNode): StateNode;
2023-04-25 11:01:25 +00:00
// (undocumented)
children?: () => TLStateNodeConstructor[];
2023-04-25 11:01:25 +00:00
// (undocumented)
id: string;
2023-04-25 11:01:25 +00:00
// (undocumented)
initial?: string;
2023-04-25 11:01:25 +00:00
}
// @public (undocumented)
export type TLStoreEventInfo = HistoryEntry<TLRecord>;
// @public (undocumented)
export type TLStoreOptions = {
initialData?: StoreSnapshot<TLRecord>;
defaultName?: string;
} & ({
schema: StoreSchema<TLRecord, TLStoreProps>;
} | {
shapes: readonly AnyTLShapeInfo[];
});
// @public (undocumented)
export type TLStoreWithStatus = {
readonly status: 'error';
readonly store?: undefined;
readonly error: Error;
} | {
readonly status: 'loading';
readonly store?: undefined;
readonly error?: undefined;
} | {
readonly status: 'not-synced';
readonly store: TLStore;
readonly error?: undefined;
} | {
readonly status: 'synced-local';
readonly store: TLStore;
readonly error?: undefined;
} | {
readonly status: 'synced-remote';
readonly connectionStatus: 'offline' | 'online';
readonly store: TLStore;
readonly error?: undefined;
};
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export type TLTickEvent = (elapsed: number) => void;
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
// @public
export interface TLUserPreferences {
// (undocumented)
animationSpeed: number;
// (undocumented)
color: string;
// (undocumented)
id: string;
// (undocumented)
isDarkMode: boolean;
// (undocumented)
Independent instance state persistence (#1493) This PR - Removes UserDocumentRecordType - moving isSnapMode to user preferences - moving isGridMode and isPenMode to InstanceRecordType - deleting the other properties which are no longer needed. - Creates a separate pipeline for persisting instance state. Previously the instance state records were stored alongside the document state records, and in order to load the state for a particular instance (in our case, a particular tab) you needed to pass the 'instanceId' prop. This prop ended up totally pervading the public API and people ran into all kinds of issues with it, e.g. using the same instance id in multiple editor instances. There was also an issue whereby it was hard for us to clean up old instance state so the idb table ended up bloating over time. This PR makes it so that rather than passing an instanceId, you load the instance state yourself while creating the store. It provides tools to make that easy. - Undoes the assumption that we might have more than one instance's state in the store. - Like `document`, `instance` now has a singleton id `instance:instance`. - Page state ids and camera ids are no longer random, but rather derive from the page they belong to. This is like having a foreign primary key in SQL databases. It's something i'd love to support fully as part of the RecordType/Store api. Tests to do - [x] Test Migrations - [x] Test Store.listen filtering - [x] Make type sets in Store public and readonly - [x] Test RecordType.createId - [x] Test Instance state snapshot loading/exporting - [x] Manual test File I/O - [x] Manual test Vscode extension with multiple tabs - [x] Audit usages of store.query - [x] Audit usages of changed types: InstanceRecordType, 'instance', InstancePageStateRecordType, 'instance_page_state', 'user_document', 'camera', CameraRecordType, InstancePresenceRecordType, 'instance_presence' - [x] Test user preferences - [x] Manual test isSnapMode and isGridMode and isPenMode - [ ] Test indexedDb functions - [x] Add instanceId stuff back ### Change Type - [x] `major` — Breaking Change ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] Webdriver tests ### Release Notes - Add a brief release note for your PR here.
2023-06-05 14:11:07 +00:00
isSnapMode: boolean;
// (undocumented)
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
locale: string;
// (undocumented)
name: string;
}
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export type TLWheelEvent = (info: TLWheelEventInfo) => void;
// @public (undocumented)
export type TLWheelEventInfo = TLBaseEventInfo & {
type: 'wheel';
name: 'wheel';
delta: Vec2dModel;
};
export { track }
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export const truncateStringWithEllipsis: (str: string, maxLength: number) => string;
// @public (undocumented)
export type UiEvent = TLCancelEvent | TLClickEvent | TLCompleteEvent | TLKeyboardEvent | TLPinchEvent | TLPointerEvent;
// @public (undocumented)
export type UiEventType = 'click' | 'keyboard' | 'pinch' | 'pointer' | 'wheel' | 'zoom';
// @public
export function uniqueId(): string;
export { useComputed }
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function useContainer(): HTMLDivElement;
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export const useEditor: () => Editor;
2023-04-25 11:01:25 +00:00
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
// @internal (undocumented)
export function useLocalStore({ persistenceKey, sessionId, ...rest }: {
persistenceKey?: string;
sessionId?: string;
} & TLStoreOptions): TLStoreWithStatus;
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
// @internal (undocumented)
export function usePeerIds(): string[];
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export function usePrefersReducedMotion(): boolean;
// @internal (undocumented)
export function usePresence(userId: string): null | TLInstancePresence;
export { useQuickReactor }
2023-04-25 11:01:25 +00:00
// @internal (undocumented)
export const USER_COLORS: readonly ["#FF802B", "#EC5E41", "#F2555A", "#F04F88", "#E34BA9", "#BD54C6", "#9D5BD2", "#7B66DC", "#02B1CC", "#11B3A3", "#39B178", "#55B467"];
export { useReactor }
2023-04-25 11:01:25 +00:00
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
// @public (undocumented)
export function useTLStore(opts: TLStoreOptions): TLStore;
export { useValue }
// @public (undocumented)
export const VideoShape: TLShapeInfo<TLVideoShape>;
// @public (undocumented)
export class VideoShapeUtil extends BaseBoxShapeUtil<TLVideoShape> {
// (undocumented)
canEdit: () => boolean;
// (undocumented)
component(shape: TLVideoShape): JSX.Element;
// (undocumented)
`ShapeUtil` refactor, `Editor` cleanup (#1611) This PR improves the ergonomics of `ShapeUtil` classes. ### Cached methods First, I've remove the cached methods (such as `bounds`) from the `ShapeUtil` class and lifted this to the `Editor` class. Previously, calling `ShapeUtil.getBounds` would return the un-cached bounds of a shape, while calling `ShapeUtil.bounds` would return the cached bounds of a shape. We also had `Editor.getBounds`, which would call `ShapeUtil.bounds`. It was confusing. The cached methods like `outline` were also marked with "please don't override", which suggested the architecture was just wrong. The only weirdness from this is that utils sometimes reach out to the editor for cached versions of data rather than calling their own cached methods. It's still an easier story to tell than what we had before. ### More defaults We now have three and only three `abstract` methods for a `ShapeUtil`: - `getDefaultProps` (renamed from `defaultProps`) - `getBounds`, - `component` - `indicator` Previously, we also had `getCenter` as an abstract method, though this was usually just the middle of the bounds anyway. ### Editing bounds This PR removes the concept of editingBounds. The viewport will no longer animate to editing shapes. ### Active area manager This PR also removes the active area manager, which was not being used in the way we expected it to be. ### Dpr manager This PR removes the dpr manager and uses a hook instead to update it from React. This is one less runtime browser dependency in the app, one less thing to document. ### Moving things around This PR also continues to try to organize related methods and properties in the editor. ### Change Type - [x] `major` — Breaking change ### Release Notes - [editor] renames `defaultProps` to `getDefaultProps` - [editor] removes `outline`, `outlineSegments`, `handles`, `bounds` - [editor] renames `renderBackground` to `backgroundComponent`
2023-06-19 14:01:18 +00:00
getDefaultProps(): TLVideoShape['props'];
// (undocumented)
indicator(shape: TLVideoShape): JSX.Element;
// (undocumented)
isAspectRatioLocked: () => boolean;
// (undocumented)
toSvg(shape: TLVideoShape): SVGGElement;
// (undocumented)
static type: "video";
}
[refactor] User-facing APIs (#1478) This PR updates our user-facing APIs for the Tldraw and TldrawEditor components, as well as the Editor (App). It mainly incorporates surface changes from #1450 without any changes to validators or migrators, incorporating feedback / discussion with @SomeHats and @ds300. Here we: - remove the TldrawEditorConfig - bring back a loose version of shape definitions - make a separation between "core" shapes and "default" shapes - do not allow custom shapes, migrators or validators to overwrite core shapes - but _do_ allow new shapes ## `<Tldraw>` component In this PR, the `Tldraw` component wraps both the `TldrawEditor` component and our `TldrawUi` component. It accepts a union of props for both components. Previously, this component also added local syncing via a `useLocalSyncClient` hook call, however that has been pushed down to the `TldrawEditor` component. ## `<TldrawEditor>` component The `TldrawEditor` component now more neatly wraps up the different ways that the editor can be configured. ## The store prop (`TldrawEditorProps.store`) There are three main ways for the `TldrawEditor` component to be run: 1. with an externally defined store 2. with an externally defined syncing store (local or remote) 3. with an internally defined store 4. with an internally defined locally syncing store The `store` prop allows for these configurations. If the `store` prop is defined, it may be defined either as a `TLStore` or as a `SyncedStore`. If the store is a `TLStore`, then the Editor will assume that the store is ready to go; if it is defined as a SyncedStore, then the component will display the loading / error screens as needed, or the final editor once the store's status is "synced". When the store is left undefined, then the `TldrawEditor` will create its own internal store using the optional `instanceId`, `initialData`, or `shapes` props to define the store / store schema. If the `persistenceKey` prop is left undefined, then the store will not be synced. If the `persistenceKey` is defined, then the store will be synced locally. In the future, we may also here accept the API key / roomId / etc for creating a remotely synced store. The `SyncedStore` type has been expanded to also include types used for remote syncing, e.g. with `ConnectionStatus`. ## Tools By default, the App has two "baked-in" tools: the select tool and the zoom tool. These cannot (for now) be replaced or removed. The default tools are used by default, but may be replaced by other tools if provided. ## Shapes By default, the App has a set of "core" shapes: - group - embed - bookmark - image - video - text That cannot by overwritten because they're created by the app at different moments, such as when double clicking on the canvas or via a copy and paste event. In follow up PRs, we'll split these out so that users can replace parts of the code where these shapes are created. ### Change Type - [x] `major` — Breaking Change ### Test Plan - [x] Unit Tests
2023-06-01 15:47:34 +00:00
2023-04-25 11:01:25 +00:00
// @public (undocumented)
export class WeakMapCache<T extends object, K> {
// (undocumented)
access(item: T): K | undefined;
// (undocumented)
bust(): void;
// (undocumented)
get<P extends T>(item: P, cb: (item: P) => K): NonNullable<K>;
// (undocumented)
has(item: T): boolean;
// (undocumented)
invalidate(item: T): void;
// (undocumented)
items: WeakMap<T, K>;
// (undocumented)
set(item: T, value: K): void;
}
export { whyAmIRunning }
2023-04-25 11:01:25 +00:00
// @internal (undocumented)
export const ZOOMS: number[];
export * from "@tldraw/indices";
2023-04-25 11:01:25 +00:00
export * from "@tldraw/tlschema";
// (No @packageDocumentation comment for this package)
```