file-tree-create-name.tsx 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import { createContext, FC, useContext, useMemo, useReducer } from 'react'
  2. import { isCleanFilename } from '../util/safe-path'
  3. const FileTreeCreateNameContext = createContext<
  4. | {
  5. name: string
  6. touchedName: boolean
  7. validName: boolean
  8. setName: (name: string) => void
  9. }
  10. | undefined
  11. >(undefined)
  12. export const useFileTreeCreateName = () => {
  13. const context = useContext(FileTreeCreateNameContext)
  14. if (!context) {
  15. throw new Error(
  16. 'useFileTreeCreateName is only available inside FileTreeCreateNameProvider'
  17. )
  18. }
  19. return context
  20. }
  21. type State = {
  22. name: string
  23. touchedName: boolean
  24. }
  25. const FileTreeCreateNameProvider: FC<
  26. React.PropsWithChildren<{ initialName?: string }>
  27. > = ({ children, initialName = '' }) => {
  28. const [state, setName] = useReducer(
  29. (state: State, name: string) => ({
  30. name, // the file name
  31. touchedName: true, // whether the name has been edited
  32. }),
  33. {
  34. name: initialName,
  35. touchedName: false,
  36. }
  37. )
  38. // validate the file name
  39. const validName = useMemo(() => isCleanFilename(state.name.trim()), [state])
  40. return (
  41. <FileTreeCreateNameContext.Provider
  42. value={{ ...state, setName, validName }}
  43. >
  44. {children}
  45. </FileTreeCreateNameContext.Provider>
  46. )
  47. }
  48. export default FileTreeCreateNameProvider