11'use client' ;
22
3- import { dateTime } from '@gravity-ui/date-utils' ;
4- import { Button , Popup , Sheet } from '@gravity-ui/uikit' ;
5- import type { PopupOffset , PopupPlacement } from '@gravity-ui/uikit' ;
3+ import { Popup , Sheet } from '@gravity-ui/uikit' ;
4+ import type { PopupProps } from '@gravity-ui/uikit' ;
65
76import { block } from '../../../../utils/cn' ;
8- import { RelativeDatePicker } from '../../../RelativeDatePicker' ;
9- import type { RelativeDatePickerProps } from '../../../RelativeDatePicker' ;
10- import type { RelativeRangeDatePickerState } from '../../hooks/useRelativeRangeDatePickerState' ;
11- import type { RelativeRangeDatePickerProps } from '../../types' ;
12- import { Presets } from '../Presets/Presets' ;
13- import { Zones } from '../Zones/Zones' ;
7+ import type { PopupStyleProps } from '../../../types' ;
148
15- import { i18n } from './i18n ' ;
16- import { useRelativeRangeDatePickerDialogState } from './useRelativeRangeDatePickerDialogState ' ;
9+ import { PickerForm } from './PickerForm ' ;
10+ import type { PickerFormProps } from './PickerForm ' ;
1711
1812import './PickerDialog.scss' ;
1913
2014const b = block ( 'relative-range-date-picker-dialog' ) ;
2115
22- export interface PickerDialogProps {
23- className ?: string ;
24- state : RelativeRangeDatePickerState ;
25- props : RelativeRangeDatePickerProps ;
16+ export interface PickerDialogProps extends PickerFormProps , PopupStyleProps {
17+ /** Popup anchor */
18+ anchor : HTMLElement | null ;
19+ /** Manages `Popup` visibility */
2620 open : boolean ;
27- placement ?: PopupPlacement ;
28- offset ?: PopupOffset ;
21+ /** Handles popup close event */
22+ onClose : ( reason ?: Parameters < NonNullable < PopupProps [ 'onOpenChange' ] > > [ 2 ] | 'apply' ) => void ;
23+ /** If true `Popup` act like a modal dialog */
24+ modal ?: boolean ;
25+ /** If true `Sheet` is used instead of `Popup` */
2926 isMobile ?: boolean ;
30- anchor : HTMLElement | null ;
31- onClose : ( ) => void ;
32- focusInput ?: ( ) => void ;
33- disableFocusTrap ?: boolean ;
3427}
3528
3629export function PickerDialog ( {
37- props,
38- state,
3930 open,
4031 onClose,
41- focusInput,
4232 isMobile,
4333 anchor,
44- className,
45- placement,
46- offset,
47- disableFocusTrap,
34+ popupClassName,
35+ popupStyle,
36+ popupPlacement,
37+ popupOffset,
38+ modal,
39+ ...props
4840} : PickerDialogProps ) {
4941 if ( isMobile ) {
5042 return (
5143 < Sheet
5244 visible = { open }
53- onClose = { onClose }
54- contentClassName = { b ( 'content' , { mobile : true , size : 'xl' } , className ) }
45+ onClose = { ( ) => {
46+ onClose ( 'outside-press' ) ;
47+ } }
48+ contentClassName = { b ( 'content' , { mobile : true , size : 'xl' } , popupClassName ) }
5549 >
56- < DialogContent { ...props } size = "xl" state = { state } onApply = { onClose } />
50+ < PickerForm
51+ { ...props }
52+ size = "xl"
53+ onApply = { ( ) => {
54+ onClose ( 'apply' ) ;
55+ } }
56+ />
5757 </ Sheet >
5858 ) ;
5959 }
@@ -63,114 +63,23 @@ export function PickerDialog({
6363 open = { open }
6464 onOpenChange = { ( isOpen , _event , reason ) => {
6565 if ( ! isOpen ) {
66- onClose ( ) ;
67- if ( reason === 'escape-key' ) {
68- focusInput ?.( ) ;
69- }
66+ onClose ( reason ) ;
7067 }
7168 } }
72- placement = { placement }
73- offset = { offset }
69+ placement = { popupPlacement }
70+ offset = { popupOffset }
7471 role = "dialog"
7572 anchorElement = { anchor }
76- className = { b ( 'content' , { size : props . size } , className ) }
77- modal = { ! disableFocusTrap }
73+ className = { b ( 'content' , { size : props . size } , popupClassName ) }
74+ style = { popupStyle }
75+ modal = { modal }
7876 >
79- < DialogContent { ...props } state = { state } onApply = { onClose } />
77+ < PickerForm
78+ { ...props }
79+ onApply = { ( ) => {
80+ onClose ( 'apply' ) ;
81+ } }
82+ />
8083 </ Popup >
8184 ) ;
8285}
83-
84- function DialogContent (
85- props : {
86- state : RelativeRangeDatePickerState ;
87- onApply : ( ) => void ;
88- } & RelativeRangeDatePickerProps ,
89- ) {
90- const state = useRelativeRangeDatePickerDialogState ( props . state , props ) ;
91-
92- const placeholderValue =
93- props . placeholderValue ?. timeZone ( props . state . timeZone ) ||
94- dateTime ( { timeZone : props . state . timeZone } ) ;
95- const fieldProps : RelativeDatePickerProps = {
96- timeZone : props . state . timeZone ,
97- format : props . format ,
98- minValue : props . minValue ,
99- maxValue : props . maxValue ,
100- hasClear : props . allowNullableValues ,
101- readOnly : props . readOnly ,
102- size : props . size ,
103- errorPlacement : 'inside' ,
104- } ;
105- return (
106- < div >
107- < div className = { b ( 'pickers' ) } >
108- < RelativeDatePicker
109- { ...fieldProps }
110- validationState = { state . startValidation ?. isInvalid ? 'invalid' : undefined }
111- errorMessage = {
112- state . startValidation ?. errors ?. join ( '\n' ) || i18n ( 'Value is incorrect.' )
113- }
114- placeholderValue = { placeholderValue . startOf ( 'day' ) }
115- label = { i18n ( 'From' ) }
116- value = { state . start }
117- onUpdate = { state . setStart }
118- />
119- < RelativeDatePicker
120- { ...fieldProps }
121- validationState = { state . endValidation ?. isInvalid ? 'invalid' : undefined }
122- errorMessage = {
123- state . endValidation ?. errors ?. join ( '\n' ) || i18n ( 'Value is incorrect.' )
124- }
125- placeholderValue = { placeholderValue . endOf ( 'day' ) }
126- label = { i18n ( 'To' ) }
127- value = { state . end }
128- onUpdate = { state . setEnd }
129- roundUp
130- />
131- </ div >
132- { props . withApplyButton && ! props . readOnly ? (
133- < Button
134- disabled = { state . isInvalid }
135- size = { props . size }
136- onClick = { ( ) => {
137- state . applyValue ( ) ;
138- props . onApply ( ) ;
139- } }
140- className = { b ( 'apply' ) }
141- width = "max"
142- >
143- { i18n ( 'Apply' ) }
144- </ Button >
145- ) : null }
146- { props . withPresets && ! props . readOnly ? (
147- < Presets
148- size = { props . size }
149- presetTabs = { props . presetTabs }
150- onChoosePreset = { ( start , end ) => {
151- state . setRange (
152- { type : 'relative' , value : start } ,
153- { type : 'relative' , value : end } ,
154- ) ;
155- if ( ! props . withApplyButton ) {
156- props . onApply ( ) ;
157- }
158- } }
159- minValue = { props . minValue }
160- docs = { props . docs }
161- className = { b ( 'presets' ) }
162- />
163- ) : null }
164- { props . withZonesList ? (
165- < div className = { b ( 'zone' ) } >
166- < Zones
167- value = { state . timeZone }
168- onUpdate = { state . setTimeZone }
169- disabled = { props . readOnly }
170- size = { props . size }
171- />
172- </ div >
173- ) : null }
174- </ div >
175- ) ;
176- }
0 commit comments