PluginProbe
Code Snippets / 4.0.0-beta.1
Code Snippets v4.0.0-beta.1
4.0.0-beta.2 3.10.2 3.10.1 3.10.0 3.10.0-beta.2 3.10.0-beta.1 4.0.0-beta.1 3.9.6 trunk 2.10.0 2.10.1 2.12.0 2.12.1 2.13.0 2.13.1 2.13.2 2.13.3 2.14.0 2.14.1 2.14.2 2.14.3 2.14.4 2.14.5 2.14.6 3.0.0 All 65 releases
code-snippets / js / components / EditMenu / EditMenu.tsx

EditMenu.tsx in Code Snippets 4.0.0-beta.1, at js/components/EditMenu/EditMenu.tsx

119 lines 3.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import React, { useEffect } from 'react'
2 import { SnippetForm } from './SnippetForm'
3
4 const EVENT_NAME = 'code_snippets_focus_editor'
5
6 interface EditMenuLinkBinding {
7 menuLink: HTMLAnchorElement
8 originalHref: string | undefined
9 originalRole: string | undefined
10 originalTabIndex: string | undefined
11 handleClick: (event: MouseEvent) => void
12 handleKeyDown: (event: KeyboardEvent) => void
13 }
14
15 const focusCodeEditor = () => {
16 window.dispatchEvent(new CustomEvent(EVENT_NAME))
17 }
18
19 const restoreAttribute = (menuLink: HTMLAnchorElement, name: string, value: string | undefined) => {
20 if (undefined !== value) {
21 menuLink.setAttribute(name, value)
22 return
23 }
24
25 menuLink.removeAttribute(name)
26 }
27
28 const getEditPage = (): string | undefined => {
29 const editUrl = window.CODE_SNIPPETS?.urls.edit
30
31 return editUrl ? new URL(editUrl, window.location.origin).searchParams.get('page') ?? undefined : undefined
32 }
33
34 const bindEditMenuLink = (menuLink: HTMLAnchorElement, page: string): EditMenuLinkBinding | undefined => {
35 const menuUrl = new URL(menuLink.href, window.location.origin)
36
37 if (page !== menuUrl.searchParams.get('page')) {
38 return undefined
39 }
40
41 const handleClick = (event: MouseEvent) => {
42 event.preventDefault()
43 focusCodeEditor()
44 }
45
46 const handleKeyDown = (event: KeyboardEvent) => {
47 if ('Enter' !== event.key && ' ' !== event.key) {
48 return
49 }
50
51 event.preventDefault()
52 focusCodeEditor()
53 }
54
55 const binding = {
56 menuLink,
57 originalHref: menuLink.getAttribute('href') ?? undefined,
58 originalRole: menuLink.getAttribute('role') ?? undefined,
59 originalTabIndex: menuLink.getAttribute('tabindex') ?? undefined,
60 handleClick,
61 handleKeyDown
62 }
63
64 menuLink.dataset.codeSnippetsDisabled = 'true'
65 menuLink.setAttribute('role', 'button')
66 menuLink.setAttribute('tabindex', '0')
67 menuLink.classList.add('code-snippets-edit-menu-link')
68 menuLink.removeAttribute('href')
69 menuLink.addEventListener('click', handleClick)
70 menuLink.addEventListener('keydown', handleKeyDown)
71
72 return binding
73 }
74
75 const unbindEditMenuLink = ({
76 menuLink,
77 originalHref,
78 originalRole,
79 originalTabIndex,
80 handleClick,
81 handleKeyDown
82 }: EditMenuLinkBinding) => {
83 menuLink.removeEventListener('click', handleClick)
84 menuLink.removeEventListener('keydown', handleKeyDown)
85 menuLink.classList.remove('code-snippets-edit-menu-link')
86 delete menuLink.dataset.codeSnippetsDisabled
87
88 restoreAttribute(menuLink, 'href', originalHref)
89 restoreAttribute(menuLink, 'role', originalRole)
90 restoreAttribute(menuLink, 'tabindex', originalTabIndex)
91 }
92
93 const useEditMenuLinkFocus = () => {
94 useEffect(() => {
95 const page = getEditPage()
96
97 if (!page) {
98 return
99 }
100
101 const editMenuLinks = Array.from(document.querySelectorAll<HTMLAnchorElement>('#adminmenu a[href]'))
102 .flatMap(menuLink => {
103 const binding = bindEditMenuLink(menuLink, page)
104
105 return binding ? [binding] : []
106 })
107
108 return () => {
109 editMenuLinks.forEach(unbindEditMenuLink)
110 }
111 }, [])
112 }
113
114 export const EditMenu = () => {
115 useEditMenuLinkFocus()
116
117 return <SnippetForm />
118 }
119