Skip to content

Commit f00df01

Browse files
authored
feat: add shortcuts for greek letters and primes (#71)
Closes: #61
1 parent 123ff7f commit f00df01

File tree

1 file changed

+81
-3
lines changed

1 file changed

+81
-3
lines changed

src/components/svg/svg_editor.tsx

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,26 @@ interface AtomLabelEditFormProps {
181181
onCancel: () => void;
182182
}
183183

184+
const greekLetters = {
185+
alpha: 'α',
186+
beta: 'β',
187+
gamma: 'γ',
188+
delta: 'δ',
189+
epsilon: 'ε',
190+
zeta: 'ζ',
191+
eta: 'η',
192+
theta: 'θ',
193+
} as const;
194+
const greekLetterNames = Object.keys(greekLetters);
195+
const greeksFirstLine = greekLetterNames.slice(0, 6);
196+
const greeksLastLine = greekLetterNames.slice(6);
197+
const primes = {
198+
prime1: '′',
199+
prime2: '″',
200+
prime3: '‴',
201+
};
202+
const primeNames = Object.keys(primes);
203+
184204
function AtomLabelEditForm(props: AtomLabelEditFormProps) {
185205
const { defaultValue, formCoords, onSubmit, onCancel } = props;
186206

@@ -236,6 +256,25 @@ function AtomLabelEditForm(props: AtomLabelEditFormProps) {
236256
};
237257
}, []);
238258

259+
function onShortcut(event: MouseEvent<HTMLButtonElement>) {
260+
event.preventDefault();
261+
event.stopPropagation();
262+
263+
if (!formRef.current) return;
264+
const form = formRef.current;
265+
const input = form.querySelector('input[type="text"]') as HTMLInputElement;
266+
if (!input) return;
267+
268+
const value = event.currentTarget.textContent.trim();
269+
input.setRangeText(
270+
value,
271+
input.selectionStart ?? 0,
272+
input.selectionEnd ?? input.value.length,
273+
'end',
274+
);
275+
input.focus();
276+
}
277+
239278
return (
240279
<form
241280
ref={formRef}
@@ -245,7 +284,13 @@ function AtomLabelEditForm(props: AtomLabelEditFormProps) {
245284
position: 'absolute',
246285
top: formCoords.y,
247286
left: formCoords.x,
248-
display: 'flex',
287+
display: 'grid',
288+
gridTemplateAreas: `
289+
"input input input input submit cancel"
290+
"${greeksFirstLine.join(' ')}"
291+
"${greeksLastLine.join(' ')} . ${primeNames.join(' ')}"
292+
`,
293+
gridTemplateColumns: 'repeat(4, 1.5em)',
249294
alignItems: 'stretch',
250295
gap: '0.25em',
251296
border: '1px solid lightgray',
@@ -254,17 +299,50 @@ function AtomLabelEditForm(props: AtomLabelEditFormProps) {
254299
}}
255300
>
256301
<input
302+
style={{ gridArea: 'input' }}
257303
type="text"
258304
name="label"
259305
defaultValue={defaultValue}
260306
size={5}
261307
autoFocus
262308
ref={autoSelectText}
263309
/>
264-
<input type="submit" value="✔️" aria-label="Submit" />
265-
<button type="button" aria-label="Cancel" onClick={onCancelClick}>
310+
<input
311+
style={{ gridArea: 'submit' }}
312+
type="submit"
313+
value="✔️"
314+
aria-label="Submit"
315+
/>
316+
<button
317+
style={{ gridArea: 'cancel' }}
318+
type="button"
319+
aria-label="Cancel"
320+
onClick={onCancelClick}
321+
>
266322
267323
</button>
324+
325+
{Object.entries(greekLetters).map(([charName, greekChar]) => (
326+
<button
327+
key={charName}
328+
type="submit"
329+
style={{ gridArea: charName }}
330+
onClick={onShortcut}
331+
>
332+
{greekChar}
333+
</button>
334+
))}
335+
336+
{Object.entries(primes).map(([primeName, primeChar]) => (
337+
<button
338+
key={primeName}
339+
type="submit"
340+
style={{ gridArea: primeName }}
341+
onClick={onShortcut}
342+
>
343+
{primeChar}
344+
</button>
345+
))}
268346
</form>
269347
);
270348
}

0 commit comments

Comments
 (0)