@@ -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+
184204function 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