diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.css b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.css index c708adcffdbc33..040d2e4d28933a 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.css +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.css @@ -28,3 +28,19 @@ justify-content: center; color: var(--color-dim); } + +.Input { + background: none; + font-size: var(--font-size-sans-normal); + text-align: right; + font-family: var(--font-family-monospace); + border: 1px solid transparent; + border-radius: 0.125rem; + padding: 0.125rem; + color: var(--color-attribute-editable-value); +} + +.Input:focus { + background-color: var(--color-button-background-focus); + outline: none; +} diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js index b79569df1e48f4..42510f08761a73 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js @@ -8,7 +8,7 @@ */ import * as React from 'react'; -import {Fragment, useCallback, useContext, useMemo} from 'react'; +import {Fragment, useContext, useMemo} from 'react'; import Button from '../Button'; import ButtonIcon from '../ButtonIcon'; import {ProfilerContext} from './ProfilerContext'; @@ -86,47 +86,89 @@ export default function SnapshotSelector(_: Props) { let label = null; if (numFilteredCommits > 0) { - label = - `${selectedFilteredCommitIndex + 1}`.padStart( - `${numFilteredCommits}`.length, - '0', - ) + - ' / ' + - numFilteredCommits; + const handleCommitInputChange = event => { + const value = parseInt(event.currentTarget.value, 10); + if (!isNaN(value)) { + const filteredIndex = Math.min( + Math.max(value - 1, 0), + + // Snashots are shown to the user as 1-based + // but the indices within the profiler data array ar 0-based. + numFilteredCommits - 1, + ); + selectCommitIndex(filteredCommitIndices[filteredIndex]); + } + }; + + const handleClick = event => { + event.currentTarget.select(); + }; + + const handleKeyDown = event => { + switch (event.key) { + case 'ArrowDown': + viewPrevCommit(); + event.stopPropagation(); + break; + case 'ArrowUp': + viewNextCommit(); + event.stopPropagation(); + break; + default: + break; + } + }; + + const input = ( + + ); + + label = ( + + {input} / {numFilteredCommits} + + ); } - const viewNextCommit = useCallback(() => { + const viewNextCommit = () => { let nextCommitIndex = ((selectedFilteredCommitIndex: any): number) + 1; if (nextCommitIndex === filteredCommitIndices.length) { nextCommitIndex = 0; } selectCommitIndex(filteredCommitIndices[nextCommitIndex]); - }, [selectedFilteredCommitIndex, filteredCommitIndices, selectCommitIndex]); - const viewPrevCommit = useCallback(() => { + }; + const viewPrevCommit = () => { let nextCommitIndex = ((selectedFilteredCommitIndex: any): number) - 1; if (nextCommitIndex < 0) { nextCommitIndex = filteredCommitIndices.length - 1; } selectCommitIndex(filteredCommitIndices[nextCommitIndex]); - }, [selectedFilteredCommitIndex, filteredCommitIndices, selectCommitIndex]); + }; - const handleKeyDown = useCallback( - event => { - switch (event.key) { - case 'ArrowLeft': - viewPrevCommit(); - event.stopPropagation(); - break; - case 'ArrowRight': - viewNextCommit(); - event.stopPropagation(); - break; - default: - break; - } - }, - [viewNextCommit, viewPrevCommit], - ); + const handleKeyDown = event => { + switch (event.key) { + case 'ArrowLeft': + viewPrevCommit(); + event.stopPropagation(); + break; + case 'ArrowRight': + viewNextCommit(); + event.stopPropagation(); + break; + default: + break; + } + }; if (commitData.length === 0) { return null;