editor-switch.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import { ChangeEvent, FC, memo, useCallback, useId } from 'react'
  2. import OLTooltip from '@/shared/components/ol/ol-tooltip'
  3. import { sendMB } from '../../../infrastructure/event-tracking'
  4. import { useTranslation } from 'react-i18next'
  5. import { useEditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
  6. import { useEditorPropertiesContext } from '@/features/ide-react/context/editor-properties-context'
  7. import { isVisualEditorAvailable } from '../utils/visual-editor'
  8. function EditorSwitch() {
  9. const { t } = useTranslation()
  10. const { showVisual: visual, setShowVisual: setVisual } =
  11. useEditorPropertiesContext()
  12. const { openDocName } = useEditorOpenDocContext()
  13. const inputId = useId()
  14. const richTextAvailable = openDocName
  15. ? isVisualEditorAvailable(openDocName)
  16. : false
  17. const handleChange = useCallback(
  18. (event: ChangeEvent<HTMLInputElement>) => {
  19. const editorType = event.target.value
  20. switch (editorType) {
  21. case 'cm6':
  22. setVisual(false)
  23. break
  24. case 'rich-text':
  25. setVisual(true)
  26. break
  27. }
  28. sendMB('editor-switch-change', { editorType })
  29. },
  30. [setVisual]
  31. )
  32. return (
  33. <div
  34. className="editor-toggle-switch"
  35. aria-label={t('toolbar_code_visual_editor_switch')}
  36. >
  37. <form>
  38. <fieldset className="toggle-switch">
  39. <legend className="visually-hidden">Editor mode.</legend>
  40. <input
  41. type="radio"
  42. name="editor"
  43. value="cm6"
  44. id={inputId}
  45. className="toggle-switch-input"
  46. checked={!richTextAvailable || !visual}
  47. onChange={handleChange}
  48. />
  49. <label htmlFor={inputId} className="toggle-switch-label">
  50. <span>{t('code_editor')}</span>
  51. </label>
  52. <RichTextToggle
  53. checked={richTextAvailable && visual}
  54. disabled={!richTextAvailable}
  55. handleChange={handleChange}
  56. />
  57. </fieldset>
  58. </form>
  59. </div>
  60. )
  61. }
  62. const RichTextToggle: FC<{
  63. checked: boolean
  64. disabled: boolean
  65. handleChange: (event: ChangeEvent<HTMLInputElement>) => void
  66. }> = ({ checked, disabled, handleChange }) => {
  67. const { t } = useTranslation()
  68. const inputId = useId()
  69. const toggle = (
  70. <span>
  71. <input
  72. type="radio"
  73. name="editor"
  74. value="rich-text"
  75. id={inputId}
  76. className="toggle-switch-input"
  77. checked={checked}
  78. onChange={handleChange}
  79. disabled={disabled}
  80. />
  81. <label htmlFor={inputId} className="toggle-switch-label">
  82. <span>{t('visual_editor')}</span>
  83. </label>
  84. </span>
  85. )
  86. if (disabled) {
  87. return (
  88. <OLTooltip
  89. description={t('visual_editor_is_only_available_for_tex_files')}
  90. id="rich-text-toggle-tooltip"
  91. overlayProps={{ placement: 'bottom' }}
  92. tooltipProps={{ className: 'tooltip-wide' }}
  93. >
  94. {toggle}
  95. </OLTooltip>
  96. )
  97. }
  98. return (
  99. <OLTooltip
  100. id="rich-text-toggle-tooltip"
  101. description={t('toolbar_change_editor_mode')}
  102. overlayProps={{ placement: 'bottom' }}
  103. tooltipProps={{ className: 'tooltip-wide' }}
  104. >
  105. {toggle}
  106. </OLTooltip>
  107. )
  108. }
  109. export default memo(EditorSwitch)