This repository was archived by the owner on May 12, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 426
Expand file tree
/
Copy pathEditorHeaderToolDropdown.tsx
More file actions
119 lines (108 loc) · 3.29 KB
/
EditorHeaderToolDropdown.tsx
File metadata and controls
119 lines (108 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import React, { useMemo, useRef } from 'react'
import { useEffectOnce } from 'react-use'
import { getFirstFocusableChildOfElement } from '../../lib/dom'
import { FormattingTool } from './types'
import {
isSingleKeyEventOutsideOfInput,
preventKeyboardEventPropagation,
useGlobalKeyDownHandler,
useUpDownNavigationListener,
} from '../../lib/keyboard'
import {
mdiFormatHeader1,
mdiFormatHeader2,
mdiFormatHeader3,
mdiFormatHeader4,
mdiFormatHeader5,
mdiFormatHeader6,
} from '@mdi/js'
import ContextMenuItem from '../Topbar/Controls/ControlsContextMenu/ControlsContextMenuItem'
import { StyledEditorToolDropdownContainer } from './styled'
import styled from '../../../design/lib/styled'
import Icon from '../../../design/components/atoms/Icon'
interface EditorHeaderToolDropdownProps {
onFormatCallback: (format: FormattingTool) => void
closeDropdowndown: () => void
}
interface EditorHeaderToolDropdownOption {
label: string
format: FormattingTool
icon: string
}
const options: EditorHeaderToolDropdownOption[] = [
{ label: 'Header 1', format: 'header1', icon: mdiFormatHeader1 },
{ label: 'Header 2', format: 'header2', icon: mdiFormatHeader2 },
{ label: 'Header 3', format: 'header3', icon: mdiFormatHeader3 },
{ label: 'Header 4', format: 'header4', icon: mdiFormatHeader4 },
{ label: 'Header 5', format: 'header5', icon: mdiFormatHeader5 },
{ label: 'Header 6', format: 'header6', icon: mdiFormatHeader6 },
]
const EditorHeaderToolDropdown = ({
closeDropdowndown,
onFormatCallback,
}: EditorHeaderToolDropdownProps) => {
const menuRef = useRef<HTMLDivElement>(null)
useEffectOnce(() => {
const focusableElement = getFirstFocusableChildOfElement(menuRef.current!)
if (focusableElement == null) {
menuRef.current!.focus()
} else {
focusableElement.focus()
}
})
const onBlurHandler = (event: any) => {
if (
event.relatedTarget == null ||
menuRef.current!.contains(event.relatedTarget)
) {
return
}
closeDropdowndown()
}
const keydownHandler = useMemo(() => {
return (event: KeyboardEvent) => {
if (isSingleKeyEventOutsideOfInput(event, 'escape')) {
preventKeyboardEventPropagation(event)
closeDropdowndown()
}
}
}, [closeDropdowndown])
useGlobalKeyDownHandler(keydownHandler)
useUpDownNavigationListener(menuRef)
return (
<>
<StyledEditorToolDropdownContainer ref={menuRef} onBlur={onBlurHandler}>
{options.map((option) => (
<ContextMenuItem
key={option.label}
label={
<StyledMenuItem>
<StyledIcon>
<Icon path={option.icon} size={20} />
</StyledIcon>
{option.label}
</StyledMenuItem>
}
onClick={() => onFormatCallback(option.format)}
id={`editor-toolbar-${option.format}`}
/>
))}
</StyledEditorToolDropdownContainer>
</>
)
}
export default EditorHeaderToolDropdown
const StyledMenuItem = styled.div`
display: flex;
align-items: center;
justify-content: flex-start;
width: 100%;
white-space: nowrap;
`
const StyledIcon = styled.div`
display: flex;
align-items: center;
flex: 0 0 auto;
padding-right: ${({ theme }) => theme.sizes.spaces.sm}px;
font-size: 21px;
`