|
@@ -15,14 +15,20 @@ import { useFileSystemHandlers } from '~hooks'
|
15
|
15
|
import { HeartIcon } from '~components/Primitives/icons/HeartIcon'
|
16
|
16
|
import { preventEvent } from '~components/preventEvent'
|
17
|
17
|
import { DiscordIcon } from '~components/Primitives/icons'
|
|
18
|
+import type { TDSnapshot } from '~types'
|
18
|
19
|
|
19
|
20
|
interface MenuProps {
|
20
|
21
|
showSponsorLink: boolean
|
21
|
22
|
readOnly: boolean
|
22
|
23
|
}
|
23
|
24
|
|
|
25
|
+const numberOfSelectedIdsSelector = (s: TDSnapshot) => {
|
|
26
|
+ return s.document.pageStates[s.appState.currentPageId].selectedIds.length
|
|
27
|
+}
|
|
28
|
+
|
24
|
29
|
export const Menu = React.memo(function Menu({ showSponsorLink, readOnly }: MenuProps) {
|
25
|
30
|
const app = useTldrawApp()
|
|
31
|
+ const numberOfSelectedIds = app.useStore(numberOfSelectedIdsSelector)
|
26
|
32
|
|
27
|
33
|
const { onNewProject, onOpenProject, onSaveProject, onSaveProjectAs } = useFileSystemHandlers()
|
28
|
34
|
|
|
@@ -70,6 +76,8 @@ export const Menu = React.memo(function Menu({ showSponsorLink, readOnly }: Menu
|
70
|
76
|
|
71
|
77
|
const showSignInOutMenu = app.callbacks.onSignIn || app.callbacks.onSignOut || showSponsorLink
|
72
|
78
|
|
|
79
|
+ const hasSelection = numberOfSelectedIds > 0
|
|
80
|
+
|
73
|
81
|
return (
|
74
|
82
|
<DropdownMenu.Root dir="ltr">
|
75
|
83
|
<DMTriggerIcon isSponsor={showSponsorLink}>
|
|
@@ -110,20 +118,30 @@ export const Menu = React.memo(function Menu({ showSponsorLink, readOnly }: Menu
|
110
|
118
|
Redo
|
111
|
119
|
</DMItem>
|
112
|
120
|
<DMDivider dir="ltr" />
|
113
|
|
- <DMItem onSelect={preventEvent} onClick={handleCut} kbd="#X">
|
|
121
|
+ <DMItem onSelect={preventEvent} disabled={!hasSelection} onClick={handleCut} kbd="#X">
|
114
|
122
|
Cut
|
115
|
123
|
</DMItem>
|
116
|
|
- <DMItem onSelect={preventEvent} onClick={handleCopy} kbd="#C">
|
|
124
|
+ <DMItem
|
|
125
|
+ onSelect={preventEvent}
|
|
126
|
+ disabled={!hasSelection}
|
|
127
|
+ onClick={handleCopy}
|
|
128
|
+ kbd="#C"
|
|
129
|
+ >
|
117
|
130
|
Copy
|
118
|
131
|
</DMItem>
|
119
|
132
|
<DMItem onSelect={preventEvent} onClick={handlePaste} kbd="#V">
|
120
|
133
|
Paste
|
121
|
134
|
</DMItem>
|
122
|
135
|
<DMDivider dir="ltr" />
|
123
|
|
- <DMItem onSelect={preventEvent} onClick={handleCopySvg} kbd="#⇧C">
|
|
136
|
+ <DMItem
|
|
137
|
+ onSelect={preventEvent}
|
|
138
|
+ disabled={!hasSelection}
|
|
139
|
+ onClick={handleCopySvg}
|
|
140
|
+ kbd="#⇧C"
|
|
141
|
+ >
|
124
|
142
|
Copy as SVG
|
125
|
143
|
</DMItem>
|
126
|
|
- <DMItem onSelect={preventEvent} onClick={handleCopyJson}>
|
|
144
|
+ <DMItem onSelect={preventEvent} disabled={!hasSelection} onClick={handleCopyJson}>
|
127
|
145
|
Copy as JSON
|
128
|
146
|
</DMItem>
|
129
|
147
|
<DMDivider dir="ltr" />
|