project-name-editable-label.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import { useEffect, useState, useRef } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import classNames from 'classnames'
  4. import OLFormControl from '@/features/ui/components/ol/ol-form-control'
  5. import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
  6. import MaterialIcon from '@/shared/components/material-icon'
  7. type ProjectNameEditableLabelProps = {
  8. projectName: string
  9. onChange: (value: string) => void
  10. hasRenamePermissions?: boolean
  11. className?: string
  12. }
  13. function ProjectNameEditableLabel({
  14. projectName,
  15. hasRenamePermissions,
  16. onChange,
  17. className,
  18. }: ProjectNameEditableLabelProps) {
  19. const { t } = useTranslation()
  20. const [isRenaming, setIsRenaming] = useState(false)
  21. const canRename = hasRenamePermissions && !isRenaming
  22. const [inputContent, setInputContent] = useState(projectName)
  23. const inputRef = useRef<HTMLInputElement | null>(null)
  24. useEffect(() => {
  25. if (isRenaming) {
  26. inputRef.current?.select()
  27. }
  28. }, [isRenaming])
  29. function startRenaming() {
  30. if (canRename) {
  31. setInputContent(projectName)
  32. setIsRenaming(true)
  33. }
  34. }
  35. function finishRenaming() {
  36. setIsRenaming(false)
  37. onChange(inputContent)
  38. }
  39. function handleKeyDown(event: React.KeyboardEvent) {
  40. if (event.key === 'Enter') {
  41. event.preventDefault()
  42. finishRenaming()
  43. }
  44. }
  45. function handleOnChange(event: React.ChangeEvent<HTMLInputElement>) {
  46. setInputContent(event.target.value)
  47. }
  48. function handleBlur() {
  49. if (isRenaming) {
  50. finishRenaming()
  51. }
  52. }
  53. return (
  54. <div className={classNames('project-name', className)}>
  55. {!isRenaming && (
  56. <span className="name" onDoubleClick={startRenaming}>
  57. {projectName}
  58. </span>
  59. )}
  60. {isRenaming && (
  61. <OLFormControl
  62. ref={inputRef}
  63. type="text"
  64. onKeyDown={handleKeyDown}
  65. onChange={handleOnChange}
  66. onBlur={handleBlur}
  67. value={inputContent}
  68. />
  69. )}
  70. {canRename && (
  71. <OLTooltip
  72. id="online-user"
  73. description={t('rename')}
  74. overlayProps={{ placement: 'bottom', trigger: ['hover', 'focus'] }}
  75. >
  76. {/* eslint-disable-next-line jsx-a11y/anchor-is-valid, jsx-a11y/click-events-have-key-events, jsx-a11y/interactive-supports-focus */}
  77. <a className="rename" role="button" onClick={startRenaming}>
  78. <MaterialIcon type="edit" className="align-text-bottom" />
  79. </a>
  80. </OLTooltip>
  81. )}
  82. </div>
  83. )
  84. }
  85. export default ProjectNameEditableLabel