Skip to content

Commit

Permalink
Using codemirror for copy template text-area highlighting (#28)
Browse files Browse the repository at this point in the history
* codemirror basic setup

* feat: wire-up save

* chore: lint fix
  • Loading branch information
MrRobz authored Oct 23, 2021
1 parent edf3cd7 commit 61c459a
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 9 deletions.
11 changes: 11 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,17 @@
"yarn-deduplicate": "^3.1.0"
},
"dependencies": {
"@codemirror/autocomplete": "^0.19.3",
"@codemirror/closebrackets": "^0.19.0",
"@codemirror/commands": "^0.19.5",
"@codemirror/comment": "^0.19.0",
"@codemirror/history": "^0.19.0",
"@codemirror/lang-javascript": "^0.19.2",
"@codemirror/language": "^0.19.3",
"@codemirror/matchbrackets": "^0.19.3",
"@codemirror/state": "^0.19.2",
"@codemirror/theme-one-dark": "^0.19.0",
"@codemirror/view": "^0.19.9",
"@dnd-kit/core": "^4.0.0",
"@dnd-kit/sortable": "^5.0.0",
"@fontsource/dm-sans": "^4.5.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useEffect, useRef } from 'react';
import { EditorState } from '@codemirror/state';
import { javascript } from '@codemirror/lang-javascript';
import { oneDark } from '@codemirror/theme-one-dark';
import type { Extension } from '@codemirror/state';
import type { ViewUpdate } from '@codemirror/view';
import { keymap, drawSelection, EditorView } from '@codemirror/view';
import { history, historyKeymap } from '@codemirror/history';
import { indentOnInput } from '@codemirror/language';
import { bracketMatching } from '@codemirror/matchbrackets';
import { closeBrackets, closeBracketsKeymap } from '@codemirror/closebrackets';
import { autocompletion, completionKeymap } from '@codemirror/autocomplete';
import { defaultKeymap } from '@codemirror/commands';
import { commentKeymap } from '@codemirror/comment';
import './styles.css';

interface EditorProps {
value?: string;
onUpdate?: (update: ViewUpdate) => void;
}

export const TemplateEditor = ({
value = '',
onUpdate = undefined,
}: EditorProps) => {
const editor = useRef(null);

useEffect(() => {
const currentEditor = editor.current as Exclude<
typeof editor['current'],
null
>;
const extensions: Extension[] = [
history(),
drawSelection(),
indentOnInput(),
bracketMatching(),
closeBrackets(),
autocompletion(),
oneDark,
javascript(),
keymap.of([
...closeBracketsKeymap,
...defaultKeymap,
...historyKeymap,
...commentKeymap,
...completionKeymap,
]),
];
if (onUpdate) extensions.push(EditorView.updateListener.of(onUpdate));

const state = EditorState.create({
doc: value,
extensions,
});
const view = new EditorView({
state,
parent: currentEditor,
});

return () => view.destroy();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [editor]);

return <div ref={editor} />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.cm-editor {
@apply h-20 p-1 text-xl;
}

.cm-editor.cm-focused {
outline: none;
}
.cm-editor > .cm-scroller:focus {
outline: none;
}

.cm-scroller::-webkit-scrollbar {
height: 10px;
}

.cm-scroller::-webkit-scrollbar-track {
@apply bg-black3 rounded-full;
}

.cm-scroller::-webkit-scrollbar-thumb {
@apply rounded-full;
background-image: linear-gradient(180deg, #696eff 0%, #f7abff 100%);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TextArea } from 'components/ui/atomic-components';
import { ChangeEvent, FC } from 'react';
import { ViewUpdate } from '@codemirror/view';
import { FC } from 'react';
import { TemplateEditor } from './TemplateEditor';

interface Props {
defaultValue: string;
Expand All @@ -10,18 +11,19 @@ export const TemplateStringCreator: FC<Props> = ({
defaultValue,
onChange,
}) => {
const onTextChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
const { value } = e.target;

onChange(value);
const onTextChange = (v: ViewUpdate) => {
if (v.docChanged) {
const value = v.state.doc.toString();
onChange(value);
}
};

return (
<div className="mt-8">
<label className="flex font-medium text-gray-400 ml-1 mb-1">
Copy string template
</label>
<TextArea defaultValue={defaultValue} onChange={onTextChange} />
<TemplateEditor value={defaultValue} onUpdate={onTextChange} />
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const CustomizeActionsModal: FC<Props> = ({
footer={
!showEditScreen ? (
<Button type="primary" onClick={onSubmit}>
Done
Done and save
</Button>
) : (
<></>
Expand Down
2 changes: 1 addition & 1 deletion src/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export default class MenuBuilder {
{ label: 'Redo', accelerator: 'Shift+Command+Z', selector: 'redo:' },
{ type: 'separator' },
{ label: 'Cut', accelerator: 'Command+X', selector: 'cut:' },
// { label: 'Copy', accelerator: 'Command+C', selector: 'copy:' },
{ label: 'Copy', accelerator: 'Command+C', selector: 'copy:' },
{ label: 'Paste', accelerator: 'Command+V', selector: 'paste:' },
{
label: 'Select All',
Expand Down
198 changes: 198 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1137,6 +1137,170 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==

"@codemirror/autocomplete@^0.19.0", "@codemirror/autocomplete@^0.19.3":
version "0.19.3"
resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-0.19.3.tgz#0266ac29617277d2d8cc7dcfb600c1e50c332d35"
integrity sha512-5juP6hVrHAogzQ0JUTQuibE8j1seqeGNJ98qLUPuliI6kLBg5INS4qvUI1Brqye+wYPFu7UHqrrn13RLh5YSzw==
dependencies:
"@codemirror/language" "^0.19.0"
"@codemirror/state" "^0.19.0"
"@codemirror/text" "^0.19.2"
"@codemirror/tooltip" "^0.19.0"
"@codemirror/view" "^0.19.0"
"@lezer/common" "^0.15.0"

"@codemirror/closebrackets@^0.19.0":
version "0.19.0"
resolved "https://registry.yarnpkg.com/@codemirror/closebrackets/-/closebrackets-0.19.0.tgz#69fdcee85779d638a00a42becd9f53a33a26d77f"
integrity sha512-dFWX5OEVYWRNtGaifSbwIAlymnRRjxWMiMbffbAjF7p0zfGHDbdGkiT56q3Xud63h5/tQdSo5dK1iyNTzHz5vg==
dependencies:
"@codemirror/language" "^0.19.0"
"@codemirror/rangeset" "^0.19.0"
"@codemirror/state" "^0.19.0"
"@codemirror/text" "^0.19.0"
"@codemirror/view" "^0.19.0"

"@codemirror/commands@^0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-0.19.5.tgz#2607b5c12c5c96df2cabce2e43f6285c07cfaf11"
integrity sha512-8PZOtx7d/GbKhFYA88zs2wINDtaUgj3pEjLYScKTd/Vsyw8qOp86tJQQNnMFTRZj/ISQl9Lbg3aAmHvroMqspw==
dependencies:
"@codemirror/language" "^0.19.0"
"@codemirror/matchbrackets" "^0.19.0"
"@codemirror/state" "^0.19.2"
"@codemirror/text" "^0.19.0"
"@codemirror/view" "^0.19.0"
"@lezer/common" "^0.15.0"

"@codemirror/comment@^0.19.0":
version "0.19.0"
resolved "https://registry.yarnpkg.com/@codemirror/comment/-/comment-0.19.0.tgz#4f23497924e9346898c2e0123011acc535a0bea6"
integrity sha512-3hqAd0548fxqOBm4khFMcXVIivX8p0bSlbAuZJ6PNoUn/0wXhxkxowPp0FmFzU2+y37Z+ZQF5cRB5EREWPRIiQ==
dependencies:
"@codemirror/state" "^0.19.0"
"@codemirror/text" "^0.19.0"
"@codemirror/view" "^0.19.0"

"@codemirror/highlight@^0.19.0", "@codemirror/highlight@^0.19.6":
version "0.19.6"
resolved "https://registry.yarnpkg.com/@codemirror/highlight/-/highlight-0.19.6.tgz#7f2e066f83f5649e8e0748a3abe0aaeaf64b8ac2"
integrity sha512-+eibu6on9quY8uN3xJ/n3rH+YIDLlpX7YulVmFvqAIz/ukRQ5tWaBmB7fMixHmnmRIRBRZgB8rNtonuMwZSAHQ==
dependencies:
"@codemirror/language" "^0.19.0"
"@codemirror/rangeset" "^0.19.0"
"@codemirror/state" "^0.19.0"
"@codemirror/view" "^0.19.0"
"@lezer/common" "^0.15.0"
style-mod "^4.0.0"

"@codemirror/history@^0.19.0":
version "0.19.0"
resolved "https://registry.yarnpkg.com/@codemirror/history/-/history-0.19.0.tgz#cc8095c927c9566f7b69fa404074edde4c54d39c"
integrity sha512-E0H+lncH66IMDhaND9jgkjE7s0dhYfjCPmS+Ig2Yes9I8+UIEecIdObj8c8HPCFGctGg3fxXqRAw2mdHl2Wouw==
dependencies:
"@codemirror/state" "^0.19.0"
"@codemirror/view" "^0.19.0"

"@codemirror/lang-javascript@^0.19.2":
version "0.19.2"
resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-0.19.2.tgz#afefd3154979b825605bed894850a4cea957a4e0"
integrity sha512-qNFjCSTWOTZ/KusoVx3CxjmNS37DrhVoVO9E1IkrIMVC3tkk8Hs2eA6HNMxT4VGp5O+0yBmf1DE2o5QQSMs0jg==
dependencies:
"@codemirror/autocomplete" "^0.19.0"
"@codemirror/highlight" "^0.19.6"
"@codemirror/language" "^0.19.0"
"@codemirror/lint" "^0.19.0"
"@codemirror/state" "^0.19.0"
"@codemirror/view" "^0.19.0"
"@lezer/javascript" "^0.15.0"

"@codemirror/language@^0.19.0", "@codemirror/language@^0.19.3":
version "0.19.3"
resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-0.19.3.tgz#e4f61555dec0787f757b78348a54a00f3bb23c9c"
integrity sha512-6vjkRYHRJg/z9wdAk75nU2fQwCJBsh2HpkIjKXIHfzISSgLt5qSDxVhPd8Uu8PD5WMmFFP8tX7I9kdIt873o0A==
dependencies:
"@codemirror/state" "^0.19.0"
"@codemirror/text" "^0.19.0"
"@codemirror/view" "^0.19.0"
"@lezer/common" "^0.15.5"
"@lezer/lr" "^0.15.0"

"@codemirror/lint@^0.19.0":
version "0.19.2"
resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-0.19.2.tgz#1c3932cffd635da796bea3384256b0a315b6fe1e"
integrity sha512-477qvXWwuf24YsBi1DzjrGyzM+qfPe5L4xEHGxQTGOMq6R0+QAFKppOJsxN3y7gzDpLrZSYZdhJzWevOuliZQg==
dependencies:
"@codemirror/panel" "^0.19.0"
"@codemirror/state" "^0.19.0"
"@codemirror/tooltip" "^0.19.0"
"@codemirror/view" "^0.19.0"
crelt "^1.0.5"

"@codemirror/matchbrackets@^0.19.0", "@codemirror/matchbrackets@^0.19.3":
version "0.19.3"
resolved "https://registry.yarnpkg.com/@codemirror/matchbrackets/-/matchbrackets-0.19.3.tgz#1f430ada6fa21af2205280ff344ef57bb95dd3cb"
integrity sha512-ljkrBxaLgh8jesroUiBa57pdEwqJamxkukXrJpL9LdyFZVJaF+9TldhztRaMsMZO1XnCSSHQ9sg32iuHo7Sc2g==
dependencies:
"@codemirror/language" "^0.19.0"
"@codemirror/state" "^0.19.0"
"@codemirror/view" "^0.19.0"
"@lezer/common" "^0.15.0"

"@codemirror/panel@^0.19.0":
version "0.19.0"
resolved "https://registry.yarnpkg.com/@codemirror/panel/-/panel-0.19.0.tgz#18c7a253a7a1ef686bece1ef13ec0e5eb6603265"
integrity sha512-LJuu49xnuhaAztlhnLJQ57ddOirSyf8/lnl7twsQUG/05RkxodBZ9F7q8r5AOLqOkaQOy9WySEKX1Ur8lD9Q5w==
dependencies:
"@codemirror/state" "^0.19.0"
"@codemirror/view" "^0.19.0"

"@codemirror/rangeset@^0.19.0":
version "0.19.1"
resolved "https://registry.yarnpkg.com/@codemirror/rangeset/-/rangeset-0.19.1.tgz#03ab6f93fb60d9ba98f810b98ed9471cba1e3854"
integrity sha512-WaKTEw8JB/3QFlQzpdgRoklopcWvG8O/Xp+rxxOfFKYTaeaejpY/tjpyBBg+Ea65Ka3m7+pPp9d5j/oR2rd9NA==
dependencies:
"@codemirror/state" "^0.19.0"

"@codemirror/state@^0.19.0", "@codemirror/state@^0.19.2":
version "0.19.2"
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-0.19.2.tgz#81de81f89e87b9362b8bc6d51135637dddd4d33d"
integrity sha512-dDqCrtkb0c/LYUlvQBLyLfkISEskbZnhvBbcVOF4j2AusJ1ptJ3EGMxBL9G16GP1TOdC1T613gA1J1qc3pbfGQ==
dependencies:
"@codemirror/text" "^0.19.0"

"@codemirror/text@^0.19.0", "@codemirror/text@^0.19.2":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@codemirror/text/-/text-0.19.4.tgz#522cbe93becdf7637ca7148b67f628b3d8b8fdf5"
integrity sha512-Msd1ImS+Mmref28+oyoOrBwqjH4lbCVO/5ol2jRaCEYH7+KaMocxFADZomPLnMPgDW6Gc4mu/K2lj8IjAOFdTA==

"@codemirror/theme-one-dark@^0.19.0":
version "0.19.0"
resolved "https://registry.yarnpkg.com/@codemirror/theme-one-dark/-/theme-one-dark-0.19.0.tgz#e039d7ee5de7ea6251f6cd53d1c12281a9b8e210"
integrity sha512-Xlk68ARreanFveE+KvZJY4HxecNr+VKDOR61O8l3kzlQ0qvxNXA0KAp1xu4p32pA9jzJqJi5haIgdfWSZogXZg==
dependencies:
"@codemirror/highlight" "^0.19.0"
"@codemirror/state" "^0.19.0"
"@codemirror/view" "^0.19.0"

"@codemirror/tooltip@^0.19.0":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@codemirror/tooltip/-/tooltip-0.19.4.tgz#eed2214a08d4a50ee6b9c7f40d40700de8fade52"
integrity sha512-DTv6SOzjw8LbHdTd2FszpIkQCUKRl0dqh1pWqawR31Lu/ZCz1nOiOY1sxkiEZVXMTFg44V0Uff0YlY6mTVK2DQ==
dependencies:
"@codemirror/state" "^0.19.0"
"@codemirror/view" "^0.19.0"

"@codemirror/view@^0.19.0", "@codemirror/view@^0.19.9":
version "0.19.9"
resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-0.19.9.tgz#cbdcbc398818e7c9603c81e4b2a2868ec0a1f954"
integrity sha512-d2Z2rFl53yTwvhsRYtS97xT7ce1f/Q/NNE2uDg/Be1MVjP2v1OlwUTyTosBmxiCt4oUvMklfa+EdPGOATVJhtg==
dependencies:
"@codemirror/rangeset" "^0.19.0"
"@codemirror/state" "^0.19.2"
"@codemirror/text" "^0.19.0"
style-mod "^4.0.0"
w3c-keyname "^2.2.4"

"@develar/schema-utils@~2.6.5":
version "2.6.5"
resolved "https://registry.yarnpkg.com/@develar/schema-utils/-/schema-utils-2.6.5.tgz#3ece22c5838402419a6e0425f85742b961d9b6c6"
Expand Down Expand Up @@ -1439,6 +1603,25 @@
"@types/yargs" "^16.0.0"
chalk "^4.0.0"

"@lezer/common@^0.15.0", "@lezer/common@^0.15.5":
version "0.15.7"
resolved "https://registry.yarnpkg.com/@lezer/common/-/common-0.15.7.tgz#8b445dae9777f689783132cf490770ece3c03d7b"
integrity sha512-Rw8TDJnBzZnkyzIXs1Tmmd241FrBLJBj8gkdy3y0joGFb8Z4I/joKEsR+gv1pb13o1TMsZxm3fmP+d/wPt2CTQ==

"@lezer/javascript@^0.15.0":
version "0.15.0"
resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-0.15.0.tgz#0033be1ff814c0d448e992cc3e0285b8b296135e"
integrity sha512-euFjbbyYmxpBls9FyBAKnGLEjaMFqfHvhfueA7M1PitZdieHu8KSblutmcwjpWKIV4eH4uElMZO2cPVe0aFxXA==
dependencies:
"@lezer/lr" "^0.15.0"

"@lezer/lr@^0.15.0":
version "0.15.4"
resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-0.15.4.tgz#634670d7224040fddac1370af01211eecd9ac0a0"
integrity sha512-vwgG80sihEGJn6wJp6VijXrnzVai/KPva/OzYKaWvIx0IiXKjoMQ8UAwcgpSBwfS4Fbz3IKOX/cCNXU3r1FvpQ==
dependencies:
"@lezer/common" "^0.15.0"

"@malept/cross-spawn-promise@^1.1.0", "@malept/cross-spawn-promise@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d"
Expand Down Expand Up @@ -3659,6 +3842,11 @@ crc@^3.8.0:
dependencies:
buffer "^5.1.0"

crelt@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.5.tgz#57c0d52af8c859e354bace1883eb2e1eb182bb94"
integrity sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==

cross-env@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
Expand Down Expand Up @@ -10555,6 +10743,11 @@ style-loader@^2.0.0:
loader-utils "^2.0.0"
schema-utils "^3.0.0"

style-mod@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.0.0.tgz#97e7c2d68b592975f2ca7a63d0dd6fcacfe35a01"
integrity sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==

stylehacks@^4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5"
Expand Down Expand Up @@ -11301,6 +11494,11 @@ w3c-hr-time@^1.0.2:
dependencies:
browser-process-hrtime "^1.0.0"

w3c-keyname@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.4.tgz#4ade6916f6290224cdbd1db8ac49eab03d0eef6b"
integrity sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==

w3c-xmlserializer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a"
Expand Down

0 comments on commit 61c459a

Please sign in to comment.