PluginProbe
Code Snippets / 3.8.1
Code Snippets v3.8.1
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 3.0.1 All 64 releases
code-snippets / js / components / SnippetForm / fields / CodeEditor.tsx

CodeEditor.tsx in Code Snippets 3.8.1, at js/components/SnippetForm/fields/CodeEditor.tsx

95 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, useRef } from 'react'
2 import { __ } from '@wordpress/i18n'
3 import { useSubmitSnippet } from '../../../hooks/useSubmitSnippet'
4 import { handleUnknownError } from '../../../utils/errors'
5 import { isMacOS } from '../../../utils/screen'
6 import { useSnippetForm } from '../../../hooks/useSnippetForm'
7 import { Button } from '../../common/Button'
8 import { ExpandIcon } from '../../common/icons/ExpandIcon'
9 import { MinimiseIcon } from '../../common/icons/MinimiseIcon'
10 import { CodeEditorShortcuts } from './CodeEditorShortcuts'
11 import type { Dispatch, RefObject, SetStateAction } from 'react'
12
13 interface EditorTextareaProps {
14 textareaRef: RefObject<HTMLTextAreaElement>
15 }
16
17 const EditorTextarea: React.FC<EditorTextareaProps> = ({ textareaRef }) => {
18 const { snippet, setSnippet } = useSnippetForm()
19
20 return (
21 <div className="snippet-editor">
22 <textarea
23 ref={textareaRef}
24 id="snippet-code"
25 name="snippet_code"
26 value={snippet.code}
27 rows={200}
28 spellCheck={false}
29 onChange={event => {
30 setSnippet(previous => ({ ...previous, code: event.target.value }))
31 }}
32 />
33 <CodeEditorShortcuts editorTheme={window.CODE_SNIPPETS_EDIT?.editorTheme ?? 'default'} />
34 </div>
35 )
36 }
37
38 export interface CodeEditorProps {
39 isExpanded: boolean
40 setIsExpanded: Dispatch<SetStateAction<boolean>>
41 }
42
43 export const CodeEditor: React.FC<CodeEditorProps> = ({ isExpanded, setIsExpanded }) => {
44 const { snippet, setSnippet, codeEditorInstance, setCodeEditorInstance } = useSnippetForm()
45 const { submitSnippet } = useSubmitSnippet()
46 const textareaRef = useRef<HTMLTextAreaElement>(null)
47
48 useEffect(() => {
49 setCodeEditorInstance(editorInstance => {
50 if (textareaRef.current && !editorInstance) {
51 editorInstance = window.wp.codeEditor.initialize(textareaRef.current)
52
53 editorInstance.codemirror.on('changes', instance => {
54 setSnippet(previous => ({ ...previous, code: instance.getValue() }))
55 })
56 }
57
58 return editorInstance
59 })
60 }, [setCodeEditorInstance, textareaRef, setSnippet])
61
62 useEffect(() => {
63 if (codeEditorInstance) {
64 const extraKeys = codeEditorInstance.codemirror.getOption('extraKeys') ?? {}
65 const controlKey = isMacOS() ? 'Cmd' : 'Ctrl'
66 const onSave = () => {
67 submitSnippet()
68 .then(() => undefined)
69 .catch(handleUnknownError)
70 }
71
72 codeEditorInstance.codemirror.setOption('extraKeys', {
73 ...'object' === typeof extraKeys ? extraKeys : undefined,
74 [`${controlKey}-S`]: onSave,
75 [`${controlKey}-Enter`]: onSave
76 })
77 }
78 }, [submitSnippet, codeEditorInstance, snippet])
79
80 return (
81 <div className="snippet-code-container">
82 <div className="above-snippet-code">
83 <h2><label htmlFor="snippet-code">{__('Snippet Content', 'code-snippets')}</label></h2>
84
85 <Button small className="expand-editor-button" onClick={() => setIsExpanded(current => !current)}>
86 {isExpanded ? <MinimiseIcon /> : <ExpandIcon />}
87 {isExpanded ? __('Minimize', 'code-snippets') : __('Expand', 'code-snippets')}
88 </Button>
89 </div>
90
91 <EditorTextarea textareaRef={textareaRef} />
92 </div>
93 )
94 }
95