@mantine/hooks
Version:
A collection of 50+ hooks for state and UI management
1 lines • 5.35 kB
Source Map (JSON)
{"version":3,"file":"use-file-dialog.cjs","names":[],"sources":["../../src/use-file-dialog/use-file-dialog.ts"],"sourcesContent":["import { useCallback, useRef, useState } from 'react';\nimport { useIsomorphicEffect } from '../use-isomorphic-effect/use-isomorphic-effect';\n\nexport interface UseFileDialogOptions {\n /** Determines whether multiple files are allowed, `true` by default */\n multiple?: boolean;\n\n /** `accept` attribute of the file input, '*' by default */\n accept?: string;\n\n /** `capture` attribute of the file input */\n capture?: string;\n\n /** Determines whether the user can pick a directory instead of file, `false` by default */\n directory?: boolean;\n\n /** Determines whether the file input state should be reset when the file dialog is opened, `false` by default */\n resetOnOpen?: boolean;\n\n /** Initial selected files */\n initialFiles?: FileList | File[];\n\n /** Called when files are selected */\n onChange?: (files: FileList | null) => void;\n\n /** Called when file dialog is canceled */\n onCancel?: () => void;\n}\n\nconst defaultOptions: UseFileDialogOptions = {\n multiple: true,\n accept: '*',\n};\n\nfunction getInitialFilesList(files: UseFileDialogOptions['initialFiles']): FileList | null {\n if (!files) {\n return null;\n }\n\n if (files instanceof FileList) {\n return files;\n }\n\n const result = new DataTransfer();\n for (const file of files) {\n result.items.add(file);\n }\n\n return result.files;\n}\n\nfunction createInput(options: UseFileDialogOptions) {\n if (typeof document === 'undefined') {\n return null;\n }\n\n const input = document.createElement('input');\n input.type = 'file';\n\n if (options.accept) {\n input.accept = options.accept;\n }\n\n if (options.multiple) {\n input.multiple = options.multiple;\n }\n\n if (options.capture) {\n input.capture = options.capture;\n }\n\n if (options.directory) {\n input.webkitdirectory = options.directory;\n }\n\n input.style.display = 'none';\n return input;\n}\n\nexport interface UseFileDialogReturnValue {\n files: FileList | null;\n open: () => void;\n reset: () => void;\n}\n\nexport function useFileDialog(input: UseFileDialogOptions = {}): UseFileDialogReturnValue {\n const options: UseFileDialogOptions = { ...defaultOptions, ...input };\n const [files, setFiles] = useState<FileList | null>(getInitialFilesList(options.initialFiles));\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n const handleChange = useCallback(\n (event: Event) => {\n const target = event.target as HTMLInputElement;\n if (target?.files) {\n setFiles(target.files);\n options.onChange?.(target.files);\n }\n },\n [options.onChange]\n );\n\n const createAndSetupInput = useCallback(() => {\n inputRef.current?.remove();\n inputRef.current = createInput(options);\n\n if (inputRef.current) {\n inputRef.current.addEventListener('change', handleChange, { once: true });\n if (options.onCancel) {\n inputRef.current.addEventListener('cancel', options.onCancel, { once: true });\n }\n document.body.appendChild(inputRef.current);\n }\n }, [options, handleChange]);\n\n useIsomorphicEffect(() => {\n createAndSetupInput();\n return () => inputRef.current?.remove();\n }, []);\n\n const reset = useCallback(() => {\n setFiles(null);\n options.onChange?.(null);\n }, [options.onChange]);\n\n const open = useCallback(() => {\n if (options.resetOnOpen) {\n reset();\n }\n\n createAndSetupInput();\n inputRef.current?.click();\n }, [options.resetOnOpen, reset, createAndSetupInput]);\n\n return { files, open, reset };\n}\n\nexport namespace useFileDialog {\n export type Options = UseFileDialogOptions;\n export type ReturnValue = UseFileDialogReturnValue;\n}\n"],"mappings":";;;;AA6BA,MAAM,iBAAuC;CAC3C,UAAU;CACV,QAAQ;AACV;AAEA,SAAS,oBAAoB,OAA8D;CACzF,IAAI,CAAC,OACH,OAAO;CAGT,IAAI,iBAAiB,UACnB,OAAO;CAGT,MAAM,SAAS,IAAI,aAAa;CAChC,KAAK,MAAM,QAAQ,OACjB,OAAO,MAAM,IAAI,IAAI;CAGvB,OAAO,OAAO;AAChB;AAEA,SAAS,YAAY,SAA+B;CAClD,IAAI,OAAO,aAAa,aACtB,OAAO;CAGT,MAAM,QAAQ,SAAS,cAAc,OAAO;CAC5C,MAAM,OAAO;CAEb,IAAI,QAAQ,QACV,MAAM,SAAS,QAAQ;CAGzB,IAAI,QAAQ,UACV,MAAM,WAAW,QAAQ;CAG3B,IAAI,QAAQ,SACV,MAAM,UAAU,QAAQ;CAG1B,IAAI,QAAQ,WACV,MAAM,kBAAkB,QAAQ;CAGlC,MAAM,MAAM,UAAU;CACtB,OAAO;AACT;AAQA,SAAgB,cAAc,QAA8B,CAAC,GAA6B;CACxF,MAAM,UAAgC;EAAE,GAAG;EAAgB,GAAG;CAAM;CACpE,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAsC,oBAAoB,QAAQ,YAAY,CAAC;CAC7F,MAAM,YAAA,GAAA,MAAA,QAA2C,IAAI;CAErD,MAAM,gBAAA,GAAA,MAAA,cACH,UAAiB;EAChB,MAAM,SAAS,MAAM;EACrB,IAAI,QAAQ,OAAO;GACjB,SAAS,OAAO,KAAK;GACrB,QAAQ,WAAW,OAAO,KAAK;EACjC;CACF,GACA,CAAC,QAAQ,QAAQ,CACnB;CAEA,MAAM,uBAAA,GAAA,MAAA,mBAAwC;EAC5C,SAAS,SAAS,OAAO;EACzB,SAAS,UAAU,YAAY,OAAO;EAEtC,IAAI,SAAS,SAAS;GACpB,SAAS,QAAQ,iBAAiB,UAAU,cAAc,EAAE,MAAM,KAAK,CAAC;GACxE,IAAI,QAAQ,UACV,SAAS,QAAQ,iBAAiB,UAAU,QAAQ,UAAU,EAAE,MAAM,KAAK,CAAC;GAE9E,SAAS,KAAK,YAAY,SAAS,OAAO;EAC5C;CACF,GAAG,CAAC,SAAS,YAAY,CAAC;CAE1B,8BAAA,0BAA0B;EACxB,oBAAoB;EACpB,aAAa,SAAS,SAAS,OAAO;CACxC,GAAG,CAAC,CAAC;CAEL,MAAM,SAAA,GAAA,MAAA,mBAA0B;EAC9B,SAAS,IAAI;EACb,QAAQ,WAAW,IAAI;CACzB,GAAG,CAAC,QAAQ,QAAQ,CAAC;CAWrB,OAAO;EAAE;EAAO,OAAA,GAAA,MAAA,mBATe;GAC7B,IAAI,QAAQ,aACV,MAAM;GAGR,oBAAoB;GACpB,SAAS,SAAS,MAAM;EAC1B,GAAG;GAAC,QAAQ;GAAa;GAAO;EAAmB,CAEhC;EAAG;CAAM;AAC9B"}