@@ -5,15 +5,19 @@ import horizontalGripIcon from '@ui5/webcomponents-icons/dist/horizontal-grip.js
55import verticalGripIcon from '@ui5/webcomponents-icons/dist/vertical-grip.js' ;
66import { useCurrentTheme , useI18nBundle , useIsRTL , useSyncRef , useStylesheet } from '@ui5/webcomponents-react-base' ;
77import { forwardRef , useEffect , useRef , useState } from 'react' ;
8+ import type { KeyboardEventHandler , PointerEventHandler } from 'react' ;
89import { PRESS_ARROW_KEYS_TO_MOVE } from '../../i18n/i18n-defaults.js' ;
910import type { CommonProps } from '../../types/index.js' ;
10- import { Button , Icon } from '../../webComponents/index.js' ;
11+ import { Button } from '../../webComponents/Button/index.js' ;
12+ import { Icon } from '../../webComponents/Icon/index.js' ;
13+ import type { SplitterLayoutPropTypes } from '../SplitterLayout/types.js' ;
1114import { classNames , styleData } from './Splitter.module.css.js' ;
1215
1316export interface SplitterPropTypes extends CommonProps {
1417 height : string | number ;
1518 width : string | number ;
1619 vertical : boolean ;
20+ onResize : SplitterLayoutPropTypes [ 'onResize' ] | undefined ;
1721}
1822
1923const verticalPositionInfo = {
@@ -39,7 +43,7 @@ const horizontalPositionInfo = {
3943} ;
4044
4145const Splitter = forwardRef < HTMLDivElement , SplitterPropTypes > ( ( props , ref ) => {
42- const { vertical } = props ;
46+ const { vertical, onResize } = props ;
4347 const i18nBundle = useI18nBundle ( '@ui5/webcomponents-react' ) ;
4448 const [ componentRef , localRef ] = useSyncRef < HTMLDivElement > ( ref ) ;
4549 const isRtl = useIsRTL ( localRef ) ;
@@ -58,6 +62,38 @@ const Splitter = forwardRef<HTMLDivElement, SplitterPropTypes>((props, ref) => {
5862 const [ isDragging , setIsDragging ] = useState < boolean | string > ( false ) ;
5963 const [ isSiblings , setIsSiblings ] = useState ( [ 'previousSibling' , 'nextSibling' ] ) ;
6064
65+ const animationFrameIdRef = useRef ( null ) ;
66+ function fireOnResize ( prevSibling : HTMLElement , nextSibling : HTMLElement ) {
67+ if ( animationFrameIdRef . current ) {
68+ cancelAnimationFrame ( animationFrameIdRef . current ) ;
69+ }
70+ if ( typeof onResize !== 'function' ) {
71+ return ;
72+ }
73+ animationFrameIdRef . current = requestAnimationFrame ( ( ) => {
74+ const logicalPrevSibling = isRtl ? nextSibling : prevSibling ;
75+ const logicalNextSibling = isRtl ? prevSibling : nextSibling ;
76+ const splitterWidth = localRef . current . getBoundingClientRect ( ) [ positionKeys . size ] ;
77+ onResize ( {
78+ areas : [
79+ {
80+ size : logicalPrevSibling . getBoundingClientRect ( ) ?. [ positionKeys . size ] + splitterWidth ,
81+ area : logicalPrevSibling ,
82+ } ,
83+ {
84+ // last element doesn't have splitter
85+ size :
86+ logicalNextSibling . getBoundingClientRect ( ) ?. [ positionKeys . size ] +
87+ ( logicalNextSibling . nextElementSibling !== null ? splitterWidth : 0 ) ,
88+ area : logicalNextSibling ,
89+ } ,
90+ ] ,
91+ splitter : localRef . current ,
92+ } ) ;
93+ animationFrameIdRef . current = null ;
94+ } ) ;
95+ }
96+
6197 const handleSplitterMove = ( e ) => {
6298 const offset = resizerClickOffset . current ;
6399 const previousSibling = localRef . current [ isSiblings [ 0 ] ] as HTMLDivElement ;
@@ -71,10 +107,10 @@ const Splitter = forwardRef<HTMLDivElement, SplitterPropTypes>((props, ref) => {
71107
72108 const move = ( ) => {
73109 previousSibling . style . flex = `0 0 ${ previousSiblingSize . current + sizeDiv } px` ;
74-
75110 if ( nextSibling . nextSibling && previousSiblingSize . current + sizeDiv > 0 ) {
76111 nextSibling . style . flex = `0 0 ${ nextSiblingSize . current - sizeDiv } px` ;
77112 }
113+ fireOnResize ( previousSibling , nextSibling ) ;
78114 } ;
79115
80116 if (
@@ -126,6 +162,7 @@ const Splitter = forwardRef<HTMLDivElement, SplitterPropTypes>((props, ref) => {
126162 ( nextSiblingRect ?. [ positionKeys . size ] as number ) + prevSiblingRect ?. [ positionKeys . size ]
127163 } px`;
128164 }
165+ fireOnResize ( prevSibling , nextSibling ) ;
129166 }
130167
131168 // right
@@ -142,10 +179,12 @@ const Splitter = forwardRef<HTMLDivElement, SplitterPropTypes>((props, ref) => {
142179 ( prevSiblingRect ?. [ positionKeys . size ] as number ) + nextSiblingRect ?. [ positionKeys . size ]
143180 } px`;
144181 }
182+
183+ fireOnResize ( prevSibling , nextSibling ) ;
145184 }
146185 } ;
147186
148- const handleMoveSplitterStart = ( e ) => {
187+ const handleMoveSplitterStart : PointerEventHandler < HTMLDivElement > = ( e ) => {
149188 if ( e . type === 'pointerdown' && e . pointerType !== 'touch' ) {
150189 return ;
151190 }
@@ -175,7 +214,7 @@ const Splitter = forwardRef<HTMLDivElement, SplitterPropTypes>((props, ref) => {
175214 start . current = e [ `client${ positionKeys . position } ` ] ;
176215 } ;
177216
178- const onHandleKeyDown = ( e ) => {
217+ const onHandleKeyDown : KeyboardEventHandler < HTMLDivElement > = ( e ) => {
179218 const keyEventProperties = e . code ?? e . key ;
180219 if (
181220 keyEventProperties === 'ArrowRight' ||
@@ -203,6 +242,12 @@ const Splitter = forwardRef<HTMLDivElement, SplitterPropTypes>((props, ref) => {
203242 const secondSiblingSize = secondSibling . getBoundingClientRect ( ) ?. [ positionKeys . size ] as number ;
204243 secondSibling . style . flex = `0 0 ${ secondSiblingSize - tickSize } px` ;
205244 firstSibling . style . flex = `0 0 ${ firstSiblingSize + tickSize } px` ;
245+
246+ if ( keyEventProperties === 'ArrowLeft' || keyEventProperties === 'ArrowUp' ) {
247+ fireOnResize ( secondSibling , firstSibling ) ;
248+ } else {
249+ fireOnResize ( firstSibling , secondSibling ) ;
250+ }
206251 }
207252 }
208253 } ;
0 commit comments