[improvement] adds option to keep style menu open (#697)
* Adds open to keep style menu open * fix keyboard shortcuts, add button to menu
This commit is contained in:
parent
c3fe36c2e7
commit
ba0795c595
6 changed files with 96 additions and 52 deletions
|
@ -1,7 +1,7 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { DMCheckboxItem, DMDivider, DMSubMenu } from '~components/Primitives/DropdownMenu'
|
import { DMCheckboxItem, DMDivider, DMSubMenu } from '~components/Primitives/DropdownMenu'
|
||||||
import { useTldrawApp } from '~hooks'
|
import { useTldrawApp } from '~hooks'
|
||||||
import type { TDSnapshot } from '~types'
|
import { TDSnapshot } from '~types'
|
||||||
|
|
||||||
const settingsSelector = (s: TDSnapshot) => s.settings
|
const settingsSelector = (s: TDSnapshot) => s.settings
|
||||||
|
|
||||||
|
@ -11,39 +11,43 @@ export function PreferencesMenu() {
|
||||||
const settings = app.useStore(settingsSelector)
|
const settings = app.useStore(settingsSelector)
|
||||||
|
|
||||||
const toggleDebugMode = React.useCallback(() => {
|
const toggleDebugMode = React.useCallback(() => {
|
||||||
app.setSetting('isDebugMode', (v) => !v)
|
app.setSetting('isDebugMode', v => !v)
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
const toggleDarkMode = React.useCallback(() => {
|
const toggleDarkMode = React.useCallback(() => {
|
||||||
app.setSetting('isDarkMode', (v) => !v)
|
app.setSetting('isDarkMode', v => !v)
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
const toggleFocusMode = React.useCallback(() => {
|
const toggleFocusMode = React.useCallback(() => {
|
||||||
app.setSetting('isFocusMode', (v) => !v)
|
app.setSetting('isFocusMode', v => !v)
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
const toggleRotateHandle = React.useCallback(() => {
|
const toggleRotateHandle = React.useCallback(() => {
|
||||||
app.setSetting('showRotateHandles', (v) => !v)
|
app.setSetting('showRotateHandles', v => !v)
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
const toggleGrid = React.useCallback(() => {
|
const toggleGrid = React.useCallback(() => {
|
||||||
app.setSetting('showGrid', (v) => !v)
|
app.setSetting('showGrid', v => !v)
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
const toggleBoundShapesHandle = React.useCallback(() => {
|
const toggleBoundShapesHandle = React.useCallback(() => {
|
||||||
app.setSetting('showBindingHandles', (v) => !v)
|
app.setSetting('showBindingHandles', v => !v)
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
const toggleisSnapping = React.useCallback(() => {
|
const toggleisSnapping = React.useCallback(() => {
|
||||||
app.setSetting('isSnapping', (v) => !v)
|
app.setSetting('isSnapping', v => !v)
|
||||||
|
}, [app])
|
||||||
|
|
||||||
|
const toggleKeepStyleMenuOpen = React.useCallback(() => {
|
||||||
|
app.setSetting('keepStyleMenuOpen', v => !v)
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
const toggleCloneControls = React.useCallback(() => {
|
const toggleCloneControls = React.useCallback(() => {
|
||||||
app.setSetting('showCloneHandles', (v) => !v)
|
app.setSetting('showCloneHandles', v => !v)
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
const toggleCadSelectMode = React.useCallback(() => {
|
const toggleCadSelectMode = React.useCallback(() => {
|
||||||
app.setSetting('isCadSelectMode', (v) => !v)
|
app.setSetting('isCadSelectMode', v => !v)
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -87,6 +91,13 @@ export function PreferencesMenu() {
|
||||||
>
|
>
|
||||||
Use CAD Selection
|
Use CAD Selection
|
||||||
</DMCheckboxItem>
|
</DMCheckboxItem>
|
||||||
|
<DMCheckboxItem
|
||||||
|
checked={settings.keepStyleMenuOpen}
|
||||||
|
onCheckedChange={toggleKeepStyleMenuOpen}
|
||||||
|
id="TD-MenuItem-Preferences-Style_menu"
|
||||||
|
>
|
||||||
|
Keep Style Menu Open
|
||||||
|
</DMCheckboxItem>
|
||||||
<DMCheckboxItem
|
<DMCheckboxItem
|
||||||
checked={settings.isSnapping}
|
checked={settings.isSnapping}
|
||||||
onCheckedChange={toggleisSnapping}
|
onCheckedChange={toggleisSnapping}
|
||||||
|
|
|
@ -2,7 +2,12 @@ import * as React from 'react'
|
||||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||||
import { strokes, fills, defaultTextStyle } from '~state/shapes/shared/shape-styles'
|
import { strokes, fills, defaultTextStyle } from '~state/shapes/shared/shape-styles'
|
||||||
import { useTldrawApp } from '~hooks'
|
import { useTldrawApp } from '~hooks'
|
||||||
import { DMCheckboxItem, DMContent, DMRadioItem } from '~components/Primitives/DropdownMenu'
|
import {
|
||||||
|
DMCheckboxItem,
|
||||||
|
DMContent,
|
||||||
|
DMDivider,
|
||||||
|
DMRadioItem,
|
||||||
|
} from '~components/Primitives/DropdownMenu'
|
||||||
import {
|
import {
|
||||||
CircleIcon,
|
CircleIcon,
|
||||||
DashDashedIcon,
|
DashDashedIcon,
|
||||||
|
@ -63,6 +68,8 @@ const ALIGN_ICONS = {
|
||||||
|
|
||||||
const themeSelector = (s: TDSnapshot) => (s.settings.isDarkMode ? 'dark' : 'light')
|
const themeSelector = (s: TDSnapshot) => (s.settings.isDarkMode ? 'dark' : 'light')
|
||||||
|
|
||||||
|
const keepOpenSelector = (s: TDSnapshot) => s.settings.keepStyleMenuOpen
|
||||||
|
|
||||||
const optionsSelector = (s: TDSnapshot) => {
|
const optionsSelector = (s: TDSnapshot) => {
|
||||||
const { activeTool, currentPageId: pageId } = s.appState
|
const { activeTool, currentPageId: pageId } = s.appState
|
||||||
switch (activeTool) {
|
switch (activeTool) {
|
||||||
|
@ -104,6 +111,8 @@ export const StyleMenu = React.memo(function ColorMenu() {
|
||||||
|
|
||||||
const theme = app.useStore(themeSelector)
|
const theme = app.useStore(themeSelector)
|
||||||
|
|
||||||
|
const keepOpen = app.useStore(keepOpenSelector)
|
||||||
|
|
||||||
const options = app.useStore(optionsSelector)
|
const options = app.useStore(optionsSelector)
|
||||||
|
|
||||||
const currentStyle = app.useStore(currentStyleSelector)
|
const currentStyle = app.useStore(currentStyleSelector)
|
||||||
|
@ -126,9 +135,9 @@ export const StyleMenu = React.memo(function ColorMenu() {
|
||||||
} else {
|
} else {
|
||||||
const overrides = new Set<string>([])
|
const overrides = new Set<string>([])
|
||||||
app.selectedIds
|
app.selectedIds
|
||||||
.map((id) => page.shapes[id])
|
.map(id => page.shapes[id])
|
||||||
.forEach((shape) => {
|
.forEach(shape => {
|
||||||
STYLE_KEYS.forEach((key) => {
|
STYLE_KEYS.forEach(key => {
|
||||||
if (overrides.has(key)) return
|
if (overrides.has(key)) return
|
||||||
if (commonStyle[key] === undefined) {
|
if (commonStyle[key] === undefined) {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
@ -152,6 +161,10 @@ export const StyleMenu = React.memo(function ColorMenu() {
|
||||||
}
|
}
|
||||||
}, [currentStyle, selectedIds])
|
}, [currentStyle, selectedIds])
|
||||||
|
|
||||||
|
const handleToggleKeepOpen = React.useCallback((checked: boolean) => {
|
||||||
|
app.setSetting('keepStyleMenuOpen', checked)
|
||||||
|
}, [])
|
||||||
|
|
||||||
const handleToggleFilled = React.useCallback((checked: boolean) => {
|
const handleToggleFilled = React.useCallback((checked: boolean) => {
|
||||||
app.style({ isFilled: checked })
|
app.style({ isFilled: checked })
|
||||||
}, [])
|
}, [])
|
||||||
|
@ -180,7 +193,11 @@ export const StyleMenu = React.memo(function ColorMenu() {
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Root dir="ltr" onOpenChange={handleMenuOpenChange}>
|
<DropdownMenu.Root
|
||||||
|
dir="ltr"
|
||||||
|
onOpenChange={handleMenuOpenChange}
|
||||||
|
open={keepOpen ? true : undefined}
|
||||||
|
>
|
||||||
<DropdownMenu.Trigger asChild id="TD-Styles">
|
<DropdownMenu.Trigger asChild id="TD-Styles">
|
||||||
<ToolButton variant="text">
|
<ToolButton variant="text">
|
||||||
Styles
|
Styles
|
||||||
|
@ -240,7 +257,7 @@ export const StyleMenu = React.memo(function ColorMenu() {
|
||||||
<StyledRow id="TD-Styles-Dash-Container">
|
<StyledRow id="TD-Styles-Dash-Container">
|
||||||
Dash
|
Dash
|
||||||
<StyledGroup dir="ltr" value={displayedStyle.dash} onValueChange={handleDashChange}>
|
<StyledGroup dir="ltr" value={displayedStyle.dash} onValueChange={handleDashChange}>
|
||||||
{Object.values(DashStyle).map((style) => (
|
{Object.values(DashStyle).map(style => (
|
||||||
<DMRadioItem
|
<DMRadioItem
|
||||||
key={style}
|
key={style}
|
||||||
isActive={style === displayedStyle.dash}
|
isActive={style === displayedStyle.dash}
|
||||||
|
@ -257,7 +274,7 @@ export const StyleMenu = React.memo(function ColorMenu() {
|
||||||
<StyledRow id="TD-Styles-Size-Container">
|
<StyledRow id="TD-Styles-Size-Container">
|
||||||
Size
|
Size
|
||||||
<StyledGroup dir="ltr" value={displayedStyle.size} onValueChange={handleSizeChange}>
|
<StyledGroup dir="ltr" value={displayedStyle.size} onValueChange={handleSizeChange}>
|
||||||
{Object.values(SizeStyle).map((sizeStyle) => (
|
{Object.values(SizeStyle).map(sizeStyle => (
|
||||||
<DMRadioItem
|
<DMRadioItem
|
||||||
key={sizeStyle}
|
key={sizeStyle}
|
||||||
isActive={sizeStyle === displayedStyle.size}
|
isActive={sizeStyle === displayedStyle.size}
|
||||||
|
@ -277,7 +294,7 @@ export const StyleMenu = React.memo(function ColorMenu() {
|
||||||
<StyledRow id="TD-Styles-Font-Container">
|
<StyledRow id="TD-Styles-Font-Container">
|
||||||
Font
|
Font
|
||||||
<StyledGroup dir="ltr" value={displayedStyle.font} onValueChange={handleFontChange}>
|
<StyledGroup dir="ltr" value={displayedStyle.font} onValueChange={handleFontChange}>
|
||||||
{Object.values(FontStyle).map((fontStyle) => (
|
{Object.values(FontStyle).map(fontStyle => (
|
||||||
<DMRadioItem
|
<DMRadioItem
|
||||||
key={fontStyle}
|
key={fontStyle}
|
||||||
isActive={fontStyle === displayedStyle.font}
|
isActive={fontStyle === displayedStyle.font}
|
||||||
|
@ -299,7 +316,7 @@ export const StyleMenu = React.memo(function ColorMenu() {
|
||||||
value={displayedStyle.textAlign}
|
value={displayedStyle.textAlign}
|
||||||
onValueChange={handleTextAlignChange}
|
onValueChange={handleTextAlignChange}
|
||||||
>
|
>
|
||||||
{Object.values(AlignStyle).map((style) => (
|
{Object.values(AlignStyle).map(style => (
|
||||||
<DMRadioItem
|
<DMRadioItem
|
||||||
key={style}
|
key={style}
|
||||||
isActive={style === displayedStyle.textAlign}
|
isActive={style === displayedStyle.textAlign}
|
||||||
|
@ -316,6 +333,15 @@ export const StyleMenu = React.memo(function ColorMenu() {
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
<DMDivider />
|
||||||
|
<DMCheckboxItem
|
||||||
|
variant="styleMenu"
|
||||||
|
checked={keepOpen}
|
||||||
|
onCheckedChange={handleToggleKeepOpen}
|
||||||
|
id="TD-Styles-Keep-Open"
|
||||||
|
>
|
||||||
|
Keep Open
|
||||||
|
</DMCheckboxItem>
|
||||||
</DMContent>
|
</DMContent>
|
||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,7 +9,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
const canHandleEvent = React.useCallback(
|
const canHandleEvent = React.useCallback(
|
||||||
(ignoreMenus = false) => {
|
(ignoreMenus = false) => {
|
||||||
const elm = ref.current
|
const elm = ref.current
|
||||||
if (ignoreMenus && app.isMenuOpen) return true
|
if (ignoreMenus && (app.isMenuOpen || app.settings.keepStyleMenuOpen)) return true
|
||||||
return elm && (document.activeElement === elm || elm.contains(document.activeElement))
|
return elm && (document.activeElement === elm || elm.contains(document.activeElement))
|
||||||
},
|
},
|
||||||
[ref]
|
[ref]
|
||||||
|
@ -159,7 +159,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'ctrl+shift+d,⌘+shift+d',
|
'ctrl+shift+d,⌘+shift+d',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent(true)) return
|
if (!canHandleEvent(true)) return
|
||||||
app.toggleDarkMode()
|
app.toggleDarkMode()
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -192,12 +192,17 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
// File System
|
// File System
|
||||||
|
|
||||||
const { onNewProject, onOpenProject, onSaveProject, onSaveProjectAs, onOpenMedia } =
|
const {
|
||||||
useFileSystemHandlers()
|
onNewProject,
|
||||||
|
onOpenProject,
|
||||||
|
onSaveProject,
|
||||||
|
onSaveProjectAs,
|
||||||
|
onOpenMedia,
|
||||||
|
} = useFileSystemHandlers()
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'ctrl+n,⌘+n',
|
'ctrl+n,⌘+n',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
|
|
||||||
onNewProject(e)
|
onNewProject(e)
|
||||||
|
@ -207,7 +212,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
)
|
)
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'ctrl+s,⌘+s',
|
'ctrl+s,⌘+s',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
|
|
||||||
onSaveProject(e)
|
onSaveProject(e)
|
||||||
|
@ -218,7 +223,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'ctrl+shift+s,⌘+shift+s',
|
'ctrl+shift+s,⌘+shift+s',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
|
|
||||||
onSaveProjectAs(e)
|
onSaveProjectAs(e)
|
||||||
|
@ -228,7 +233,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
)
|
)
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'ctrl+o,⌘+o',
|
'ctrl+o,⌘+o',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
|
|
||||||
onOpenProject(e)
|
onOpenProject(e)
|
||||||
|
@ -238,7 +243,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
)
|
)
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'ctrl+u,⌘+u',
|
'ctrl+u,⌘+u',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
onOpenMedia(e)
|
onOpenMedia(e)
|
||||||
},
|
},
|
||||||
|
@ -306,7 +311,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'ctrl+=,⌘+=,ctrl+num_subtract,⌘+num_subtract',
|
'ctrl+=,⌘+=,ctrl+num_subtract,⌘+num_subtract',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent(true)) return
|
if (!canHandleEvent(true)) return
|
||||||
app.zoomIn()
|
app.zoomIn()
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -317,7 +322,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'ctrl+-,⌘+-,ctrl+num_add,⌘+num_add',
|
'ctrl+-,⌘+-,ctrl+num_add,⌘+num_add',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent(true)) return
|
if (!canHandleEvent(true)) return
|
||||||
|
|
||||||
app.zoomOut()
|
app.zoomOut()
|
||||||
|
@ -361,7 +366,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'ctrl+d,⌘+d',
|
'ctrl+d,⌘+d',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
|
|
||||||
app.duplicate()
|
app.duplicate()
|
||||||
|
@ -536,7 +541,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'⌘+shift+c,ctrl+shift+c',
|
'⌘+shift+c,ctrl+shift+c',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
|
|
||||||
app.copySvg()
|
app.copySvg()
|
||||||
|
@ -571,7 +576,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'⌘+g,ctrl+g',
|
'⌘+g,ctrl+g',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
|
|
||||||
app.group()
|
app.group()
|
||||||
|
@ -583,7 +588,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'⌘+shift+g,ctrl+shift+g',
|
'⌘+shift+g,ctrl+shift+g',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
|
|
||||||
app.ungroup()
|
app.ungroup()
|
||||||
|
@ -637,7 +642,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'ctrl+shift+backspace,⌘+shift+backspace',
|
'ctrl+shift+backspace,⌘+shift+backspace',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
if (app.settings.isDebugMode) {
|
if (app.settings.isDebugMode) {
|
||||||
app.resetDocument()
|
app.resetDocument()
|
||||||
|
@ -652,7 +657,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'alt+command+l,alt+ctrl+l',
|
'alt+command+l,alt+ctrl+l',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent(true)) return
|
if (!canHandleEvent(true)) return
|
||||||
app.style({ textAlign: AlignStyle.Start })
|
app.style({ textAlign: AlignStyle.Start })
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -663,7 +668,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'alt+command+t,alt+ctrl+t',
|
'alt+command+t,alt+ctrl+t',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent(true)) return
|
if (!canHandleEvent(true)) return
|
||||||
app.style({ textAlign: AlignStyle.Middle })
|
app.style({ textAlign: AlignStyle.Middle })
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -674,7 +679,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'alt+command+r,alt+ctrl+r',
|
'alt+command+r,alt+ctrl+r',
|
||||||
(e) => {
|
e => {
|
||||||
if (!canHandleEvent(true)) return
|
if (!canHandleEvent(true)) return
|
||||||
app.style({ textAlign: AlignStyle.End })
|
app.style({ textAlign: AlignStyle.End })
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
|
@ -4086,6 +4086,7 @@ export class TldrawApp extends StateManager<TDSnapshot> {
|
||||||
isSnapping: false,
|
isSnapping: false,
|
||||||
isDebugMode: false,
|
isDebugMode: false,
|
||||||
isReadonlyMode: false,
|
isReadonlyMode: false,
|
||||||
|
keepStyleMenuOpen: false,
|
||||||
nudgeDistanceLarge: 16,
|
nudgeDistanceLarge: 16,
|
||||||
nudgeDistanceSmall: 1,
|
nudgeDistanceSmall: 1,
|
||||||
showRotateHandles: true,
|
showRotateHandles: true,
|
||||||
|
|
|
@ -11,8 +11,8 @@ export function migrate(document: TDDocument, newVersion: number): TDDocument {
|
||||||
// Remove unused assets when loading a document
|
// Remove unused assets when loading a document
|
||||||
const assetIdsInUse = new Set<string>()
|
const assetIdsInUse = new Set<string>()
|
||||||
|
|
||||||
Object.values(document.pages).forEach((page) =>
|
Object.values(document.pages).forEach(page =>
|
||||||
Object.values(page.shapes).forEach((shape) => {
|
Object.values(page.shapes).forEach(shape => {
|
||||||
const { parentId, children, assetId } = shape
|
const { parentId, children, assetId } = shape
|
||||||
|
|
||||||
if (assetId) {
|
if (assetId) {
|
||||||
|
@ -26,7 +26,7 @@ export function migrate(document: TDDocument, newVersion: number): TDDocument {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shape.type === TDShapeType.Group && children) {
|
if (shape.type === TDShapeType.Group && children) {
|
||||||
children.forEach((childId) => {
|
children.forEach(childId => {
|
||||||
if (!page.shapes[childId]) {
|
if (!page.shapes[childId]) {
|
||||||
console.warn('Encountered a parent with a missing child!', shape.id, childId)
|
console.warn('Encountered a parent with a missing child!', shape.id, childId)
|
||||||
children?.splice(children.indexOf(childId), 1)
|
children?.splice(children.indexOf(childId), 1)
|
||||||
|
@ -38,7 +38,7 @@ export function migrate(document: TDDocument, newVersion: number): TDDocument {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
Object.keys(document.assets).forEach((assetId) => {
|
Object.keys(document.assets).forEach(assetId => {
|
||||||
if (!assetIdsInUse.has(assetId)) {
|
if (!assetIdsInUse.has(assetId)) {
|
||||||
delete document.assets[assetId]
|
delete document.assets[assetId]
|
||||||
}
|
}
|
||||||
|
@ -47,22 +47,22 @@ export function migrate(document: TDDocument, newVersion: number): TDDocument {
|
||||||
if (version === newVersion) return document
|
if (version === newVersion) return document
|
||||||
|
|
||||||
if (version < 14) {
|
if (version < 14) {
|
||||||
Object.values(document.pages).forEach((page) => {
|
Object.values(document.pages).forEach(page => {
|
||||||
Object.values(page.shapes)
|
Object.values(page.shapes)
|
||||||
.filter((shape) => shape.type === TDShapeType.Text)
|
.filter(shape => shape.type === TDShapeType.Text)
|
||||||
.forEach((shape) => (shape as TextShape).style.font === FontStyle.Script)
|
.forEach(shape => (shape as TextShape).style.font === FontStyle.Script)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lowercase styles, move binding meta to binding
|
// Lowercase styles, move binding meta to binding
|
||||||
if (version <= 13) {
|
if (version <= 13) {
|
||||||
Object.values(document.pages).forEach((page) => {
|
Object.values(document.pages).forEach(page => {
|
||||||
Object.values(page.bindings).forEach((binding) => {
|
Object.values(page.bindings).forEach(binding => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
Object.assign(binding, (binding as any).meta)
|
Object.assign(binding, (binding as any).meta)
|
||||||
})
|
})
|
||||||
|
|
||||||
Object.values(page.shapes).forEach((shape) => {
|
Object.values(page.shapes).forEach(shape => {
|
||||||
Object.entries(shape.style).forEach(([id, style]) => {
|
Object.entries(shape.style).forEach(([id, style]) => {
|
||||||
if (typeof style === 'string') {
|
if (typeof style === 'string') {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -95,8 +95,8 @@ export function migrate(document: TDDocument, newVersion: number): TDDocument {
|
||||||
document.assets = {}
|
document.assets = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.values(document.pages).forEach((page) => {
|
Object.values(document.pages).forEach(page => {
|
||||||
Object.values(page.shapes).forEach((shape) => {
|
Object.values(page.shapes).forEach(shape => {
|
||||||
if (version < 15.2) {
|
if (version < 15.2) {
|
||||||
if (shape.type === TDShapeType.Image || shape.type === TDShapeType.Video) {
|
if (shape.type === TDShapeType.Image || shape.type === TDShapeType.Video) {
|
||||||
shape.style.isFilled = true
|
shape.style.isFilled = true
|
||||||
|
@ -118,8 +118,8 @@ export function migrate(document: TDDocument, newVersion: number): TDDocument {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
Object.values(document.pageStates).forEach((pageState) => {
|
Object.values(document.pageStates).forEach(pageState => {
|
||||||
pageState.selectedIds = pageState.selectedIds.filter((id) => {
|
pageState.selectedIds = pageState.selectedIds.filter(id => {
|
||||||
return document.pages[pageState.id].shapes[id] !== undefined
|
return document.pages[pageState.id].shapes[id] !== undefined
|
||||||
})
|
})
|
||||||
pageState.bindingId = undefined
|
pageState.bindingId = undefined
|
||||||
|
|
|
@ -85,6 +85,7 @@ export interface TDSnapshot {
|
||||||
isPenMode: boolean
|
isPenMode: boolean
|
||||||
isReadonlyMode: boolean
|
isReadonlyMode: boolean
|
||||||
isZoomSnap: boolean
|
isZoomSnap: boolean
|
||||||
|
keepStyleMenuOpen: boolean
|
||||||
nudgeDistanceSmall: number
|
nudgeDistanceSmall: number
|
||||||
nudgeDistanceLarge: number
|
nudgeDistanceLarge: number
|
||||||
isFocusMode: boolean
|
isFocusMode: boolean
|
||||||
|
|
Loading…
Reference in a new issue