@@ -191,6 +191,8 @@ class App {
191191 this . fileInput . style . cursor = 'pointer' ;
192192 this . fileInput . style . zIndex = '10' ;
193193 this . fileInput . style . fontSize = '0' ;
194+ this . fileInput . style . pointerEvents = 'auto' ; // Chrome compatibility
195+ this . fileInput . setAttribute ( 'tabindex' , '-1' ) ; // Make it focusable but not in tab order
194196
195197 // Ensure upload area has overflow hidden
196198 this . uploadArea . style . overflow = 'hidden' ;
@@ -203,43 +205,76 @@ class App {
203205 }
204206
205207 setupEventListeners ( ) {
206- // File input is positioned absolutely over upload area, so clicking anywhere opens it
207- // Also handle direct clicks on upload area as fallback
208+ // Chrome requires direct user interaction - make file input directly clickable
209+ // Ensure file input accepts clicks directly
210+ this . fileInput . addEventListener ( 'click' , ( e ) => {
211+ // Allow normal file input behavior
212+ e . stopPropagation ( ) ;
213+ } ) ;
214+
215+ // Handle clicks on upload area - Chrome compatibility
208216 this . uploadArea . addEventListener ( 'click' , ( e ) => {
209217 // Don't trigger if clicking on remove button or other interactive elements
210218 if ( e . target . closest ( '.remove-file' ) || e . target . closest ( '.btn' ) ) {
211219 return ;
212220 }
213- // If click is not on file input itself, trigger it
214- if ( this . fileInput && e . target !== this . fileInput && ! e . target . closest ( 'input[type="file"]' ) ) {
215- // Use setTimeout for better compatibility
216- setTimeout ( ( ) => {
217- try {
218- this . fileInput . click ( ) ;
219- } catch ( err ) {
220- console . error ( 'Error opening file dialog:' , err ) ;
221- }
222- } , 10 ) ;
221+
222+ // If click is directly on file input, allow it
223+ if ( e . target === this . fileInput || e . target . closest ( 'input[type="file"]' ) ) {
224+ return ;
225+ }
226+
227+ // For Chrome: use direct click without setTimeout
228+ if ( this . fileInput ) {
229+ // Try direct click first (works in most browsers)
230+ try {
231+ this . fileInput . click ( ) ;
232+ } catch ( err ) {
233+ // Fallback: trigger click event
234+ const clickEvent = new MouseEvent ( 'click' , {
235+ bubbles : true ,
236+ cancelable : true ,
237+ view : window
238+ } ) ;
239+ this . fileInput . dispatchEvent ( clickEvent ) ;
240+ }
223241 }
224242 } ) ;
225243
226- // Also handle mousedown for better compatibility
244+ // Also handle mousedown for Chrome - Chrome sometimes needs mousedown
227245 this . uploadArea . addEventListener ( 'mousedown' , ( e ) => {
228246 if ( e . target . closest ( '.remove-file' ) || e . target . closest ( '.btn' ) ) {
229247 return ;
230248 }
231- if ( this . fileInput && e . target !== this . fileInput && ! e . target . closest ( 'input[type="file"]' ) ) {
232- // Prevent default to avoid conflicts
233- e . preventDefault ( ) ;
234- setTimeout ( ( ) => {
249+ if ( e . target === this . fileInput || e . target . closest ( 'input[type="file"]' ) ) {
250+ return ;
251+ }
252+
253+ // For Chrome: trigger click on mouseup (more reliable)
254+ const handleMouseUp = ( ) => {
255+ if ( this . fileInput ) {
235256 try {
257+ this . fileInput . focus ( ) ;
236258 this . fileInput . click ( ) ;
237259 } catch ( err ) {
238260 console . error ( 'Error opening file dialog:' , err ) ;
239261 }
240- } , 10 ) ;
241- }
262+ }
263+ document . removeEventListener ( 'mouseup' , handleMouseUp ) ;
264+ } ;
265+ document . addEventListener ( 'mouseup' , handleMouseUp ) ;
242266 } ) ;
267+
268+ // Make upload-content clickable too (removes pointer-events: none issue)
269+ const uploadContent = this . uploadArea . querySelector ( '.upload-content' ) ;
270+ if ( uploadContent ) {
271+ uploadContent . addEventListener ( 'click' , ( e ) => {
272+ e . stopPropagation ( ) ;
273+ if ( this . fileInput ) {
274+ this . fileInput . click ( ) ;
275+ }
276+ } ) ;
277+ }
243278
244279 // Drag and drop
245280 this . uploadArea . addEventListener ( 'dragover' , ( e ) => {
0 commit comments