index.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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 } from 'react'
  21. import classnames from 'classnames'
  22. import { ResizableBox, ResizableProps } from 'libs/react-resizable'
  23. import ResizeHandle from './ResizeHandle'
  24. import './SplitPane.less'
  25. export interface ISplitPaneProps {
  26. className?: string
  27. type: 'horizontal' | 'vertical'
  28. invert?: boolean
  29. spliter?: boolean
  30. initialSize: number
  31. maxSize?: number
  32. minSize?: number
  33. onResize?: (newSize: number) => void
  34. onResizeStart?: () => void
  35. onResizeStop?: (newSize: number) => void
  36. }
  37. const SplitPane: React.FC<ISplitPaneProps> = (props) => {
  38. const {
  39. className,
  40. type,
  41. invert,
  42. spliter,
  43. initialSize,
  44. maxSize,
  45. minSize,
  46. children,
  47. onResize,
  48. onResizeStart,
  49. onResizeStop
  50. } = props
  51. const [child1, child2] = React.Children.toArray(
  52. children
  53. ) as React.ReactElement[]
  54. const [currentSize, setCurrentSize] = useState(initialSize)
  55. const cls = classnames({
  56. [className]: !!className,
  57. ['split-pane']: true,
  58. [`split-pane-${type}`]: true
  59. })
  60. const resizableProps: Partial<ResizableProps> = {
  61. handle: ResizeHandle,
  62. onResize: (e, { size }) => {
  63. e.stopPropagation()
  64. let newSize: number
  65. if (type === 'horizontal') {
  66. newSize = size.width
  67. } else if (type === 'vertical') {
  68. newSize = size.height
  69. }
  70. setCurrentSize(newSize)
  71. if (onResize) {
  72. onResize(newSize)
  73. }
  74. },
  75. onResizeStart: () => {
  76. if (onResizeStart) {
  77. onResizeStart()
  78. }
  79. },
  80. onResizeStop: (e, { size }) => {
  81. let newSize: number
  82. if (type === 'horizontal') {
  83. newSize = size.width
  84. } else if (type === 'vertical') {
  85. newSize = size.height
  86. }
  87. if (onResizeStop) {
  88. onResizeStop(newSize)
  89. }
  90. }
  91. }
  92. if (type === 'horizontal') {
  93. resizableProps.minConstraints = [minSize, 0]
  94. resizableProps.maxConstraints = [maxSize, 0]
  95. resizableProps.resizeHandles = invert ? ['w'] : ['e']
  96. resizableProps.width = currentSize
  97. resizableProps.axis = 'x'
  98. } else if (type === 'vertical') {
  99. resizableProps.minConstraints = [0, minSize]
  100. resizableProps.maxConstraints = [0, maxSize]
  101. resizableProps.resizeHandles = invert ? ['s'] : ['n']
  102. resizableProps.height = currentSize
  103. resizableProps.axis = 'y'
  104. }
  105. const paneCls = [
  106. classnames({
  107. ['split-pane-1']: !invert,
  108. ['split-pane-2']: invert,
  109. [`split-pane-${type}-spliter`]: spliter
  110. }),
  111. classnames({
  112. 'split-pane-1': invert,
  113. 'split-pane-2': !invert
  114. })
  115. ]
  116. const [pane1Cls, pane2Cls] = paneCls
  117. const partitions = [child1, child2]
  118. if (invert) {
  119. partitions[1] = (
  120. <ResizableBox {...resizableProps}>{partitions[1]}</ResizableBox>
  121. )
  122. } else {
  123. partitions[0] = (
  124. <ResizableBox {...resizableProps}>{partitions[0]}</ResizableBox>
  125. )
  126. }
  127. const [content1, content2] = partitions
  128. return (
  129. <div className={cls}>
  130. <div className={pane1Cls}>{content1}</div>
  131. <div className={pane2Cls}>{content2}</div>
  132. </div>
  133. )
  134. }
  135. export default SplitPane