ProjectName.tsx 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import "./TextInput.scss";
  2. import React, { Component } from "react";
  3. import { selectNode, removeSelection } from "../utils";
  4. type Props = {
  5. value: string;
  6. onChange: (value: string) => void;
  7. label: string;
  8. isNameEditable: boolean;
  9. };
  10. export class ProjectName extends Component<Props> {
  11. private handleFocus = (event: React.FocusEvent<HTMLElement>) => {
  12. selectNode(event.currentTarget);
  13. };
  14. private handleBlur = (event: React.FocusEvent<HTMLElement>) => {
  15. const value = event.currentTarget.innerText.trim();
  16. if (value !== this.props.value) {
  17. this.props.onChange(value);
  18. }
  19. removeSelection();
  20. };
  21. private handleKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {
  22. if (event.key === "Enter") {
  23. event.preventDefault();
  24. if (event.nativeEvent.isComposing || event.keyCode === 229) {
  25. return;
  26. }
  27. event.currentTarget.blur();
  28. }
  29. };
  30. private makeEditable = (editable: HTMLSpanElement | null) => {
  31. if (!editable) {
  32. return;
  33. }
  34. try {
  35. editable.contentEditable = "plaintext-only";
  36. } catch {
  37. editable.contentEditable = "true";
  38. }
  39. };
  40. public render() {
  41. return this.props.isNameEditable ? (
  42. <span
  43. suppressContentEditableWarning
  44. ref={this.makeEditable}
  45. data-type="wysiwyg"
  46. className="TextInput"
  47. role="textbox"
  48. aria-label={this.props.label}
  49. onBlur={this.handleBlur}
  50. onKeyDown={this.handleKeyDown}
  51. onFocus={this.handleFocus}
  52. >
  53. {this.props.value}
  54. </span>
  55. ) : (
  56. <span
  57. className="TextInput TextInput--readonly"
  58. aria-label={this.props.label}
  59. >
  60. {this.props.value}
  61. </span>
  62. );
  63. }
  64. }