Fix undo/redo for Opacity Slider + Style dropdowns. (#2933)
Closes #2664 and #2929 ### Change Type - [x] `patch` — Bug fix [^1]: publishes a `patch` release, for devDependencies use `internal` [^2]: will not publish a new version ### Test Plan 1. Add a step-by-step description of how to test your PR here. 2. - [ ] Unit Tests - [ ] End to end tests ### Release Notes - Fixed issues where undo/redo entries were not being set up correctly for the opacity slider or the style dropdown menus.
This commit is contained in:
parent
521d84a611
commit
046ebc4ac0
8 changed files with 18 additions and 14 deletions
|
@ -1214,7 +1214,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
if (partial.isChangingStyle === true) {
|
if (partial.isChangingStyle === true) {
|
||||||
// If we've set to true, set a new reset timeout to change the value back to false after 2 seconds
|
// If we've set to true, set a new reset timeout to change the value back to false after 2 seconds
|
||||||
this._isChangingStyleTimeout = setTimeout(() => {
|
this._isChangingStyleTimeout = setTimeout(() => {
|
||||||
this.updateInstanceState({ isChangingStyle: false })
|
this.updateInstanceState({ isChangingStyle: false }, { ephemeral: true })
|
||||||
}, 2000)
|
}, 2000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1927,7 +1927,7 @@ export interface TLUiSliderProps {
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
label: string;
|
label: string;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
onValueChange: (value: number, emphemeral: boolean) => void;
|
onValueChange: (value: number, squashing: boolean) => void;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
steps: number;
|
steps: number;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
|
|
|
@ -37,7 +37,7 @@ export function MobileStylePanel() {
|
||||||
const handleStylesOpenChange = useCallback(
|
const handleStylesOpenChange = useCallback(
|
||||||
(isOpen: boolean) => {
|
(isOpen: boolean) => {
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
editor.updateInstanceState({ isChangingStyle: false })
|
editor.updateInstanceState({ isChangingStyle: false }, { ephemeral: true })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[editor]
|
[editor]
|
||||||
|
|
|
@ -21,7 +21,7 @@ export const DefaultStylePanel = memo(function DefaultStylePanel({
|
||||||
|
|
||||||
const handlePointerOut = useCallback(() => {
|
const handlePointerOut = useCallback(() => {
|
||||||
if (!isMobile) {
|
if (!isMobile) {
|
||||||
editor.updateInstanceState({ isChangingStyle: false })
|
editor.updateInstanceState({ isChangingStyle: false }, { ephemeral: true })
|
||||||
}
|
}
|
||||||
}, [editor, isMobile])
|
}, [editor, isMobile])
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ function useStyleChangeCallback() {
|
||||||
editor.setStyleForSelectedShapes(style, value, { squashing })
|
editor.setStyleForSelectedShapes(style, value, { squashing })
|
||||||
}
|
}
|
||||||
editor.setStyleForNextShapes(style, value, { squashing })
|
editor.setStyleForNextShapes(style, value, { squashing })
|
||||||
editor.updateInstanceState({ isChangingStyle: true })
|
editor.updateInstanceState({ isChangingStyle: true }, { ephemeral: true })
|
||||||
})
|
})
|
||||||
|
|
||||||
trackEvent('set-style', { source: 'style-panel', id: style.id, value: value as string })
|
trackEvent('set-style', { source: 'style-panel', id: style.id, value: value as string })
|
||||||
|
@ -297,14 +297,14 @@ function OpacitySlider() {
|
||||||
const msg = useTranslation()
|
const msg = useTranslation()
|
||||||
|
|
||||||
const handleOpacityValueChange = React.useCallback(
|
const handleOpacityValueChange = React.useCallback(
|
||||||
(value: number, ephemeral: boolean) => {
|
(value: number, squashing: boolean) => {
|
||||||
const item = tldrawSupportedOpacities[value]
|
const item = tldrawSupportedOpacities[value]
|
||||||
editor.batch(() => {
|
editor.batch(() => {
|
||||||
if (editor.isIn('select')) {
|
if (editor.isIn('select')) {
|
||||||
editor.setOpacityForSelectedShapes(item, { ephemeral })
|
editor.setOpacityForSelectedShapes(item, { squashing })
|
||||||
}
|
}
|
||||||
editor.setOpacityForNextShapes(item, { ephemeral })
|
editor.setOpacityForNextShapes(item, { squashing })
|
||||||
editor.updateInstanceState({ isChangingStyle: true })
|
editor.updateInstanceState({ isChangingStyle: true }, { ephemeral: true })
|
||||||
})
|
})
|
||||||
|
|
||||||
trackEvent('set-style', { source: 'style-panel', id: 'opacity', value })
|
trackEvent('set-style', { source: 'style-panel', id: 'opacity', value })
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { SharedStyle, StyleProp } from '@tldraw/editor'
|
import { SharedStyle, StyleProp, useEditor } from '@tldraw/editor'
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { StyleValuesForUi } from '../../../styles'
|
import { StyleValuesForUi } from '../../../styles'
|
||||||
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
|
import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
|
||||||
|
@ -36,6 +36,7 @@ function _DropdownPicker<T extends string>({
|
||||||
onValueChange,
|
onValueChange,
|
||||||
}: DropdownPickerProps<T>) {
|
}: DropdownPickerProps<T>) {
|
||||||
const msg = useTranslation()
|
const msg = useTranslation()
|
||||||
|
const editor = useEditor()
|
||||||
|
|
||||||
const icon = React.useMemo(
|
const icon = React.useMemo(
|
||||||
() => items.find((item) => value.type === 'shared' && item.value === value.value)?.icon,
|
() => items.find((item) => value.type === 'shared' && item.value === value.value)?.icon,
|
||||||
|
@ -65,7 +66,10 @@ function _DropdownPicker<T extends string>({
|
||||||
type="icon"
|
type="icon"
|
||||||
data-testid={`style.${uiType}.${item.value}`}
|
data-testid={`style.${uiType}.${item.value}`}
|
||||||
title={msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)}
|
title={msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)}
|
||||||
onClick={() => onValueChange(style, item.value, false)}
|
onClick={() => {
|
||||||
|
editor.mark('select style dropdown item')
|
||||||
|
onValueChange(style, item.value, false)
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<TldrawUiButtonIcon icon={item.icon} />
|
<TldrawUiButtonIcon icon={item.icon} />
|
||||||
</TldrawUiButton>
|
</TldrawUiButton>
|
||||||
|
|
|
@ -10,7 +10,7 @@ export interface TLUiSliderProps {
|
||||||
value: number | null
|
value: number | null
|
||||||
label: string
|
label: string
|
||||||
title: string
|
title: string
|
||||||
onValueChange: (value: number, emphemeral: boolean) => void
|
onValueChange: (value: number, squashing: boolean) => void
|
||||||
'data-testid'?: string
|
'data-testid'?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ export function pasteTldrawContent(editor: Editor, clipboard: TLContent, point?:
|
||||||
seletionBoundsBefore?.collides(selectedBoundsAfter)
|
seletionBoundsBefore?.collides(selectedBoundsAfter)
|
||||||
) {
|
) {
|
||||||
// Creates a 'puff' to show a paste has happened.
|
// Creates a 'puff' to show a paste has happened.
|
||||||
editor.updateInstanceState({ isChangingStyle: true })
|
editor.updateInstanceState({ isChangingStyle: true }, { ephemeral: true })
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
editor.updateInstanceState({ isChangingStyle: false })
|
editor.updateInstanceState({ isChangingStyle: false }, { ephemeral: true })
|
||||||
}, 150)
|
}, 150)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue