editableTabTitle.tsx 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import {useEffect, useRef, useState} from 'react';
  2. import styled from '@emotion/styled';
  3. function EditableTabTitle({
  4. label,
  5. onChange,
  6. isEditing,
  7. setIsEditing,
  8. }: {
  9. isEditing: boolean;
  10. label: string;
  11. onChange: (newLabel: string) => void;
  12. setIsEditing: (isEditing: boolean) => void;
  13. }) {
  14. const [inputValue, setInputValue] = useState(label);
  15. const inputRef = useRef<HTMLInputElement>(null);
  16. const isEmpty = !inputValue.trim();
  17. const handleOnBlur = () => {
  18. if (!isEditing) {
  19. return;
  20. }
  21. if (isEmpty) {
  22. setInputValue(label);
  23. return;
  24. }
  25. if (inputValue !== label) {
  26. onChange(inputValue);
  27. }
  28. setIsEditing(false);
  29. };
  30. const handleOnKeyDown = (e: React.KeyboardEvent) => {
  31. if (e.key === 'Enter') {
  32. handleOnBlur();
  33. }
  34. if (e.key === 'Escape') {
  35. setInputValue(label);
  36. setIsEditing(false);
  37. }
  38. };
  39. useEffect(() => {
  40. setTimeout(() => {
  41. inputRef?.current?.focus();
  42. }, 0);
  43. }, [isEditing, inputRef]);
  44. const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  45. setInputValue(e.target.value);
  46. };
  47. return isEditing ? (
  48. <StyledInput
  49. type="text"
  50. value={inputValue}
  51. onChange={handleOnChange}
  52. onKeyDown={handleOnKeyDown}
  53. onBlur={handleOnBlur}
  54. ref={inputRef}
  55. size={inputValue.length > 1 ? inputValue.length - 1 : 1}
  56. />
  57. ) : (
  58. label
  59. );
  60. }
  61. export default EditableTabTitle;
  62. const StyledInput = styled('input')`
  63. border: none !important;
  64. width: fit-content;
  65. background: transparent;
  66. outline: none;
  67. height: auto;
  68. padding: 0;
  69. font-size: inherit;
  70. &,
  71. &:focus,
  72. &:active,
  73. &:hover {
  74. box-shadow: none;
  75. }
  76. `;