@wordpress/editor 14.33.8 → 14.33.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -381,9 +381,16 @@ export function Comments( {
381
381
  };
382
382
 
383
383
  const hasThreads = Array.isArray( threads ) && threads.length > 0;
384
- // This should no longer happen since https://github.com/WordPress/gutenberg/pull/72872.
384
+ // A special case for `template-locked` mode - https://github.com/WordPress/gutenberg/pull/72646.
385
385
  if ( ! hasThreads && ! isFloating ) {
386
- return null;
386
+ return (
387
+ <AddComment
388
+ onSubmit={ onAddReply }
389
+ newNoteFormState={ newNoteFormState }
390
+ setNewNoteFormState={ setNewNoteFormState }
391
+ commentSidebarRef={ commentSidebarRef }
392
+ />
393
+ );
387
394
  }
388
395
 
389
396
  return (
@@ -463,6 +470,7 @@ function Thread( {
463
470
  selectedThread,
464
471
  commentLastUpdated,
465
472
  } );
473
+ const isKeyboardTabbingRef = useRef( false );
466
474
 
467
475
  const onMouseEnter = () => {
468
476
  debouncedToggleBlockHighlight( thread.blockClientId, true );
@@ -472,13 +480,48 @@ function Thread( {
472
480
  debouncedToggleBlockHighlight( thread.blockClientId, false );
473
481
  };
474
482
 
483
+ const onFocus = () => {
484
+ toggleBlockHighlight( thread.blockClientId, true );
485
+ };
486
+
487
+ const onBlur = ( event ) => {
488
+ const isNoteFocused = event.relatedTarget?.closest(
489
+ '.editor-collab-sidebar-panel__thread'
490
+ );
491
+ const isDialogFocused =
492
+ event.relatedTarget?.closest( '[role="dialog"]' );
493
+ const isTabbing = isKeyboardTabbingRef.current;
494
+
495
+ // When another note is clicked, do nothing because the current note is automatically closed.
496
+ if ( isNoteFocused && ! isTabbing ) {
497
+ return;
498
+ }
499
+ // When deleting a note, a dialog appears, but the note should not be collapsed.
500
+ if ( isDialogFocused ) {
501
+ return;
502
+ }
503
+ // When tabbing, do nothing if the focus is within the current note.
504
+ if (
505
+ isTabbing &&
506
+ event.currentTarget.contains( event.relatedTarget )
507
+ ) {
508
+ return;
509
+ }
510
+
511
+ // Closes a note that has lost focus when any of the following conditions are met:
512
+ // - An element other than a note is clicked.
513
+ // - Focus was lost by tabbing.
514
+ toggleBlockHighlight( thread.blockClientId, false );
515
+ unselectThread();
516
+ };
517
+
475
518
  const handleCommentSelect = () => {
476
519
  setNewNoteFormState( 'closed' );
477
520
  setSelectedThread( thread.id );
521
+ toggleBlockSpotlight( thread.blockClientId, true );
478
522
  if ( !! thread.blockClientId ) {
479
523
  // Pass `null` as the second parameter to prevent focusing the block.
480
524
  selectBlock( thread.blockClientId, null );
481
- toggleBlockSpotlight( thread.blockClientId, true );
482
525
  }
483
526
  };
484
527
 
@@ -540,9 +583,20 @@ function Thread( {
540
583
  onClick={ handleCommentSelect }
541
584
  onMouseEnter={ onMouseEnter }
542
585
  onMouseLeave={ onMouseLeave }
543
- onFocus={ onMouseEnter }
544
- onBlur={ onMouseLeave }
545
- onKeyDown={ onKeyDown }
586
+ onFocus={ onFocus }
587
+ onBlur={ onBlur }
588
+ onKeyUp={ ( event ) => {
589
+ if ( event.key === 'Tab' ) {
590
+ isKeyboardTabbingRef.current = false;
591
+ }
592
+ } }
593
+ onKeyDown={ ( event ) => {
594
+ if ( event.key === 'Tab' ) {
595
+ isKeyboardTabbingRef.current = true;
596
+ } else {
597
+ onKeyDown( event );
598
+ }
599
+ } }
546
600
  tabIndex={ 0 }
547
601
  role="treeitem"
548
602
  aria-label={ ariaLabel }
@@ -562,7 +616,7 @@ function Thread( {
562
616
  );
563
617
  } }
564
618
  >
565
- { __( 'Add new note' ) }
619
+ { __( 'Add new reply' ) }
566
620
  </Button>
567
621
  { ! thread.blockClientId && (
568
622
  <Text as="p" weight={ 500 } variant="muted">
@@ -767,6 +821,14 @@ const CommentBoard = ( {
767
821
  ? actions.filter( ( item ) => item.isEligible( thread ) )
768
822
  : [];
769
823
 
824
+ const deleteConfirmMessage =
825
+ // When deleting a top level note, descendants will also be deleted.
826
+ thread.parent === 0
827
+ ? __(
828
+ "Are you sure you want to delete this note? This will also delete all of this note's replies."
829
+ )
830
+ : __( 'Are you sure you want to delete this reply?' );
831
+
770
832
  return (
771
833
  <VStack
772
834
  spacing="2"
@@ -821,7 +883,12 @@ const CommentBoard = ( {
821
883
  />
822
884
  }
823
885
  />
824
- <Menu.Popover>
886
+ <Menu.Popover
887
+ // The menu popover is rendered in a portal, which causes focus to be
888
+ // lost and the note to be collapsed unintentionally. To prevent this,
889
+ // the popover should be rendered as an inline.
890
+ modal={ false }
891
+ >
825
892
  { moreActions.map( ( action ) => (
826
893
  <Menu.Item
827
894
  key={ action.id }
@@ -902,9 +969,7 @@ const CommentBoard = ( {
902
969
  onCancel={ handleCancel }
903
970
  confirmButtonText={ __( 'Delete' ) }
904
971
  >
905
- { __(
906
- "Are you sure you want to delete this note? This will also delete all of this note's replies."
907
- ) }
972
+ { deleteConfirmMessage }
908
973
  </ConfirmDialog>
909
974
  ) }
910
975
  </VStack>
@@ -6,14 +6,10 @@ import { createHigherOrderComponent } from '@wordpress/compose';
6
6
  import { useCallback } from '@wordpress/element';
7
7
  import { __ } from '@wordpress/i18n';
8
8
  import {
9
- BlockControls,
9
+ __unstableBlockToolbarLastItem as BlockToolbarLastItem,
10
10
  store as blockEditorStore,
11
11
  } from '@wordpress/block-editor';
12
- import {
13
- ToolbarButton,
14
- ToolbarGroup,
15
- __experimentalDivider as Divider,
16
- } from '@wordpress/components';
12
+ import { ToolbarButton, ToolbarGroup } from '@wordpress/components';
17
13
  import { useSelect, useDispatch } from '@wordpress/data';
18
14
  import { store as interfaceStore } from '@wordpress/interface';
19
15
 
@@ -96,15 +92,8 @@ function TemplatePartNavigationEditButton( { clientId } ) {
96
92
  }
97
93
 
98
94
  return (
99
- <BlockControls group="other">
95
+ <BlockToolbarLastItem>
100
96
  <ToolbarGroup>
101
- { /*
102
- * Add a vertical divider to visually separate the "Edit navigation"
103
- * button from the template part's "Edit" button. Both buttons share
104
- * the same toolbar group ("other"), so without this divider they
105
- * would appear directly adjacent with no visual separation.
106
- */ }
107
- <Divider orientation="vertical" marginEnd={ 3 } />
108
97
  <ToolbarButton
109
98
  label={ __( 'Edit navigation' ) }
110
99
  onClick={ onEditNavigation }
@@ -112,7 +101,7 @@ function TemplatePartNavigationEditButton( { clientId } ) {
112
101
  { __( 'Edit navigation' ) }
113
102
  </ToolbarButton>
114
103
  </ToolbarGroup>
115
- </BlockControls>
104
+ </BlockToolbarLastItem>
116
105
  );
117
106
  }
118
107