fix: reset bounds action

This commit is contained in:
Peng Xiao
2022-08-22 13:35:01 +08:00
parent 5a78da0d9d
commit ddb794907d
6 changed files with 76 additions and 38 deletions

View File

@@ -16,6 +16,7 @@ import { tint } from 'polished'
import type {
BoxShape,
EllipseShape,
HTMLShape,
LineShape,
LogseqPortalShape,
PencilShape,
@@ -31,6 +32,7 @@ export const contextBarActionTypes = [
'Edit',
'Swatch',
'NoFill',
'ResetBounds',
'StrokeType',
'ScaleLevel',
'YoutubeLink',
@@ -47,7 +49,7 @@ const contextBarActionMapping = new Map<ContextBarActionType, React.FC>()
type ShapeType = Shape['props']['type']
const shapeMapping: Partial<Record<ShapeType, ContextBarActionType[]>> = {
'logseq-portal': ['Edit', 'LogseqPortalViewMode', 'ScaleLevel', 'OpenPage'],
'logseq-portal': ['Edit', 'LogseqPortalViewMode', 'ScaleLevel', 'OpenPage', 'ResetBounds'],
youtube: ['YoutubeLink'],
box: ['Swatch', 'NoFill', 'StrokeType'],
ellipse: ['Swatch', 'NoFill', 'StrokeType'],
@@ -55,8 +57,8 @@ const shapeMapping: Partial<Record<ShapeType, ContextBarActionType[]>> = {
line: ['Edit', 'Swatch', 'ArrowMode'],
pencil: ['Swatch'],
highlighter: ['Swatch'],
text: ['Edit', 'Swatch', 'ScaleLevel'],
html: ['ScaleLevel'],
text: ['Edit', 'Swatch', 'ScaleLevel', 'ResetBounds'],
html: ['ScaleLevel', 'ResetBounds'],
}
const noStrokeShapes = Object.entries(shapeMapping)
@@ -97,6 +99,29 @@ const EditAction = observer(() => {
)
})
const ResetBoundsAction = observer(() => {
const app = useApp<Shape>()
const shapes = filterShapeByAction<LogseqPortalShape | TextShape | HTMLShape>(
app.selectedShapesArray,
'ResetBounds'
)
return (
<button
className="tl-contextbar-button"
type="button"
onClick={() => {
shapes.forEach(s => {
s.onResetBounds()
})
app.persist()
}}
>
<TablerIcon name="dimensions" />
</button>
)
})
const LogseqPortalViewModeAction = observer(() => {
const app = useApp<Shape>()
const shapes = filterShapeByAction<LogseqPortalShape>(
@@ -354,6 +379,7 @@ const ArrowModeAction = observer(() => {
})
contextBarActionMapping.set('Edit', EditAction)
contextBarActionMapping.set('ResetBounds', ResetBoundsAction)
contextBarActionMapping.set('LogseqPortalViewMode', LogseqPortalViewModeAction)
contextBarActionMapping.set('ScaleLevel', ScaleLevelAction)
contextBarActionMapping.set('OpenPage', OpenPageAction)

View File

@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { delay, TLBoxShape, TLBoxShapeProps } from '@tldraw/core'
import { delay, TLBoxShape, TLBoxShapeProps, TLResetBoundsInfo } from '@tldraw/core'
import { HTMLContainer, TLComponentProps, useApp } from '@tldraw/react'
import Vec from '@tldraw/vec'
import { action, computed } from 'mobx'
@@ -39,6 +39,7 @@ export class HTMLShape extends TLBoxShape<HTMLShapeProps> {
canChangeAspectRatio = true
canFlip = false
canEdit = true
htmlAnchorRef = React.createRef<HTMLDivElement>()
@computed get scaleLevel() {
return this.props.scaleLevel ?? 'md'
@@ -58,6 +59,18 @@ export class HTMLShape extends TLBoxShape<HTMLShapeProps> {
})
}
onResetBounds = (info?: TLResetBoundsInfo) => {
if (this.htmlAnchorRef.current) {
this.update({
size: [
this.props.size[0],
Math.max(Math.min(this.htmlAnchorRef.current.offsetHeight || 400, 800), 10),
],
})
}
return this
}
ReactComponent = observer(({ events, isErasing, isEditing }: TLComponentProps) => {
const {
props: { html, scaleLevel },
@@ -78,18 +91,11 @@ export class HTMLShape extends TLBoxShape<HTMLShapeProps> {
[tlEventsEnabled]
)
const anchorRef = React.useRef<HTMLDivElement>(null)
const scaleRatio = levelToScale[scaleLevel ?? 'md']
React.useEffect(() => {
if (this.props.size[1] === 0 && anchorRef.current) {
this.update({
size: [
this.props.size[0],
Math.max(Math.min(anchorRef.current.offsetHeight || 400, 800), 10),
],
})
if (this.props.size[1] === 0) {
this.onResetBounds()
app.persist(true)
}
}, [])
@@ -117,7 +123,7 @@ export class HTMLShape extends TLBoxShape<HTMLShapeProps> {
}}
>
<div
ref={anchorRef}
ref={this.htmlAnchorRef}
className="tl-html-anchor"
dangerouslySetInnerHTML={{ __html: html.trim() }}
/>

View File

@@ -1,5 +1,12 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { delay, TLBoxShape, TLBoxShapeProps, TLResizeInfo, validUUID } from '@tldraw/core'
import {
delay,
TLBoxShape,
TLBoxShapeProps,
TLResetBoundsInfo,
TLResizeInfo,
validUUID,
} from '@tldraw/core'
import { HTMLContainer, TLComponentProps, useApp } from '@tldraw/react'
import Vec from '@tldraw/vec'
import { action, computed, makeObservable } from 'mobx'
@@ -172,16 +179,16 @@ export class LogseqPortalShape extends TLBoxShape<LogseqPortalShapeProps> {
return this.props.blockType === 'B' ? this.props.compact : this.props.collapsed
}
@action setCollapsed = (collapsed: boolean) => {
@action setCollapsed = async (collapsed: boolean) => {
if (this.props.blockType === 'B') {
this.update({ compact: collapsed })
this.canResize[1] = !collapsed
if (!collapsed) {
// this will also persist the state, so we can skip persist call
this.autoResizeHeight()
} else {
this.persist?.()
await delay()
this.onResetBounds()
}
this.persist?.()
} else {
const originalHeight = this.props.size[1]
this.canResize[1] = !collapsed
@@ -256,17 +263,15 @@ export class LogseqPortalShape extends TLBoxShape<LogseqPortalShapeProps> {
return null
}
autoResizeHeight(replace: boolean = false) {
setTimeout(() => {
const height = this.getAutoResizeHeight()
if (height !== null && Math.abs(height - this.props.size[1]) > AUTO_RESIZE_THRESHOLD) {
this.update({
size: [this.props.size[0], height],
})
this.persist?.(replace)
this.initialHeightCalculated = true
}
})
onResetBounds = (info?: TLResetBoundsInfo) => {
const height = this.getAutoResizeHeight()
if (height !== null && Math.abs(height - this.props.size[1]) > AUTO_RESIZE_THRESHOLD) {
this.update({
size: [this.props.size[0], height],
})
this.initialHeightCalculated = true
}
return this
}
onResize = (initialProps: any, info: TLResizeInfo): this => {
@@ -615,7 +620,10 @@ export class LogseqPortalShape extends TLBoxShape<LogseqPortalShapeProps> {
React.useEffect(() => {
if (!this.initialHeightCalculated) {
this.autoResizeHeight(true)
setTimeout(() => {
this.onResetBounds()
app.persist(true)
})
}
}, [this.initialHeightCalculated])

View File

@@ -38,7 +38,7 @@ export class TLImageShape<
assetId: '',
}
onResetBounds = (info: TLResetBoundsInfo<TLImageAsset>) => {
autoResize = (info: TLResetBoundsInfo<TLImageAsset>) => {
const { clipping, size, point } = this.props
if (clipping) {
const [t, r, b, l] = Array.isArray(clipping)

View File

@@ -57,9 +57,7 @@ export interface TLResizeInfo {
transformOrigin: number[]
}
export interface TLResetBoundsInfo<T extends TLAsset> {
asset?: T
}
export interface TLResetBoundsInfo {}
export interface TLHandleChangeInfo {
id: string
@@ -306,7 +304,7 @@ export abstract class TLShape<P extends TLShapeProps = TLShapeProps, M = any> {
return new this.constructor(this.serialized)
}
onResetBounds = (info: TLResetBoundsInfo<any>) => {
onResetBounds = (info?: TLResetBoundsInfo) => {
return this
}

View File

@@ -77,7 +77,7 @@ export class HoveringSelectionHandleState<
break
}
case TLTargetType.Selection: {
selectedShape.onResetBounds?.({})
selectedShape.autoResize?.({})
if (this.app.selectedShapesArray.length === 1) {
this.tool.transition('editingShape', {
type: TLTargetType.Shape,
@@ -91,7 +91,7 @@ export class HoveringSelectionHandleState<
const asset = selectedShape.props.assetId
? this.app.assets[selectedShape.props.assetId]
: undefined
selectedShape.onResetBounds({ asset })
selectedShape.autoResize({ asset })
this.tool.transition('idle')
}
}