feat: introduce iframe component

pull/6647/head
Konstantinos Kaloutas 2022-09-08 11:29:50 +03:00
parent a58e513928
commit 0d16402dca
7 changed files with 137 additions and 2 deletions

View File

@ -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<Shape>[] = [
PencilTool,
TextTool,
YouTubeTool,
IFrameTool,
HTMLTool,
LogseqPortalTool,
]

View File

@ -7,6 +7,7 @@ import type {
LogseqPortalShape,
TextShape,
HTMLShape,
IFrameShape,
YouTubeShape,
BoxShape,
PolygonShape,
@ -36,13 +37,14 @@ 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<ContextBarActionType, React.FC>()
@ -51,6 +53,7 @@ type ShapeType = Shape['props']['type']
export const shapeMapping: Partial<Record<ShapeType, ContextBarActionType[]>> = {
'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 +242,34 @@ const OpenPageAction = observer(() => {
)
})
const IFrameSourceAction = observer(() => {
const app = useApp<Shape>()
const shape = filterShapeByAction<IFrameShape>(app.selectedShapesArray, 'IFrameSource')[0]
const handleChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
shape.onIFrameSourceChange(e.target.value)
app.persist()
}, [])
return (
<span className="flex gap-3">
<TextInput
title="Website Url"
className="tl-iframe-src"
value={`${shape.props.url}`}
onChange={handleChange}
/>
<button
title="Open website url"
className="tl-contextbar-button"
type="button"
onClick={() => window.logseq?.api?.open_external_link?.(shape.props.url)}
>
<TablerIcon name="external-link" />
</button>
</span>
)
})
const YoutubeLinkAction = observer(() => {
const app = useApp<Shape>()
const shape = filterShapeByAction<YouTubeShape>(app.selectedShapesArray, 'YoutubeLink')[0]
@ -450,6 +481,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)

View File

@ -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
}

View File

@ -0,0 +1,79 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
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<IFrameShapeProps> {
static id = 'iframe'
static defaultProps: IFrameShapeProps = {
id: 'iframe',
type: 'iframe',
parentId: 'page',
point: [0, 0],
size: [853, 480],
url: '',
}
@computed get url() {
return this.props.url
}
@action onIFrameSourceChange = (url: string) => {
this.update({ url })
}
ReactComponent = observer(({ events, isErasing, isEditing }: TLComponentProps) => {
return (
<HTMLContainer
style={{
overflow: 'hidden',
pointerEvents: 'all',
opacity: isErasing ? 0.2 : 1,
}}
{...events}
>
<div
className="rounded-lg w-full h-full relative overflow-hidden shadow-xl"
style={{
pointerEvents: isEditing ? 'all' : 'none',
userSelect: 'none',
}}
>
{this.url && (
<div
style={{
overflow: 'hidden',
position: 'relative',
height: '100%',
}}
>
<iframe
className="absolute inset-0 w-full h-full m-0"
width="100%"
height="100%"
src={`${this.url}`}
frameBorder="0"
/>
</div>
)}
</div>
</HTMLContainer>
)
})
ReactIndicator = observer(() => {
const {
props: {
size: [w, h],
},
} = this
return <rect width={w} height={h} fill="transparent" rx={8} ry={8} />
})
}

View File

@ -6,6 +6,7 @@ import { HighlighterShape } from './HighlighterShape'
import { HTMLShape } from './HTMLShape'
import { ImageShape } from './ImageShape'
import { VideoShape } from './VideoShape'
import { IFrameShape } from './IFrameShape'
import { LineShape } from './LineShape'
import { LogseqPortalShape } from './LogseqPortalShape'
import { PencilShape } from './PencilShape'
@ -27,6 +28,7 @@ export type Shape =
| PolygonShape
| TextShape
| YouTubeShape
| IFrameShape
| HTMLShape
| LogseqPortalShape
@ -37,6 +39,7 @@ export * from './HighlighterShape'
export * from './HTMLShape'
export * from './ImageShape'
export * from './VideoShape'
export * from './IFrameShape'
export * from './LineShape'
export * from './LogseqPortalShape'
export * from './PencilShape'
@ -56,6 +59,7 @@ export const shapes: TLReactShapeConstructor<Shape>[] = [
PolygonShape,
TextShape,
YouTubeShape,
IFrameShape,
HTMLShape,
LogseqPortalShape,
]

View File

@ -0,0 +1,10 @@
import { TLBoxTool } from '@tldraw/core'
import type { TLReactEventMap } from '@tldraw/react'
import { IFrameShape, type Shape } from '../shapes'
export class IFrameTool extends TLBoxTool<IFrameShape, Shape, TLReactEventMap> {
static id = 'iframe'
Shape = IFrameShape
}
export {}

View File

@ -10,3 +10,4 @@ export * from './TextTool'
export * from './YouTubeTool'
export * from './LogseqPortalTool'
export * from './HTMLTool'
export * from './IFrameTool'