Editor.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. * <<
  3. * Davinci
  4. * ==
  5. * Copyright (C) 2016 - 2017 EDP
  6. * ==
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. * >>
  19. */
  20. import React, { useState, useCallback } from 'react'
  21. import cloneDeep from 'lodash/cloneDeep'
  22. import { Row, Button, Modal } from 'antd'
  23. import { RichText, RichTextNode } from 'components/RichText'
  24. import Toolbar from 'components/RichText/Toolbar'
  25. import Preview from './Preview'
  26. import Styles from './RichText.less'
  27. interface IRichTextEditorProps {
  28. content: string | RichTextNode[]
  29. mapFields: object
  30. fieldBoundaries: [string, string]
  31. onChange: (value: RichTextNode[]) => void
  32. onFormatText: (text: string) => string
  33. }
  34. const RichTextEditor: React.FC<IRichTextEditorProps> = (props) => {
  35. const { content, mapFields, fieldBoundaries, onChange, onFormatText } = props
  36. const [previewVisible, setPreviewVisible] = useState(false)
  37. const [previewContent, setPreviewContent] = useState(null)
  38. const openPreview = useCallback(() => {
  39. // @REFACTOR temporarily resolve range selection error in Editor
  40. // caused by same content value reference in Editor & Preview
  41. const clonedContent = cloneDeep(content)
  42. setPreviewContent(clonedContent)
  43. setPreviewVisible(true)
  44. }, [content])
  45. const closePreview = useCallback(() => {
  46. setPreviewVisible(false)
  47. }, [])
  48. return (
  49. <div className={Styles.richText}>
  50. <RichText
  51. className={Styles.editor}
  52. value={content}
  53. toolbar={
  54. <Toolbar.Toolbar>
  55. <Toolbar.Font />
  56. <Toolbar.Heading />
  57. <Toolbar.Format />
  58. <Toolbar.Alignment />
  59. <Toolbar.Link />
  60. <Toolbar.Image />
  61. <Toolbar.Marquee />
  62. <Toolbar.Field
  63. mapFields={mapFields}
  64. fieldBoundaries={fieldBoundaries}
  65. />
  66. <Toolbar.Reset />
  67. </Toolbar.Toolbar>
  68. }
  69. onChange={onChange}
  70. />
  71. <Row type="flex" align="middle" justify="end" style={{ paddingTop: 16 }}>
  72. <Button onClick={openPreview} type="primary">
  73. 预览
  74. </Button>
  75. </Row>
  76. <Modal
  77. title="富文本预览"
  78. wrapClassName="ant-modal-large"
  79. visible={previewVisible}
  80. footer={null}
  81. onCancel={closePreview}
  82. >
  83. <Preview content={previewContent} onFormatText={onFormatText} />
  84. </Modal>
  85. </div>
  86. )
  87. }
  88. export default RichTextEditor