Skip to content

Commit e99ee7a

Browse files
committed
feat(OUT-2891): implement embed UI
1 parent 283f2fb commit e99ee7a

2 files changed

Lines changed: 40 additions & 31 deletions

File tree

‎src/features/editor/components/Editor/extensions/Embed.ext/Embed.tsx‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
import type { IframeOptions } from '@extensions/Embed.ext'
1+
import type { EmbedOptions } from '@extensions/Embed.ext'
22
import { ResizeBar } from '@extensions/Embed.ext/ResizeBar'
33
import { type NodeViewProps, NodeViewWrapper } from '@tiptap/react'
44
import { useCallback, useState } from 'react'
55
import { debounce } from '@/utils/debounce'
66

7-
interface IframeProps extends NodeViewProps {
7+
interface EmbedProps extends NodeViewProps {
88
extension: NodeViewProps['extension'] & {
9-
options: IframeOptions
9+
options: EmbedOptions
1010
}
1111
}
1212

13-
export const IframeEmbed = (props: IframeProps) => {
13+
export const Embed = (props: EmbedProps) => {
1414
const [isResizing, setIsResizing] = useState(false)
1515

1616
const handleMouseDown = useCallback(
@@ -55,7 +55,7 @@ export const IframeEmbed = (props: IframeProps) => {
5555
}
5656
}
5757

58-
const isReadonly = true
58+
const isReadonly = false
5959

6060
return (
6161
<NodeViewWrapper className="embed relative">
Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,69 @@
11
import type { Editor } from '@tiptap/core'
2-
import { type SyntheticEvent, useEffect, useRef, useState } from 'react'
2+
import { Icon } from 'copilot-design-system'
3+
import { type KeyboardEvent, useEffect, useRef, useState } from 'react'
34
import { fixUrl } from '@/utils/urls'
45

5-
interface IframeBubbleInputProps {
6+
interface EmbedBubbleInputProps {
67
editor: Editor
8+
showEmbedInput: boolean
9+
setShowEmbedInput: (showEmbedInput: boolean) => void
710
}
811

9-
export const IframeBubbleInput = ({ editor }: IframeBubbleInputProps) => {
12+
export const EmbedBubbleInput = ({ editor, showEmbedInput, setShowEmbedInput }: EmbedBubbleInputProps) => {
1013
const [url, setUrl] = useState('')
11-
1214
const urlInputRef = useRef<HTMLInputElement>(null)
1315

14-
const handleKeyDown = (event: SyntheticEvent<HTMLDivElement>) => {
15-
//@ts-expect-error event should contain code
16+
const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
1617
if (event.code === 'Escape') {
1718
event.preventDefault()
18-
// TODO: trigger setShowEmbedInput(false)
19+
setShowEmbedInput(false)
20+
setUrl('')
21+
return
1922
}
2023

21-
//@ts-expect-error event should contain code
2224
if (event.code === 'Enter') {
2325
event.preventDefault()
24-
console.info(fixUrl(url))
2526
editor
2627
.chain()
2728
.focus()
28-
.setIframe({ src: fixUrl(url) })
29+
.setEmbed({ src: fixUrl(url) })
2930
.run()
30-
// TODO: trigger setShowEmbedInput(false)
31+
setShowEmbedInput(false)
3132
setUrl('')
3233
}
3334
}
3435

35-
// biome-ignore lint/correctness/useExhaustiveDependencies: force side-effect here
3636
useEffect(() => {
37-
if (urlInputRef.current) {
38-
urlInputRef.current.focus()
39-
}
40-
}, [urlInputRef.current])
37+
if (!showEmbedInput) return
38+
39+
// Wait until tippy has actually mounted/moved the node into the popper
40+
const raf = requestAnimationFrame(() => {
41+
urlInputRef.current?.focus()
42+
urlInputRef.current?.select()
43+
})
44+
45+
return () => cancelAnimationFrame(raf)
46+
}, [showEmbedInput])
4147

4248
return (
43-
<div>
49+
<div className="flex items-center border border-border-gray bg-white p-2">
4450
<input
51+
ref={urlInputRef}
4552
type="text"
53+
placeholder="Paste embed URL"
54+
value={url}
4655
onChange={(e) => setUrl(e.target.value)}
47-
ref={urlInputRef}
4856
onKeyDown={handleKeyDown}
49-
value={url}
50-
/>
51-
<button
52-
type="reset"
53-
onClick={() => {
54-
// TODO: setShowEmbedInput(false)
55-
console.info('cancelled')
56-
}}
57+
className="px-2 focus:outline-none"
5758
/>
59+
<button type="reset" onClick={() => setShowEmbedInput(false)}>
60+
<Icon
61+
icon="Cancel"
62+
width={16}
63+
height={16}
64+
className="text-text-primary transition-all duration-100 ease-in-out"
65+
/>
66+
</button>
5867
</div>
5968
)
6069
}

0 commit comments

Comments
 (0)