UNPKG

@mantine/hooks

Version:

A collection of 50+ hooks for state and UI management

1 lines 5.1 kB
{"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 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;CACT;AAED,SAAS,oBAAoB,OAA8D;AACzF,KAAI,CAAC,MACH,QAAO;AAGT,KAAI,iBAAiB,SACnB,QAAO;CAGT,MAAM,SAAS,IAAI,cAAc;AACjC,MAAK,MAAM,QAAQ,MACjB,QAAO,MAAM,IAAI,KAAK;AAGxB,QAAO,OAAO;;AAGhB,SAAS,YAAY,SAA+B;AAClD,KAAI,OAAO,aAAa,YACtB,QAAO;CAGT,MAAM,QAAQ,SAAS,cAAc,QAAQ;AAC7C,OAAM,OAAO;AAEb,KAAI,QAAQ,OACV,OAAM,SAAS,QAAQ;AAGzB,KAAI,QAAQ,SACV,OAAM,WAAW,QAAQ;AAG3B,KAAI,QAAQ,QACV,OAAM,UAAU,QAAQ;AAG1B,KAAI,QAAQ,UACV,OAAM,kBAAkB,QAAQ;AAGlC,OAAM,MAAM,UAAU;AACtB,QAAO;;AAST,SAAgB,cAAc,QAA8B,EAAE,EAA4B;CACxF,MAAM,UAAgC;EAAE,GAAG;EAAgB,GAAG;EAAO;CACrE,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAsC,oBAAoB,QAAQ,aAAa,CAAC;CAC9F,MAAM,YAAA,GAAA,MAAA,QAA2C,KAAK;CAEtD,MAAM,gBAAA,GAAA,MAAA,cACH,UAAiB;EAChB,MAAM,SAAS,MAAM;AACrB,MAAI,QAAQ,OAAO;AACjB,YAAS,OAAO,MAAM;AACtB,WAAQ,WAAW,OAAO,MAAM;;IAGpC,CAAC,QAAQ,SAAS,CACnB;CAED,MAAM,uBAAA,GAAA,MAAA,mBAAwC;AAC5C,WAAS,SAAS,QAAQ;AAC1B,WAAS,UAAU,YAAY,QAAQ;AAEvC,MAAI,SAAS,SAAS;AACpB,YAAS,QAAQ,iBAAiB,UAAU,cAAc,EAAE,MAAM,MAAM,CAAC;AACzE,YAAS,KAAK,YAAY,SAAS,QAAQ;;IAE5C,CAAC,SAAS,aAAa,CAAC;AAE3B,+BAAA,0BAA0B;AACxB,uBAAqB;AACrB,eAAa,SAAS,SAAS,QAAQ;IACtC,EAAE,CAAC;CAEN,MAAM,SAAA,GAAA,MAAA,mBAA0B;AAC9B,WAAS,KAAK;AACd,UAAQ,WAAW,KAAK;IACvB,CAAC,QAAQ,SAAS,CAAC;AAWtB,QAAO;EAAE;EAAO,OAAA,GAAA,MAAA,mBATe;AAC7B,OAAI,QAAQ,YACV,QAAO;AAGT,wBAAqB;AACrB,YAAS,SAAS,OAAO;KACxB;GAAC,QAAQ;GAAa;GAAO;GAAoB,CAAC;EAE/B;EAAO"}