@@ -1,4 +1,4 @@
1−import React from 'react';
1+import React, { useCallback } from 'react';
2import * as ob from 'urbit-ob';
2import * as ob from 'urbit-ob';
3import { Input, AccessoryIcon } from 'indigo-react';
3import { Input, AccessoryIcon } from 'indigo-react';
4import { useField, useForm } from 'react-final-form';
4import { useField, useForm } from 'react-final-form';
@@ -224,30 +224,59 @@ export function TicketSegmentInput({ name, ...rest }: TicketSegmentInputProps) {
224 const { input } = useField(name);
224 const { input } = useField(name);
225 const { change } = useForm();
225 const { change } = useForm();
227+ const onPaste = useCallback(
227− const onPaste = (event: React.ClipboardEvent<HTMLInputElement>) => {
228+ (event: React.ClipboardEvent<HTMLInputElement>) => {
229− const pasteBuffer = event.clipboardData.getData('text');
230+ const pasteBuffer = event.clipboardData.getData('text');
230− const patp = ensurePatFormat(pasteBuffer);
231+ const patp = ensurePatFormat(pasteBuffer);
231− if (!ob.isValidPatp(patp)) {
232+ if (!ob.isValidPatp(patp)) {
232− throw new Error('invalid patp');
233+ throw new Error('invalid patp');
236+ // prevent pasting the entire clipboard text into the field
237+ event.preventDefault();
239+ const segments = ticketToSegments(pasteBuffer);
240+ segments.forEach((s, i) => {
241+ change(`ticket${i}`, s);
244+ console.log(`skipping ticket autofill: ${error}`);
235− // prevent pasting the entire clipboard text into the field
250+ // Advance the focused field after typing 6 characters
236− event.preventDefault();
251+ const onChange = useCallback(
252+ (event: React.ChangeEvent<HTMLInputElement>) => {
253+ const currentIndex = Number(name.replace('ticket', ''));
254+ if (currentIndex < 3 && event.target.value.length === 6) {
255+ const nextField = document.querySelector(
256+ `input[name=ticket${currentIndex + 1}]`
238− const segments = ticketToSegments(pasteBuffer);
259+ if (nextField !== null) {
239− change('ticket0', segments[0]);
260+ nextField.focus();
240− change('ticket1', segments[1]);
261+ }
241− change('ticket2', segments[2]);
262+ }
242− change('ticket3', segments[3]);
263+ },
243− } catch (error) {
264+ [name]
244− console.log(`skipping ticket autofill: ${error}`);
265+ );
267+ // Run the react-final-form onChange handler,
268+ // and our own custom one to advance the form cursor
269+ const mergedInput = {
249 <StatelessTextInput
278 <StatelessTextInput
250− {...input}
279+ {...mergedInput}
251 autoCapitalize="none"
280 autoCapitalize="none"
252 autoCorrect="off"
281 autoCorrect="off"
253 type="text"
282 type="text"