Enhance (Whiteboards): Paste and dnd behavior (also add a placeholder to shape labels) (#8753)

* fix: paste shape

* enhance: add label placeholder

* fix: don't create portal on ref click

* enhance: allow ref dragging

* fix: create line binding on drop

* enhance: allow creating url based elements on drop
pull/8768/head
Konstantinos 2023-03-06 06:04:24 +02:00 committed by GitHub
parent 91e89ef2d6
commit 82e5abf9e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 32 deletions

View File

@ -511,11 +511,6 @@
(:db/id page-entity)
:page))
(whiteboard-handler/inside-portal? (.-target e))
(whiteboard-handler/add-new-block-portal-shape!
page-name
(whiteboard-handler/closest-shape (.-target e)))
whiteboard-page?
(route-handler/redirect-to-whiteboard! page-name)
@ -546,7 +541,9 @@
(str " page-property-key block-property")
untitled? (str " opacity-50"))
:data-ref page-name
:on-mouse-down (fn [e] (open-page-ref e page-name redirect-page-name page-name-in-block contents-page? whiteboard-page?))
:draggable true
:on-drag-start (fn [e] (editor-handler/block->data-transfer! page-name e))
:on-mouse-up (fn [e] (open-page-ref e page-name redirect-page-name page-name-in-block contents-page? whiteboard-page?))
:on-key-up (fn [e] (when (and e (= (.-key e) "Enter"))
(open-page-ref e page-name redirect-page-name page-name-in-block contents-page? whiteboard-page?)))}

View File

@ -29,8 +29,8 @@ import { LogseqContext, LogseqContextValue } from '../lib/logseq-context'
const isValidURL = (url: string) => {
try {
new URL(url)
return true
const parsedUrl = new URL(url)
return parsedUrl.host && ['http:', 'https:'].includes(parsedUrl.protocol)
} catch {
return false
}
@ -105,17 +105,17 @@ const handleCreatingShapes = async (
const existingAsset = Object.values(app.assets).find(asset => asset.src === url)
if (existingAsset) {
return existingAsset as VideoImageAsset
} else {
// Create a new asset for this image
const asset: VideoImageAsset = {
id: uniqueId(),
type: isVideo ? 'video' : 'image',
src: url,
size: await getSizeFromSrc(handlers.makeAssetUrl(url), isVideo),
}
return asset
}
}
// Create a new asset for this image
const asset: VideoImageAsset = {
id: uniqueId(),
type: isVideo ? 'video' : 'image',
src: url,
size: await getSizeFromSrc(handlers.makeAssetUrl(url), isVideo),
}
return asset
}
async function createAssetsFromFiles(files: File[]) {
const tasks = files
@ -272,7 +272,7 @@ const handleCreatingShapes = async (
}
async function tryCreateShapeFromURL(rawText: string) {
if (isValidURL(rawText) && !(shiftKey || fromDrop)) {
if (isValidURL(rawText) && !shiftKey) {
if (YOUTUBE_REGEX.test(rawText)) {
return [
{
@ -415,7 +415,7 @@ const handleCreatingShapes = async (
}
app.currentPage.updateBindings(Object.fromEntries(bindingsToCreate.map(b => [b.id, b])))
if (app.selectedShapesArray.length === 1 && allShapesToAdd.length === 1 && !fromDrop) {
if (app.selectedShapesArray.length === 1 && allShapesToAdd.length === 1 && fromDrop) {
const source = app.selectedShapesArray[0]
const target = app.getShapeById(allShapesToAdd[0].id!)!
app.createNewLineBinding(source, target)

View File

@ -77,7 +77,7 @@ export class LineShape extends TLLineShape<LineShapeProps> {
const labelSize =
label || isEditing
? getTextLabelSize(
label,
label || "Enter text",
{ fontFamily: 'var(--ls-font-family)', fontSize, lineHeight: 1, fontWeight },
6
)

View File

@ -5,6 +5,7 @@ import { TextAreaUtils } from './TextAreaUtils'
const stopPropagation = (e: KeyboardEvent | React.SyntheticEvent<any, Event>) => e.stopPropagation()
const placeholder = "Enter text"
export interface TextLabelProps {
font: string
text: string
@ -57,11 +58,7 @@ export const TextLabel = React.memo(function TextLabel({
if (!(e.key === 'Meta' || e.metaKey)) {
e.stopPropagation()
} else if (e.key === 'z' && e.metaKey) {
if (e.shiftKey) {
document.execCommand('redo', false)
} else {
document.execCommand('undo', false)
}
document.execCommand(e.shiftKey ? 'redo' : 'undo', false)
e.stopPropagation()
e.preventDefault()
return
@ -92,8 +89,7 @@ export const TextLabel = React.memo(function TextLabel({
const handleFocus = React.useCallback(
(e: React.FocusEvent<HTMLTextAreaElement>) => {
if (!isEditing) return
if (!rIsMounted.current) return
if (!isEditing || !rIsMounted.current) return
if (document.activeElement === e.currentTarget) {
e.currentTarget.select()
@ -130,7 +126,7 @@ export const TextLabel = React.memo(function TextLabel({
const elm = rInnerWrapper.current
if (!elm) return
const size = getTextLabelSize(
text,
text || placeholder,
{ fontFamily: 'var(--ls-font-family)', fontSize, lineHeight: 1, fontWeight },
4
)
@ -172,7 +168,7 @@ export const TextLabel = React.memo(function TextLabel({
autoCorrect="false"
autoSave="false"
autoFocus
placeholder=""
placeholder={placeholder}
spellCheck="true"
wrap="off"
dir="auto"

View File

@ -122,9 +122,8 @@ export class TLPage<S extends TLShape = TLShape, E extends TLEventMap = TLEventM
private parseShapesArg<S>(shapes: S[] | string[]) {
if (typeof shapes[0] === 'string') {
return this.shapes.filter(shape => (shapes as string[]).includes(shape.id))
} else {
return shapes as S[]
}
return shapes as S[]
}
@action removeShapes(...shapes: S[] | string[]) {