diff --git a/tldraw/apps/tldraw-logseq/src/app.tsx b/tldraw/apps/tldraw-logseq/src/app.tsx index 2ec727aedf..c492bd7d56 100644 --- a/tldraw/apps/tldraw-logseq/src/app.tsx +++ b/tldraw/apps/tldraw-logseq/src/app.tsx @@ -28,6 +28,7 @@ import { shapes, TextTool, YouTubeTool, + IFrameTool, type Shape, } from './lib' import { LogseqContext, type LogseqContextValue } from './lib/logseq-context' @@ -47,6 +48,7 @@ const tools: TLReactToolConstructor[] = [ PencilTool, TextTool, YouTubeTool, + IFrameTool, HTMLTool, LogseqPortalTool, ] diff --git a/tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx b/tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx index 4d4cb8b3c3..0f361f9056 100644 --- a/tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx +++ b/tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx @@ -7,6 +7,7 @@ import type { LogseqPortalShape, TextShape, HTMLShape, + IFrameShape, YouTubeShape, BoxShape, PolygonShape, @@ -36,13 +37,19 @@ export const contextBarActionTypes = [ 'ScaleLevel', 'TextStyle', 'YoutubeLink', + 'IFrameSource', 'LogseqPortalViewMode', 'ArrowMode', 'OpenPage', ] as const type ContextBarActionType = typeof contextBarActionTypes[number] -const singleShapeActions: ContextBarActionType[] = ['Edit', 'YoutubeLink', 'OpenPage'] +const singleShapeActions: ContextBarActionType[] = [ + 'Edit', + 'YoutubeLink', + 'IFrameSource', + 'OpenPage', +] const contextBarActionMapping = new Map() @@ -51,6 +58,7 @@ type ShapeType = Shape['props']['type'] export const shapeMapping: Partial> = { 'logseq-portal': ['Edit', 'LogseqPortalViewMode', 'ScaleLevel', 'OpenPage', 'AutoResizing'], youtube: ['YoutubeLink'], + iframe: ['IFrameSource'], box: ['Swatch', 'NoFill', 'StrokeType'], ellipse: ['Swatch', 'NoFill', 'StrokeType'], polygon: ['Swatch', 'NoFill', 'StrokeType'], @@ -239,6 +247,42 @@ const OpenPageAction = observer(() => { ) }) +const IFrameSourceAction = observer(() => { + const app = useApp() + const shape = filterShapeByAction(app.selectedShapesArray, 'IFrameSource')[0] + + const handleChange = React.useCallback((e: React.ChangeEvent) => { + shape.onIFrameSourceChange(e.target.value.trim().toLowerCase()) + app.persist() + }, []) + + const handleReload = React.useCallback(() => { + shape.reload() + }, []) + + return ( + + + + + + ) +}) + const YoutubeLinkAction = observer(() => { const app = useApp() const shape = filterShapeByAction(app.selectedShapesArray, 'YoutubeLink')[0] @@ -450,6 +494,7 @@ contextBarActionMapping.set('LogseqPortalViewMode', LogseqPortalViewModeAction) contextBarActionMapping.set('ScaleLevel', ScaleLevelAction) contextBarActionMapping.set('OpenPage', OpenPageAction) contextBarActionMapping.set('YoutubeLink', YoutubeLinkAction) +contextBarActionMapping.set('IFrameSource', IFrameSourceAction) contextBarActionMapping.set('NoFill', NoFillAction) contextBarActionMapping.set('Swatch', SwatchAction) contextBarActionMapping.set('StrokeType', StrokeTypeAction) diff --git a/tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts b/tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts index 8b4ff85f7e..ec0579c0d5 100644 --- a/tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts +++ b/tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts @@ -19,6 +19,7 @@ import { LogseqPortalShape, VideoShape, ImageShape, + IFrameShape, } from '../lib' import type { LogseqContextValue } from '../lib/logseq-context' @@ -243,7 +244,13 @@ export function usePaste(context: LogseqContextValue) { ) { return true } - // ??? deal with normal URLs? + + shapesToCreate.push({ + ...IFrameShape.defaultProps, + url: rawText, + point: [point[0], point[1]], + }) + return true } return false } diff --git a/tldraw/apps/tldraw-logseq/src/lib/shapes/IFrameShape.tsx b/tldraw/apps/tldraw-logseq/src/lib/shapes/IFrameShape.tsx new file mode 100644 index 0000000000..f2fcad6db1 --- /dev/null +++ b/tldraw/apps/tldraw-logseq/src/lib/shapes/IFrameShape.tsx @@ -0,0 +1,87 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import * as React from 'react' +import { TLBoxShape, TLBoxShapeProps } from '@tldraw/core' +import { HTMLContainer, TLComponentProps } from '@tldraw/react' +import { action, computed } from 'mobx' +import { observer } from 'mobx-react-lite' + +export interface IFrameShapeProps extends TLBoxShapeProps { + type: 'iframe' + url: string +} + +export class IFrameShape extends TLBoxShape { + static id = 'iframe' + frameRef = React.createRef() + + static defaultProps: IFrameShapeProps = { + id: 'iframe', + type: 'iframe', + parentId: 'page', + point: [0, 0], + size: [853, 480], + url: '', + } + + canEdit = true + + @action onIFrameSourceChange = (url: string) => { + this.update({ url }) + } + + @action reload = () => { + this.frameRef.current.src = this.frameRef?.current?.src + } + + ReactComponent = observer(({ events, isErasing, isEditing }: TLComponentProps) => { + const ref = React.useRef(null) + + return ( + +
+ {this.props.url && ( +
+