Adds copy, fix bug on mutating bound shapes, adds binding indicator, adds binding to text
This commit is contained in:
parent
89dfd22bac
commit
f6934dedb8
10 changed files with 174 additions and 58 deletions
|
@ -10,7 +10,7 @@ export function Defs({ zoom }: DefProps): JSX.Element {
|
|||
<circle id="dot" className="tl-counter-scaled tl-dot" r={4} />
|
||||
<circle id="handle-bg" className="tl-handle-bg" pointerEvents="all" r={12} />
|
||||
<circle id="handle" className="tl-counter-scaled tl-handle" pointerEvents="none" r={4} />
|
||||
<g id="cross" className="tl-binding-indicator">
|
||||
<g id="cross" className="tl-anchor-indicator">
|
||||
<line x1={-6} y1={-6} x2={6} y2={6} />
|
||||
<line x1={6} y1={-6} x2={-6} y2={6} />
|
||||
</g>
|
||||
|
|
|
@ -16,6 +16,7 @@ function addToShapeTree<T extends TLShape, M extends Record<string, unknown>>(
|
|||
shapes: TLPage<T, TLBinding>['shapes'],
|
||||
selectedIds: string[],
|
||||
pageState: {
|
||||
bindingTargetId?: string
|
||||
bindingId?: string
|
||||
hoveredId?: string
|
||||
currentParentId?: string
|
||||
|
@ -28,7 +29,7 @@ function addToShapeTree<T extends TLShape, M extends Record<string, unknown>>(
|
|||
shape,
|
||||
isCurrentParent: pageState.currentParentId === shape.id,
|
||||
isEditing: pageState.editingId === shape.id,
|
||||
isBinding: pageState.bindingId === shape.id,
|
||||
isBinding: pageState.bindingTargetId === shape.id,
|
||||
meta,
|
||||
}
|
||||
|
||||
|
@ -102,13 +103,17 @@ export function useShapeTree<T extends TLShape, M extends Record<string, unknown
|
|||
rPreviousCount.current = shapesToRender.length
|
||||
}
|
||||
|
||||
const bindingTargetId = pageState.bindingId ? page.bindings[pageState.bindingId].toId : undefined
|
||||
|
||||
// Populate the shape tree
|
||||
|
||||
const tree: IShapeTreeNode<M>[] = []
|
||||
|
||||
shapesToRender
|
||||
.sort((a, b) => a.childIndex - b.childIndex)
|
||||
.forEach((shape) => addToShapeTree(shape, tree, page.shapes, selectedIds, pageState, meta))
|
||||
.forEach((shape) =>
|
||||
addToShapeTree(shape, tree, page.shapes, selectedIds, { ...pageState, bindingTargetId }, meta)
|
||||
)
|
||||
|
||||
return tree
|
||||
}
|
||||
|
|
|
@ -241,7 +241,7 @@ const tlcss = css`
|
|||
}
|
||||
.tl-binding-indicator {
|
||||
stroke-width: calc(3px * var(--tl-scale));
|
||||
fill: none;
|
||||
fill: var(--tl-selectFill);
|
||||
stroke: var(--tl-selected);
|
||||
}
|
||||
.tl-shape-group {
|
||||
|
|
|
@ -101,12 +101,12 @@ export const ContextMenu = React.memo(({ children }: ContextMenuProps): JSX.Elem
|
|||
tlstate.delete()
|
||||
}, [tlstate])
|
||||
|
||||
const handleCopyAsJson = React.useCallback(() => {
|
||||
tlstate.copyAsJson()
|
||||
const handlecopyJson = React.useCallback(() => {
|
||||
tlstate.copyJson()
|
||||
}, [tlstate])
|
||||
|
||||
const handleCopyAsSvg = React.useCallback(() => {
|
||||
tlstate.copyAsSvg()
|
||||
const handlecopySvg = React.useCallback(() => {
|
||||
tlstate.copySvg()
|
||||
}, [tlstate])
|
||||
|
||||
const handleUndo = React.useCallback(() => {
|
||||
|
@ -180,12 +180,12 @@ export const ContextMenu = React.memo(({ children }: ContextMenuProps): JSX.Elem
|
|||
)}
|
||||
{/* <MoveToPageMenu /> */}
|
||||
{isDebugMode && (
|
||||
<ContextMenuButton onSelect={handleCopyAsJson}>
|
||||
<ContextMenuButton onSelect={handlecopyJson}>
|
||||
<span>Copy Data</span>
|
||||
<Kbd variant="menu">#⇧C</Kbd>
|
||||
</ContextMenuButton>
|
||||
)}
|
||||
<ContextMenuButton onSelect={handleCopyAsSvg}>
|
||||
<ContextMenuButton onSelect={handlecopySvg}>
|
||||
<span>Copy to SVG</span>
|
||||
<Kbd variant="menu">#⇧C</Kbd>
|
||||
</ContextMenuButton>
|
||||
|
|
|
@ -66,8 +66,8 @@ function SelectedShapeContent(): JSX.Element {
|
|||
tlstate.paste()
|
||||
}, [tlstate])
|
||||
|
||||
const handleCopyAsSvg = React.useCallback(() => {
|
||||
tlstate.copyAsSvg()
|
||||
const handlecopySvg = React.useCallback(() => {
|
||||
tlstate.copySvg()
|
||||
}, [tlstate])
|
||||
|
||||
return (
|
||||
|
@ -88,7 +88,7 @@ function SelectedShapeContent(): JSX.Element {
|
|||
<span>Paste</span>
|
||||
{showKbds && <Kbd variant="menu">#V</Kbd>}
|
||||
</RowButton>
|
||||
<RowButton bp={breakpoints} onClick={handleCopyAsSvg}>
|
||||
<RowButton bp={breakpoints} onClick={handlecopySvg}>
|
||||
<span>Copy to SVG</span>
|
||||
{showKbds && <Kbd variant="menu">⇧#C</Kbd>}
|
||||
</RowButton>
|
||||
|
|
|
@ -11,6 +11,8 @@ import {
|
|||
import styled from '~styles'
|
||||
import TextAreaUtils from './text-utils'
|
||||
|
||||
const LETTER_SPACING = -1.5
|
||||
|
||||
function normalizeText(text: string) {
|
||||
return text.replace(/\r?\n|\r/g, '\n')
|
||||
}
|
||||
|
@ -31,7 +33,7 @@ function getMeasurementDiv() {
|
|||
border: '1px solid red',
|
||||
padding: '4px',
|
||||
margin: '0px',
|
||||
letterSpacing: '-2.5px',
|
||||
letterSpacing: `${LETTER_SPACING}px`,
|
||||
opacity: '0',
|
||||
position: 'absolute',
|
||||
top: '-500px',
|
||||
|
@ -93,6 +95,7 @@ export class Text extends TLDrawShapeUtil<TextShape> {
|
|||
ref,
|
||||
meta,
|
||||
isEditing,
|
||||
isBinding,
|
||||
onTextBlur,
|
||||
onTextChange,
|
||||
onTextFocus,
|
||||
|
@ -162,15 +165,15 @@ export class Text extends TLDrawShapeUtil<TextShape> {
|
|||
if (!isEditing) {
|
||||
return (
|
||||
<>
|
||||
{/* {isBinding && (
|
||||
<BindingIndicator
|
||||
as="rect"
|
||||
x={-32}
|
||||
y={-32}
|
||||
width={bounds.width + 64}
|
||||
height={bounds.height + 64}
|
||||
{isBinding && (
|
||||
<rect
|
||||
className="tl-binding-indicator"
|
||||
x={-16}
|
||||
y={-16}
|
||||
width={bounds.width + 32}
|
||||
height={bounds.height + 32}
|
||||
/>
|
||||
)} */}
|
||||
)}
|
||||
{text.split('\n').map((str, i) => (
|
||||
<text
|
||||
key={i}
|
||||
|
@ -179,7 +182,7 @@ export class Text extends TLDrawShapeUtil<TextShape> {
|
|||
fontFamily="Caveat Brush"
|
||||
fontStyle="normal"
|
||||
fontWeight="500"
|
||||
letterSpacing="-2.5"
|
||||
letterSpacing={LETTER_SPACING}
|
||||
fontSize={fontSize}
|
||||
width={bounds.width}
|
||||
height={bounds.height}
|
||||
|
@ -372,6 +375,81 @@ export class Text extends TLDrawShapeUtil<TextShape> {
|
|||
return shape.text.trim().length === 0
|
||||
}
|
||||
|
||||
getBindingPoint(
|
||||
shape: TextShape,
|
||||
point: number[],
|
||||
origin: number[],
|
||||
direction: number[],
|
||||
padding: number,
|
||||
anywhere: boolean
|
||||
) {
|
||||
const bounds = this.getBounds(shape)
|
||||
|
||||
const expandedBounds = Utils.expandBounds(bounds, padding)
|
||||
|
||||
let bindingPoint: number[]
|
||||
let distance: number
|
||||
|
||||
// The point must be inside of the expanded bounding box
|
||||
if (!Utils.pointInBounds(point, expandedBounds)) return
|
||||
|
||||
// The point is inside of the shape, so we'll assume the user is
|
||||
// indicating a specific point inside of the shape.
|
||||
if (anywhere) {
|
||||
if (Vec.dist(point, this.getCenter(shape)) < 12) {
|
||||
bindingPoint = [0.5, 0.5]
|
||||
} else {
|
||||
bindingPoint = Vec.divV(Vec.sub(point, [expandedBounds.minX, expandedBounds.minY]), [
|
||||
expandedBounds.width,
|
||||
expandedBounds.height,
|
||||
])
|
||||
}
|
||||
|
||||
distance = 0
|
||||
} else {
|
||||
// Find furthest intersection between ray from
|
||||
// origin through point and expanded bounds.
|
||||
|
||||
// TODO: Make this a ray vs rounded rect intersection
|
||||
const intersection = Intersect.ray
|
||||
.bounds(origin, direction, expandedBounds)
|
||||
.filter((int) => int.didIntersect)
|
||||
.map((int) => int.points[0])
|
||||
.sort((a, b) => Vec.dist(b, origin) - Vec.dist(a, origin))[0]
|
||||
|
||||
// The anchor is a point between the handle and the intersection
|
||||
const anchor = Vec.med(point, intersection)
|
||||
|
||||
// If we're close to the center, snap to the center
|
||||
if (Vec.distanceToLineSegment(point, anchor, this.getCenter(shape)) < 12) {
|
||||
bindingPoint = [0.5, 0.5]
|
||||
} else {
|
||||
// Or else calculate a normalized point
|
||||
bindingPoint = Vec.divV(Vec.sub(anchor, [expandedBounds.minX, expandedBounds.minY]), [
|
||||
expandedBounds.width,
|
||||
expandedBounds.height,
|
||||
])
|
||||
}
|
||||
|
||||
if (Utils.pointInBounds(point, bounds)) {
|
||||
distance = 16
|
||||
} else {
|
||||
// If the binding point was close to the shape's center, snap to the center
|
||||
// Find the distance between the point and the real bounds of the shape
|
||||
distance = Math.max(
|
||||
16,
|
||||
Utils.getBoundsSides(bounds)
|
||||
.map((side) => Vec.distanceToLineSegment(side[1][0], side[1][1], point))
|
||||
.sort((a, b) => a - b)[0]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
point: Vec.clampV(bindingPoint, 0, 1),
|
||||
distance,
|
||||
}
|
||||
}
|
||||
// getBindingPoint(shape, point, origin, direction, expandDistance) {
|
||||
// const bounds = this.getBounds(shape)
|
||||
|
||||
|
@ -442,7 +520,7 @@ const StyledTextArea = styled('textarea', {
|
|||
minHeight: 1,
|
||||
minWidth: 1,
|
||||
lineHeight: 1.4,
|
||||
letterSpacing: -2.5,
|
||||
letterSpacing: LETTER_SPACING,
|
||||
outline: 0,
|
||||
fontWeight: '500',
|
||||
backgroundColor: '$boundsBg',
|
||||
|
|
|
@ -7,9 +7,7 @@ export function style(data: Data, ids: string[], changes: Partial<ShapeStyles>):
|
|||
const { before, after } = TLDR.mutateShapes(
|
||||
data,
|
||||
ids,
|
||||
(shape) => {
|
||||
return { style: { ...shape.style, ...changes } }
|
||||
},
|
||||
(shape) => ({ style: { ...shape.style, ...changes } }),
|
||||
currentPageId
|
||||
)
|
||||
|
||||
|
@ -18,7 +16,9 @@ export function style(data: Data, ids: string[], changes: Partial<ShapeStyles>):
|
|||
before: {
|
||||
document: {
|
||||
pages: {
|
||||
[currentPageId]: { shapes: before },
|
||||
[currentPageId]: {
|
||||
shapes: before,
|
||||
},
|
||||
},
|
||||
},
|
||||
appState: {
|
||||
|
@ -28,7 +28,9 @@ export function style(data: Data, ids: string[], changes: Partial<ShapeStyles>):
|
|||
after: {
|
||||
document: {
|
||||
pages: {
|
||||
[currentPageId]: { shapes: after },
|
||||
[currentPageId]: {
|
||||
shapes: after,
|
||||
},
|
||||
},
|
||||
},
|
||||
appState: {
|
||||
|
|
|
@ -427,9 +427,19 @@ export class TLDR {
|
|||
afterShapes[id] = change
|
||||
})
|
||||
|
||||
const dataWithMutations = Utils.deepMerge(data, {
|
||||
document: {
|
||||
pages: {
|
||||
[data.appState.currentPageId]: {
|
||||
shapes: afterShapes,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const dataWithChildrenChanges = ids.reduce<Data>((cData, id) => {
|
||||
return this.recursivelyUpdateChildren(cData, id, beforeShapes, afterShapes, pageId)
|
||||
}, data)
|
||||
}, dataWithMutations)
|
||||
|
||||
const dataWithParentChanges = ids.reduce<Data>((cData, id) => {
|
||||
return this.recursivelyUpdateParents(cData, id, beforeShapes, afterShapes, pageId)
|
||||
|
|
|
@ -228,10 +228,12 @@ describe('TLDrawState', () => {
|
|||
})
|
||||
|
||||
describe('Copies to JSON', () => {
|
||||
// TODO
|
||||
tlstate.selectAll()
|
||||
tlstate.copyJson()
|
||||
})
|
||||
|
||||
describe('Copies to SVG', () => {
|
||||
// TODO
|
||||
tlstate.selectAll()
|
||||
tlstate.copySvg()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -717,7 +717,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param pageId The page from which to copy the shapes.
|
||||
* @returns A string containing the JSON.
|
||||
*/
|
||||
copyAsSvg = (ids = this.selectedIds, pageId = this.currentPageId) => {
|
||||
copySvg = (ids = this.selectedIds, pageId = this.currentPageId) => {
|
||||
if (ids.length === 0) return
|
||||
|
||||
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
||||
|
@ -767,7 +767,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param pageId The page from which to copy the shapes.
|
||||
* @returns A string containing the JSON.
|
||||
*/
|
||||
copyAsJson = (ids = this.selectedIds, pageId = this.currentPageId) => {
|
||||
copyJson = (ids = this.selectedIds, pageId = this.currentPageId) => {
|
||||
const shapes = ids.map((id) => this.getShape(id, pageId))
|
||||
const json = JSON.stringify(shapes, null, 2)
|
||||
TLDR.copyStringToClipboard(json)
|
||||
|
@ -784,7 +784,10 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param args arguments of the session's start method.
|
||||
* @returns this
|
||||
*/
|
||||
startSession<T extends Session>(session: T, ...args: ParametersExceptFirst<T['start']>): this {
|
||||
startSession = <T extends Session>(
|
||||
session: T,
|
||||
...args: ParametersExceptFirst<T['start']>
|
||||
): this => {
|
||||
this.session = session
|
||||
|
||||
const result = session.start(this.state, ...args)
|
||||
|
@ -813,7 +816,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param args The arguments of the current session's update method.
|
||||
* @returns this
|
||||
*/
|
||||
updateSession<T extends Session>(...args: ParametersExceptFirst<T['update']>): this {
|
||||
updateSession = <T extends Session>(...args: ParametersExceptFirst<T['update']>): this => {
|
||||
const { session } = this
|
||||
if (!session) return this
|
||||
const patch = session.update(this.state, ...args)
|
||||
|
@ -826,7 +829,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param args The arguments of the current session's cancel method.
|
||||
* @returns this
|
||||
*/
|
||||
cancelSession<T extends Session>(...args: ParametersExceptFirst<T['cancel']>): this {
|
||||
cancelSession = <T extends Session>(...args: ParametersExceptFirst<T['cancel']>): this => {
|
||||
const { session } = this
|
||||
if (!session) return this
|
||||
this.session = undefined
|
||||
|
@ -882,7 +885,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param args The arguments of the current session's complete method.
|
||||
* @returns this
|
||||
*/
|
||||
completeSession<T extends Session>(...args: ParametersExceptFirst<T['complete']>) {
|
||||
completeSession = <T extends Session>(...args: ParametersExceptFirst<T['complete']>): this => {
|
||||
const { session } = this
|
||||
|
||||
if (!session) return this
|
||||
|
@ -1008,20 +1011,22 @@ export class TLDrawState extends StateManager<Data> {
|
|||
/**
|
||||
* Clear the selection history (undo/redo stack for selection).
|
||||
*/
|
||||
private clearSelectHistory() {
|
||||
private clearSelectHistory = (): this => {
|
||||
this.selectHistory.pointer = 0
|
||||
this.selectHistory.stack = [this.selectedIds]
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a selection to the selection history (undo/redo stack for selection).
|
||||
*/
|
||||
private addToSelectHistory(ids: string[]) {
|
||||
private addToSelectHistory = (ids: string[]): this => {
|
||||
if (this.selectHistory.pointer < this.selectHistory.stack.length) {
|
||||
this.selectHistory.stack = this.selectHistory.stack.slice(0, this.selectHistory.pointer + 1)
|
||||
}
|
||||
this.selectHistory.pointer++
|
||||
this.selectHistory.stack.push(ids)
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1030,7 +1035,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param push Whether to add the ids to the current selection instead.
|
||||
* @returns this
|
||||
*/
|
||||
private setSelectedIds(ids: string[], push = false): this {
|
||||
private setSelectedIds = (ids: string[], push = false): this => {
|
||||
return this.patchState(
|
||||
{
|
||||
appState: {
|
||||
|
@ -1053,7 +1058,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* Undo the most recent selection.
|
||||
* @returns this
|
||||
*/
|
||||
undoSelect(): this {
|
||||
undoSelect = (): this => {
|
||||
if (this.selectHistory.pointer > 0) {
|
||||
this.selectHistory.pointer--
|
||||
this.setSelectedIds(this.selectHistory.stack[this.selectHistory.pointer])
|
||||
|
@ -1065,7 +1070,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* Redo the previous selection.
|
||||
* @returns this
|
||||
*/
|
||||
redoSelect(): this {
|
||||
redoSelect = (): this => {
|
||||
if (this.selectHistory.pointer < this.selectHistory.stack.length - 1) {
|
||||
this.selectHistory.pointer++
|
||||
this.setSelectedIds(this.selectHistory.stack[this.selectHistory.pointer])
|
||||
|
@ -1178,7 +1183,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param ids The ids of the shapes to change (defaults to selection).
|
||||
* @returns this
|
||||
*/
|
||||
style = (style: Partial<ShapeStyles>, ids = this.selectedIds) => {
|
||||
style = (style: Partial<ShapeStyles>, ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.style(this.state, ids, style))
|
||||
}
|
||||
|
||||
|
@ -1188,7 +1194,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param ids The ids of the shapes to change (defaults to selection).
|
||||
* @returns this
|
||||
*/
|
||||
align = (type: AlignType, ids = this.selectedIds) => {
|
||||
align = (type: AlignType, ids = this.selectedIds): this => {
|
||||
if (ids.length < 2) return this
|
||||
return this.setState(Commands.align(this.state, ids, type))
|
||||
}
|
||||
|
||||
|
@ -1198,7 +1205,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param ids The ids of the shapes to change (defaults to selection).
|
||||
* @returns this
|
||||
*/
|
||||
distribute = (direction: DistributeType, ids = this.selectedIds) => {
|
||||
distribute = (direction: DistributeType, ids = this.selectedIds): this => {
|
||||
if (ids.length < 3) return this
|
||||
return this.setState(Commands.distribute(this.state, ids, direction))
|
||||
}
|
||||
|
||||
|
@ -1208,7 +1216,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param ids The ids of the shapes to change (defaults to selection).
|
||||
* @returns this
|
||||
*/
|
||||
stretch = (direction: StretchType, ids = this.selectedIds) => {
|
||||
stretch = (direction: StretchType, ids = this.selectedIds): this => {
|
||||
if (ids.length < 2) return this
|
||||
return this.setState(Commands.stretch(this.state, ids, direction))
|
||||
}
|
||||
|
||||
|
@ -1217,7 +1226,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param ids The ids of the shapes to change (defaults to selection).
|
||||
* @returns this
|
||||
*/
|
||||
flipHorizontal = (ids = this.selectedIds) => {
|
||||
flipHorizontal = (ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.flip(this.state, ids, FlipType.Horizontal))
|
||||
}
|
||||
|
||||
|
@ -1226,7 +1236,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param ids The ids of the shapes to change (defaults to selection).
|
||||
* @returns this
|
||||
*/
|
||||
flipVertical = (ids = this.selectedIds) => {
|
||||
flipVertical = (ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.flip(this.state, ids, FlipType.Vertical))
|
||||
}
|
||||
|
||||
|
@ -1235,7 +1246,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param ids The ids of the shapes to change (defaults to selection).
|
||||
* @returns this
|
||||
*/
|
||||
moveToBack = (ids = this.selectedIds) => {
|
||||
moveToBack = (ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.move(this.state, ids, MoveType.ToBack))
|
||||
}
|
||||
|
||||
|
@ -1244,7 +1256,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param ids The ids of the shapes to change (defaults to selection).
|
||||
* @returns this
|
||||
*/
|
||||
moveBackward = (ids = this.selectedIds) => {
|
||||
moveBackward = (ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.move(this.state, ids, MoveType.Backward))
|
||||
}
|
||||
|
||||
|
@ -1253,7 +1266,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param ids The ids of the shapes to change (defaults to selection).
|
||||
* @returns this
|
||||
*/
|
||||
moveForward = (ids = this.selectedIds) => {
|
||||
moveForward = (ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.move(this.state, ids, MoveType.Forward))
|
||||
}
|
||||
|
||||
|
@ -1262,7 +1276,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param ids The ids of the shapes to change (defaults to selection).
|
||||
* @returns this
|
||||
*/
|
||||
moveToFront = (ids = this.selectedIds) => {
|
||||
moveToFront = (ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.move(this.state, ids, MoveType.ToFront))
|
||||
}
|
||||
|
||||
|
@ -1274,6 +1289,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @returns this
|
||||
*/
|
||||
nudge = (delta: number[], isMajor = false, ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.translate(this.state, ids, Vec.mul(delta, isMajor ? 10 : 1)))
|
||||
}
|
||||
|
||||
|
@ -1283,6 +1299,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @returns this
|
||||
*/
|
||||
duplicate = (ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.duplicate(this.state, ids))
|
||||
}
|
||||
|
||||
|
@ -1292,6 +1309,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @returns this
|
||||
*/
|
||||
toggleHidden = (ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.toggle(this.state, ids, 'isHidden'))
|
||||
}
|
||||
|
||||
|
@ -1301,6 +1319,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @returns this
|
||||
*/
|
||||
toggleLocked = (ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.toggle(this.state, ids, 'isLocked'))
|
||||
}
|
||||
|
||||
|
@ -1310,6 +1329,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @returns this
|
||||
*/
|
||||
toggleAspectRatioLocked = (ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.toggle(this.state, ids, 'isAspectRatioLocked'))
|
||||
}
|
||||
|
||||
|
@ -1320,11 +1340,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @returns this
|
||||
*/
|
||||
toggleDecoration = (handleId: string, ids = this.selectedIds): this => {
|
||||
if (handleId === 'start' || handleId === 'end') {
|
||||
return this.setState(Commands.toggleDecoration(this.state, ids, handleId))
|
||||
}
|
||||
|
||||
return this
|
||||
if (ids.length === 0 || !(handleId === 'start' || handleId === 'end')) return this
|
||||
return this.setState(Commands.toggleDecoration(this.state, ids, handleId))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1334,6 +1351,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @returns this
|
||||
*/
|
||||
rotate = (delta = Math.PI * -0.5, ids = this.selectedIds): this => {
|
||||
if (ids.length === 0) return this
|
||||
return this.setState(Commands.rotate(this.state, ids, delta))
|
||||
}
|
||||
|
||||
|
@ -1343,6 +1361,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @todo
|
||||
*/
|
||||
group = (): this => {
|
||||
// TODO
|
||||
return this
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue