11import * as React from 'react'
22
33import { cn } from '../../lib/utils'
4+ import { useEffect , useRef , useState } from 'react'
45
5- function Input ( { className, type, ...props } : React . ComponentProps < 'input' > ) {
6- return (
6+ interface OwnProps {
7+ // Something that needs to appear before the start, outside the field
8+ beforeStartDecoration ?: React . ReactNode
9+
10+ // Something that needs to appear at the start, inside the field
11+ startDecoration ?: React . ReactNode
12+
13+ // Something that needs to appear at the end, inside the field
14+ endDecoration ?: React . ReactNode
15+
16+ // Something that needs to appear after the end, outside the field
17+ afterEndDecoration ?: React . ReactNode
18+
19+ debug ?: boolean
20+ }
21+
22+ function Input ( {
23+ className,
24+ type,
25+ beforeStartDecoration,
26+ startDecoration,
27+ endDecoration,
28+ afterEndDecoration,
29+ debug,
30+ ...props
31+ } : React . ComponentProps < 'input' > & OwnProps ) {
32+ const startDecorationRef = useRef < HTMLSpanElement > ( null )
33+ const [ startDecorationWidth , setStartDecorationWidth ] = useState < number > ( 0 )
34+ const endDecorationRef = useRef < HTMLSpanElement > ( null )
35+ const [ endDecorationWidth , setEndDecorationWidth ] = useState < number > ( 0 )
36+
37+ useEffect ( ( ) => {
38+ if ( ! ! startDecoration && ! ! startDecorationRef . current ) {
39+ const rect = startDecorationRef . current . getBoundingClientRect ( )
40+ setStartDecorationWidth ( rect . width )
41+ } else {
42+ setStartDecorationWidth ( 0 )
43+ }
44+ } , [ startDecoration , startDecorationRef . current ] )
45+
46+ useEffect ( ( ) => {
47+ if ( ! ! endDecoration && ! ! endDecorationRef . current ) {
48+ const rect = endDecorationRef . current . getBoundingClientRect ( )
49+ setEndDecorationWidth ( rect . width )
50+ } else {
51+ setEndDecorationWidth ( 0 )
52+ }
53+ } , [ endDecoration , endDecorationRef . current ] ) // Re-run if content changes
54+
55+ const startStyle = ! ! startDecorationWidth ? { paddingLeft : `${ 16 + startDecorationWidth } px` } : { }
56+ const endStyle = ! ! endDecorationWidth ? { paddingRight : `${ 16 + endDecorationWidth } px` } : { }
57+
58+ const input = (
759 < input
860 type = { type }
961 data-slot = "input"
@@ -13,9 +65,32 @@ function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
1365 'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive' ,
1466 className
1567 ) }
68+ style = { { ...startStyle , ...endStyle } }
1669 { ...props }
1770 />
1871 )
72+
73+ // const hasInsideDecorations = !!startDecoration || !!endDecoration
74+ // const hasOutsideDecorations = !!beforeStartDecoration || !!afterEndDecoration
75+ return (
76+ < >
77+ { beforeStartDecoration }
78+ < div className = { 'relative' } >
79+ { ! ! startDecoration && (
80+ < span className = { 'absolute left-2.5 top-2.5' } ref = { startDecorationRef } >
81+ { startDecoration }
82+ </ span >
83+ ) }
84+ { input }
85+ { ! ! endDecoration && (
86+ < span className = { 'absolute right-2.5 top-2.5' } ref = { endDecorationRef } >
87+ { endDecoration }
88+ </ span >
89+ ) }
90+ </ div >
91+ { afterEndDecoration }
92+ </ >
93+ )
1994}
2095
2196export { Input }
0 commit comments