@@ -18,6 +18,29 @@ const convert = (val: unknown) => (isNumeric(val) ? +val : NaN);
1818const isEquivalent = ( v1 : number , v2 : number ) =>
1919 v1 === v2 || ( isNaN ( v1 ) && isNaN ( v2 ) ) ;
2020
21+ enum PersistenceTypes {
22+ 'local' = 'local' ,
23+ 'session' = 'session' ,
24+ 'memory' = 'memory' ,
25+ }
26+
27+ enum PersistedProps {
28+ 'value' = 'value' ,
29+ }
30+
31+ enum HTMLInputTypes {
32+ // Only allowing the input types with wide browser compatibility
33+ 'text' = 'text' ,
34+ 'number' = 'number' ,
35+ 'password' = 'password' ,
36+ 'email' = 'email' ,
37+ 'range' = 'range' ,
38+ 'search' = 'search' ,
39+ 'tel' = 'tel' ,
40+ 'url' = 'url' ,
41+ 'hidden' = 'hidden' ,
42+ }
43+
2144type InputProps = {
2245 /**
2346 * The value of the input
@@ -222,28 +245,19 @@ type InputProps = {
222245 * component or the page. Since only `value` is allowed this prop can
223246 * normally be ignored.
224247 */
225- persisted_props ?: [ 'value' ] ;
248+ persisted_props ?: PersistedProps [ ] ;
226249 /**
227250 * Where persisted user changes will be stored:
228251 * memory: only kept in memory, reset on page refresh.
229252 * local: window.localStorage, data is kept after the browser quit.
230253 * session: window.sessionStorage, data is cleared once the browser quit.
231254 */
232- persistence_type ?: 'local' | 'session' | 'memory' ;
255+ persistence_type ?: PersistenceTypes ;
233256
234257 /**
235258 * The type of control to render.
236259 */
237- type ?: // Only allowing the input types with wide browser compatibility
238- | 'text'
239- | 'number'
240- | 'password'
241- | 'email'
242- | 'range'
243- | 'search'
244- | 'tel'
245- | 'url'
246- | 'hidden' ;
260+ type ?: HTMLInputTypes ;
247261} ;
248262
249263const inputProps : ( keyof InputProps ) [ ] = [
@@ -268,15 +282,16 @@ const inputProps: (keyof InputProps)[] = [
268282] ;
269283
270284const defaultProps : Partial < InputProps > = {
271- type : 'text' ,
285+ type : HTMLInputTypes . text ,
286+ inputMode : 'verbatim' ,
272287 n_blur : 0 ,
273288 n_blur_timestamp : - 1 ,
274289 n_submit : 0 ,
275290 n_submit_timestamp : - 1 ,
276291 debounce : false ,
277292 step : 'any' ,
278- persisted_props : [ ' value' ] ,
279- persistence_type : ' local' ,
293+ persisted_props : [ PersistedProps . value ] ,
294+ persistence_type : PersistenceTypes . local ,
280295} ;
281296
282297/**
@@ -286,14 +301,39 @@ const defaultProps: Partial<InputProps> = {
286301 * the Checklist and RadioItems component. Dates, times, and file uploads
287302 * are also supported through separate components.
288303 */
289- function Input ( props : InputProps ) {
290- props = { ...defaultProps , ...props } ;
304+ function Input ( {
305+ type = defaultProps . type ,
306+ inputMode = defaultProps . inputMode ,
307+ n_blur = defaultProps . n_blur ,
308+ n_blur_timestamp = defaultProps . n_blur_timestamp ,
309+ n_submit = defaultProps . n_submit ,
310+ n_submit_timestamp = defaultProps . n_submit_timestamp ,
311+ debounce = defaultProps . debounce ,
312+ step = defaultProps . step ,
313+ persisted_props = defaultProps . persisted_props ,
314+ persistence_type = defaultProps . persistence_type ,
315+ ...rest
316+ } : InputProps ) {
317+ const props = {
318+ type,
319+ inputMode,
320+ n_blur,
321+ n_blur_timestamp,
322+ n_submit,
323+ n_submit_timestamp,
324+ debounce,
325+ step,
326+ persisted_props,
327+ persistence_type,
328+ ...rest ,
329+ } ;
291330 const input = useRef ( document . createElement ( 'input' ) ) ;
292331 const [ value , setValue ] = useState < InputProps [ 'value' ] > ( props . value ) ;
293332 const [ pendingEvent , setPendingEvent ] = useState < number > ( ) ;
294333 const inputId = useId ( ) ;
295334
296- const valprops = props . type === 'number' ? { } : { value : value ?? '' } ;
335+ const valprops =
336+ props . type === HTMLInputTypes . number ? { } : { value : value ?? '' } ;
297337 let { className} = props ;
298338 className = 'dash-input' + ( className ? ` ${ className } ` : '' ) ;
299339
@@ -314,7 +354,7 @@ function Input(props: InputProps) {
314354 const { value : inputValue } = input . current ;
315355 const { setProps} = props ;
316356 const valueAsNumber = convert ( inputValue ) ;
317- if ( props . type === ' number' ) {
357+ if ( props . type === HTMLInputTypes . number ) {
318358 setPropValue ( props . value , valueAsNumber ?? value ) ;
319359 } else {
320360 const propValue =
@@ -420,7 +460,7 @@ function Input(props: InputProps) {
420460 }
421461 const valueAsNumber = convert ( value ) ;
422462 setInputValue ( valueAsNumber ?? value , props . value ) ;
423- if ( props . type !== ' number' ) {
463+ if ( props . type !== HTMLInputTypes . number ) {
424464 setValue ( props . value ) ;
425465 }
426466 } , [ props . value , props . type , pendingEvent ] ) ;
@@ -437,7 +477,7 @@ function Input(props: InputProps) {
437477 if ( typeof debounce === 'number' && Number . isFinite ( debounce ) ) {
438478 debounceEvent ( debounce ) ;
439479 }
440- if ( type !== ' number' ) {
480+ if ( type !== HTMLInputTypes . number ) {
441481 setTimeout ( ( ) => {
442482 input . current . setSelectionRange (
443483 cursorPosition ,
@@ -452,7 +492,7 @@ function Input(props: InputProps) {
452492
453493 const pickedInputs = pick ( inputProps , props ) ;
454494
455- const isNumberInput = props . type === ' number' ;
495+ const isNumberInput = props . type === HTMLInputTypes . number ;
456496 const currentNumericValue = convert ( input . current . value || '0' ) ;
457497 const minValue = convert ( props . min ) ;
458498 const maxValue = convert ( props . max ) ;
@@ -467,7 +507,9 @@ function Input(props: InputProps) {
467507 { loadingProps => (
468508 < div
469509 className = { `dash-input-container ${ className } ${
470- props . type === 'hidden' ? ' dash-input-hidden' : ''
510+ props . type === HTMLInputTypes . hidden
511+ ? ' dash-input-hidden'
512+ : ''
471513 } `. trim ( ) }
472514 style = { props . style }
473515 >
0 commit comments