addons/components/HorizontallyGrowingTextField.tsxblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import type {ForwardedRef} from 'react';
b69ab319import type {ReactProps} from './utils';
b69ab3110
b69ab3111import * as stylex from '@stylexjs/stylex';
b69ab3112import {forwardRef} from 'react';
b69ab3113import {textFieldStyles} from './TextField';
b69ab3114
b69ab3115const styles = stylex.create({
b69ab3116 horizontalGrowContainer: {
b69ab3117 display: 'inline-grid',
b69ab3118 maxWidth: '600px',
b69ab3119 alignItems: 'center',
b69ab3120 '::after': {
b69ab3121 width: 'auto',
b69ab3122 minWidth: '1em',
b69ab3123 content: 'attr(data-value)',
b69ab3124 visibility: 'hidden',
b69ab3125 whiteSpace: 'pre-wrap',
b69ab3126 gridArea: '1 / 2',
b69ab3127 height: '26px',
b69ab3128 padding: '0 9px',
b69ab3129 },
b69ab3130 },
b69ab3131
b69ab3132 horizontalGrow: {
b69ab3133 width: 'auto',
b69ab3134 minWidth: '1em',
b69ab3135 gridArea: '1 / 2',
b69ab3136 },
b69ab3137});
b69ab3138
b69ab3139/**
b69ab3140 * Like a normal text field / {@link TextField}, but grows horizontally to fit the text.
b69ab3141 */
b69ab3142export const HorizontallyGrowingTextField = forwardRef(
b69ab3143 (
b69ab3144 props: ReactProps<HTMLInputElement> & {
b69ab3145 value?: string;
b69ab3146 placeholder?: string;
b69ab3147 },
b69ab3148 ref: ForwardedRef<HTMLInputElement>,
b69ab3149 ) => {
b69ab3150 const {onInput, ...otherProps} = props;
b69ab3151
b69ab3152 return (
b69ab3153 <div {...stylex.props(styles.horizontalGrowContainer)} data-value={otherProps.value}>
b69ab3154 <input
b69ab3155 {...stylex.props(textFieldStyles.input, styles.horizontalGrow)}
b69ab3156 type="text"
b69ab3157 ref={ref}
b69ab3158 onInput={e => {
b69ab3159 if ((e.currentTarget.parentNode as HTMLDivElement)?.dataset) {
b69ab3160 // Use `dataset` + `content: attr(data-value)` to size an ::after element,
b69ab3161 // which auto-expands the containing div to fit the text.
b69ab3162 (e.currentTarget.parentNode as HTMLDivElement).dataset.value = e.currentTarget.value;
b69ab3163 }
b69ab3164 onInput?.(e);
b69ab3165 }}
b69ab3166 {...otherProps}
b69ab3167 />
b69ab3168 </div>
b69ab3169 );
b69ab3170 },
b69ab3171);