file-tree-create-name.tsx 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  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<{ initialName?: string }> = ({
  26. children,
  27. initialName = '',
  28. }) => {
  29. const [state, setName] = useReducer(
  30. (state: State, name: string) => ({
  31. name, // the file name
  32. touchedName: true, // whether the name has been edited
  33. }),
  34. {
  35. name: initialName,
  36. touchedName: false,
  37. }
  38. )
  39. // validate the file name
  40. const validName = useMemo(() => isCleanFilename(state.name.trim()), [state])
  41. return (
  42. <FileTreeCreateNameContext.Provider
  43. value={{ ...state, setName, validName }}
  44. >
  45. {children}
  46. </FileTreeCreateNameContext.Provider>
  47. )
  48. }
  49. export default FileTreeCreateNameProvider