mirror of
https://github.com/logseq/logseq.git
synced 2026-06-02 19:31:24 +00:00
fix: reset bounds action
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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() }}
|
||||
/>
|
||||
|
||||
@@ -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])
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user