@@ -41,6 +41,17 @@ export class CalendarPropsBuilder {
4141 private readonly minTime : Date ;
4242 private readonly maxTime : Date ;
4343
44+ // Keeps the currently focused/selected event. Updated on every selection.
45+ private selectedEvent ?: CalendarEvent ;
46+ /**
47+ * Stores the event that should be ignored on the next onSelectEvent call.
48+ * This is set when a double-click is detected so we can ignore the
49+ * secondary click that React-Big-Calendar dispatches as part of the same
50+ * interaction. After the click has been ignored, the field is cleared so
51+ * that future selections are handled normally.
52+ */
53+ private ignoreNextClickFor ?: CalendarEvent ;
54+
4455 constructor ( private props : CalendarContainerProps ) {
4556 this . isCustomView = props . view === "custom" ;
4657 this . defaultView = this . isCustomView ? props . defaultViewCustom : props . defaultViewStandard ;
@@ -75,10 +86,14 @@ export class CalendarPropsBuilder {
7586 allDayAccessor : ( event : CalendarEvent ) => event . allDay ,
7687 endAccessor : ( event : CalendarEvent ) => event . end ,
7788 eventPropGetter,
89+ // @ts -expect-error – navigatable prop not yet in typings but exists in runtime component
90+ navigatable : true ,
7891 onEventDrop : this . handleEventDropOrResize ,
7992 onEventResize : this . handleEventDropOrResize ,
8093 onNavigate : this . handleRangeChange ,
81- onSelectEvent : this . handleEditEvent ,
94+ onSelectEvent : this . handleSelectEvent ,
95+ onDoubleClickEvent : this . handleDoubleClickEvent ,
96+ onKeyPressEvent : this . handleKeyPressEvent ,
8297 onSelectSlot : this . handleCreateEvent ,
8398 startAccessor : ( event : CalendarEvent ) => event . start ,
8499 titleAccessor : ( event : CalendarEvent ) => event . title ,
@@ -197,13 +212,51 @@ export class CalendarPropsBuilder {
197212 }
198213 } ;
199214
200- private handleEditEvent = ( event : CalendarEvent ) : void => {
215+ /**
216+ * Called when an event is single-clicked (selected).
217+ * First click only stores the selection; a consecutive click on the same event triggers edit.
218+ */
219+ private handleSelectEvent = ( event : CalendarEvent ) : void => {
220+ if ( this . ignoreNextClickFor === event ) {
221+ // Skip this click – it belongs to a double-click we've already handled.
222+ this . ignoreNextClickFor = undefined ;
223+ return ;
224+ }
225+
226+ if ( this . selectedEvent === event ) {
227+ // Second click on the already-selected event => open edit panel.
228+ this . invokeEdit ( event ) ;
229+ } else {
230+ // Update current selection.
231+ this . selectedEvent = event ;
232+ }
233+ } ;
234+
235+ /**
236+ * Fast double click should open edit immediately.
237+ */
238+ private handleDoubleClickEvent = ( event : CalendarEvent ) : void => {
239+ // Open edit immediately & prevent the subsequent single-click handler from firing edit again.
240+ this . invokeEdit ( event ) ;
241+ this . ignoreNextClickFor = event ;
242+ } ;
243+
244+ /**
245+ * When the event has focus, pressing Enter should open edit.
246+ */
247+ private handleKeyPressEvent = ( event : CalendarEvent , e : any ) : void => {
248+ if ( e . key === "Enter" ) {
249+ this . invokeEdit ( event ) ;
250+ }
251+ } ;
252+
253+ private invokeEdit ( event : CalendarEvent ) : void {
201254 const action = this . props . onEditEvent ?. get ( event . item ) ;
202255
203256 if ( action ?. canExecute ) {
204257 action . execute ( ) ;
205258 }
206- } ;
259+ }
207260
208261 private handleCreateEvent = ( slotInfo : { start : Date ; end : Date ; action : string } ) : void => {
209262 const action = this . props . onCreateEvent ;
0 commit comments