@wordpress/components 21.0.0 → 21.0.1

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.
Files changed (87) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/autocomplete/autocompleter-ui.js +3 -3
  3. package/build/autocomplete/autocompleter-ui.js.map +1 -1
  4. package/build/border-box-control/border-box-control/component.js +9 -10
  5. package/build/border-box-control/border-box-control/component.js.map +1 -1
  6. package/build/border-box-control/border-box-control-linked-button/component.js +1 -2
  7. package/build/border-box-control/border-box-control-linked-button/component.js.map +1 -1
  8. package/build/border-box-control/border-box-control-split-controls/component.js +9 -10
  9. package/build/border-box-control/border-box-control-split-controls/component.js.map +1 -1
  10. package/build/border-box-control/styles.js +7 -7
  11. package/build/border-box-control/styles.js.map +1 -1
  12. package/build/box-control/linked-button.js +3 -3
  13. package/build/box-control/linked-button.js.map +1 -1
  14. package/build/dropdown/index.js +11 -4
  15. package/build/dropdown/index.js.map +1 -1
  16. package/build/navigation/menu/menu-title-search.js +2 -1
  17. package/build/navigation/menu/menu-title-search.js.map +1 -1
  18. package/build/navigation/menu/use-navigation-tree-menu.js +2 -1
  19. package/build/navigation/menu/use-navigation-tree-menu.js.map +1 -1
  20. package/build/popover/index.js +39 -10
  21. package/build/popover/index.js.map +1 -1
  22. package/build/popover/utils.js +8 -2
  23. package/build/popover/utils.js.map +1 -1
  24. package/build/tooltip/index.js +8 -6
  25. package/build/tooltip/index.js.map +1 -1
  26. package/build-module/autocomplete/autocompleter-ui.js +4 -4
  27. package/build-module/autocomplete/autocompleter-ui.js.map +1 -1
  28. package/build-module/border-box-control/border-box-control/component.js +10 -11
  29. package/build-module/border-box-control/border-box-control/component.js.map +1 -1
  30. package/build-module/border-box-control/border-box-control-linked-button/component.js +1 -2
  31. package/build-module/border-box-control/border-box-control-linked-button/component.js.map +1 -1
  32. package/build-module/border-box-control/border-box-control-split-controls/component.js +10 -11
  33. package/build-module/border-box-control/border-box-control-split-controls/component.js.map +1 -1
  34. package/build-module/border-box-control/styles.js +7 -7
  35. package/build-module/border-box-control/styles.js.map +1 -1
  36. package/build-module/box-control/linked-button.js +3 -3
  37. package/build-module/box-control/linked-button.js.map +1 -1
  38. package/build-module/dropdown/index.js +10 -4
  39. package/build-module/dropdown/index.js.map +1 -1
  40. package/build-module/navigation/menu/menu-title-search.js +2 -1
  41. package/build-module/navigation/menu/menu-title-search.js.map +1 -1
  42. package/build-module/navigation/menu/use-navigation-tree-menu.js +2 -1
  43. package/build-module/navigation/menu/use-navigation-tree-menu.js.map +1 -1
  44. package/build-module/popover/index.js +39 -10
  45. package/build-module/popover/index.js.map +1 -1
  46. package/build-module/popover/utils.js +8 -2
  47. package/build-module/popover/utils.js.map +1 -1
  48. package/build-module/tooltip/index.js +9 -7
  49. package/build-module/tooltip/index.js.map +1 -1
  50. package/build-style/style-rtl.css +2 -3
  51. package/build-style/style.css +2 -3
  52. package/build-types/border-box-control/border-box-control/component.d.ts.map +1 -1
  53. package/build-types/border-box-control/border-box-control-linked-button/component.d.ts.map +1 -1
  54. package/build-types/border-box-control/border-box-control-split-controls/component.d.ts.map +1 -1
  55. package/build-types/border-box-control/styles.d.ts.map +1 -1
  56. package/build-types/dropdown/index.d.ts.map +1 -1
  57. package/build-types/popover/index.d.ts.map +1 -1
  58. package/build-types/popover/stories/index.d.ts.map +1 -1
  59. package/build-types/popover/types.d.ts +32 -14
  60. package/build-types/popover/types.d.ts.map +1 -1
  61. package/build-types/popover/utils.d.ts +2 -2
  62. package/build-types/popover/utils.d.ts.map +1 -1
  63. package/build-types/tooltip/index.d.ts.map +1 -1
  64. package/package.json +5 -5
  65. package/src/autocomplete/autocompleter-ui.js +6 -3
  66. package/src/border-box-control/border-box-control/component.tsx +28 -19
  67. package/src/border-box-control/border-box-control-linked-button/component.tsx +1 -2
  68. package/src/border-box-control/border-box-control-split-controls/component.tsx +25 -17
  69. package/src/border-box-control/stories/index.js +1 -0
  70. package/src/border-box-control/styles.ts +2 -1
  71. package/src/box-control/linked-button.js +3 -3
  72. package/src/box-control/test/index.js +5 -5
  73. package/src/button/style.scss +4 -3
  74. package/src/dropdown/index.js +15 -3
  75. package/src/modal/style.scss +3 -4
  76. package/src/navigation/menu/menu-title-search.js +2 -0
  77. package/src/navigation/menu/use-navigation-tree-menu.js +2 -0
  78. package/src/panel/README.md +1 -1
  79. package/src/popover/README.md +48 -3
  80. package/src/popover/index.tsx +41 -9
  81. package/src/popover/stories/index.tsx +1 -0
  82. package/src/popover/test/index.js +7 -5
  83. package/src/popover/types.ts +39 -20
  84. package/src/popover/utils.ts +16 -4
  85. package/src/tooltip/index.js +10 -6
  86. package/tsconfig.json +1 -0
  87. package/tsconfig.tsbuildinfo +1 -1
@@ -163,7 +163,6 @@ const UnforwardedPopover = (
163
163
  forwardedRef: ForwardedRef< any >
164
164
  ) => {
165
165
  const {
166
- range,
167
166
  animate = true,
168
167
  headerTitle,
169
168
  onClose,
@@ -175,22 +174,28 @@ const UnforwardedPopover = (
175
174
  placement: placementProp = 'bottom-start',
176
175
  offset: offsetProp = 0,
177
176
  focusOnMount = 'firstElement',
178
- anchorRef,
179
- anchorRect,
180
- getAnchorRect,
177
+ anchor,
181
178
  expandOnMobile,
182
179
  onFocusOutside,
183
180
  __unstableSlotName = SLOT_NAME,
184
181
  flip = true,
185
182
  resize = true,
186
183
  shift = false,
187
- __unstableShift,
184
+
185
+ // Deprecated props
188
186
  __unstableForcePosition,
187
+ __unstableShift,
188
+ anchorRef,
189
+ anchorRect,
190
+ getAnchorRect,
191
+ range,
192
+
193
+ // Rest
189
194
  ...contentProps
190
195
  } = props;
191
196
 
192
197
  if ( range ) {
193
- deprecated( 'range prop in Popover component', {
198
+ deprecated( '`range` prop in wp.components.Popover', {
194
199
  since: '6.1',
195
200
  version: '6.3',
196
201
  } );
@@ -199,7 +204,7 @@ const UnforwardedPopover = (
199
204
  let computedFlipProp = flip;
200
205
  let computedResizeProp = resize;
201
206
  if ( __unstableForcePosition !== undefined ) {
202
- deprecated( '__unstableForcePosition prop in Popover component', {
207
+ deprecated( '`__unstableForcePosition` prop wp.components.Popover', {
203
208
  since: '6.1',
204
209
  version: '6.3',
205
210
  alternative: '`flip={ false }` and `resize={ false }`',
@@ -213,7 +218,7 @@ const UnforwardedPopover = (
213
218
 
214
219
  let shouldShift = shift;
215
220
  if ( __unstableShift !== undefined ) {
216
- deprecated( '`__unstableShift` prop in Popover component', {
221
+ deprecated( '`__unstableShift` prop in wp.components.Popover', {
217
222
  since: '6.1',
218
223
  version: '6.3',
219
224
  alternative: '`shift` prop`',
@@ -223,6 +228,30 @@ const UnforwardedPopover = (
223
228
  shouldShift = __unstableShift;
224
229
  }
225
230
 
231
+ if ( anchorRef !== undefined ) {
232
+ deprecated( '`anchorRef` prop in wp.components.Popover', {
233
+ since: '6.1',
234
+ version: '6.3',
235
+ alternative: '`anchor` prop',
236
+ } );
237
+ }
238
+
239
+ if ( anchorRect !== undefined ) {
240
+ deprecated( '`anchorRect` prop in wp.components.Popover', {
241
+ since: '6.1',
242
+ version: '6.3',
243
+ alternative: '`anchor` prop',
244
+ } );
245
+ }
246
+
247
+ if ( getAnchorRect !== undefined ) {
248
+ deprecated( '`getAnchorRect` prop in wp.components.Popover', {
249
+ since: '6.1',
250
+ version: '6.3',
251
+ alternative: '`anchor` prop',
252
+ } );
253
+ }
254
+
226
255
  const arrowRef = useRef( null );
227
256
 
228
257
  const [ fallbackReferenceElement, setFallbackReferenceElement ] =
@@ -383,6 +412,7 @@ const UnforwardedPopover = (
383
412
  // recompute the reference element (real or virtual) and its owner document.
384
413
  useLayoutEffect( () => {
385
414
  const resultingReferenceOwnerDoc = getReferenceOwnerDocument( {
415
+ anchor,
386
416
  anchorRef,
387
417
  anchorRect,
388
418
  getAnchorRect,
@@ -390,6 +420,7 @@ const UnforwardedPopover = (
390
420
  fallbackDocument: document,
391
421
  } );
392
422
  const resultingReferenceElement = getReferenceElement( {
423
+ anchor,
393
424
  anchorRef,
394
425
  anchorRect,
395
426
  getAnchorRect,
@@ -400,6 +431,7 @@ const UnforwardedPopover = (
400
431
 
401
432
  setReferenceOwnerDocument( resultingReferenceOwnerDoc );
402
433
  }, [
434
+ anchor,
403
435
  anchorRef as Element | undefined,
404
436
  ( anchorRef as PopoverAnchorRefTopBottom | undefined )?.top,
405
437
  ( anchorRef as PopoverAnchorRefTopBottom | undefined )?.bottom,
@@ -527,7 +559,7 @@ const UnforwardedPopover = (
527
559
  content = <Fill name={ slotName }>{ content }</Fill>;
528
560
  }
529
561
 
530
- if ( anchorRef || anchorRect ) {
562
+ if ( anchorRef || anchorRect || anchor ) {
531
563
  return content;
532
564
  }
533
565
 
@@ -37,6 +37,7 @@ const meta: ComponentMeta< typeof Popover > = {
37
37
  title: 'Components/Popover',
38
38
  component: Popover,
39
39
  argTypes: {
40
+ anchor: { control: { type: null } },
40
41
  anchorRef: { control: { type: null } },
41
42
  anchorRect: { control: { type: null } },
42
43
  children: { control: { type: null } },
@@ -6,7 +6,7 @@ import { act, render, screen } from '@testing-library/react';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { useRef } from '@wordpress/element';
9
+ import { useState } from '@wordpress/element';
10
10
 
11
11
  /**
12
12
  * Internal dependencies
@@ -57,14 +57,16 @@ describe( 'Popover', () => {
57
57
  ).toMatchSnapshot();
58
58
  } );
59
59
 
60
- it( 'should render correctly when anchorRef is provided', () => {
60
+ it( 'should render correctly when anchor is provided', () => {
61
61
  const PopoverWithAnchor = ( args ) => {
62
- const anchorRef = useRef( null );
62
+ // Use internal state instead of a ref to make sure that the component
63
+ // re-renders when the popover's anchor updates.
64
+ const [ anchor, setAnchor ] = useState( null );
63
65
 
64
66
  return (
65
67
  <div>
66
- <p ref={ anchorRef }>Anchor</p>
67
- <Popover { ...args } anchorRef={ anchorRef } />
68
+ <p ref={ setAnchor }>Anchor</p>
69
+ <Popover { ...args } anchor={ anchor } />
68
70
  </div>
69
71
  );
70
72
  };
@@ -22,6 +22,10 @@ export type PopoverAnchorRefReference = MutableRefObject<
22
22
  >;
23
23
  export type PopoverAnchorRefTopBottom = { top: Element; bottom: Element };
24
24
 
25
+ export type VirtualElement = Pick< Element, 'getBoundingClientRect' > & {
26
+ ownerDocument?: Document;
27
+ };
28
+
25
29
  export type PopoverProps = {
26
30
  /**
27
31
  * The name of the Slot in which the popover should be rendered. It should
@@ -31,20 +35,14 @@ export type PopoverProps = {
31
35
  */
32
36
  __unstableSlotName?: string;
33
37
  /**
34
- * An object extending a `DOMRect` with an additional optional `ownerDocument`
35
- * property, used to specify a fixed popover position.
36
- */
37
- anchorRect?: DomRectWithOwnerDocument;
38
- /**
39
- * Used to specify a fixed popover position. It can be an `Element`, a React
40
- * reference to an `element`, an object with a `top` and a `bottom` properties
41
- * (both pointing to elements), or a `range`.
38
+ * The element that should be used by the popover as its anchor. It can either
39
+ * be an `Element` or, alternatively, a `VirtualElement` ie. an object with
40
+ * the `getBoundingClientRect()` and the `ownerDocument` properties defined.
41
+ *
42
+ * **The anchor element should be stored in local state** rather than a
43
+ * plain React ref to ensure reactive updating when it changes.
42
44
  */
43
- anchorRef?:
44
- | Element
45
- | PopoverAnchorRefReference
46
- | PopoverAnchorRefTopBottom
47
- | Range;
45
+ anchor?: Element | VirtualElement | null;
48
46
  /**
49
47
  * Whether the popover should animate when opening.
50
48
  *
@@ -89,13 +87,6 @@ export type PopoverProps = {
89
87
  * When not provided, the `onClose` callback will be called instead.
90
88
  */
91
89
  onFocusOutside?: ( event: SyntheticEvent ) => void;
92
- /**
93
- * A function returning the same value as the one expected by the `anchorRect`
94
- * prop, used to specify a dynamic popover position.
95
- */
96
- getAnchorRect?: (
97
- fallbackReferenceElement: Element | null
98
- ) => DomRectWithOwnerDocument;
99
90
  /**
100
91
  * Used to customize the header text shown when the popover is toggled to
101
92
  * fullscreen on mobile viewports (see the `expandOnMobile` prop).
@@ -164,6 +155,34 @@ export type PopoverProps = {
164
155
  * @deprecated
165
156
  */
166
157
  __unstableShift?: boolean;
158
+ /**
159
+ * An object extending a `DOMRect` with an additional optional `ownerDocument`
160
+ * property, used to specify a fixed popover position.
161
+ *
162
+ * @deprecated
163
+ */
164
+ anchorRect?: DomRectWithOwnerDocument;
165
+ /**
166
+ * Used to specify a fixed popover position. It can be an `Element`, a React
167
+ * reference to an `element`, an object with a `top` and a `bottom` properties
168
+ * (both pointing to elements), or a `range`.
169
+ *
170
+ * @deprecated
171
+ */
172
+ anchorRef?:
173
+ | Element
174
+ | PopoverAnchorRefReference
175
+ | PopoverAnchorRefTopBottom
176
+ | Range;
177
+ /**
178
+ * A function returning the same value as the one expected by the `anchorRect`
179
+ * prop, used to specify a dynamic popover position.
180
+ *
181
+ * @deprecated
182
+ */
183
+ getAnchorRect?: (
184
+ fallbackReferenceElement: Element | null
185
+ ) => DomRectWithOwnerDocument;
167
186
  /**
168
187
  * _Note: this prop is deprecated and has no effect on the component._
169
188
  *
@@ -116,12 +116,16 @@ export const getFrameOffset = (
116
116
  };
117
117
 
118
118
  export const getReferenceOwnerDocument = ( {
119
+ anchor,
119
120
  anchorRef,
120
121
  anchorRect,
121
122
  getAnchorRect,
122
123
  fallbackReferenceElement,
123
124
  fallbackDocument,
124
- }: Pick< PopoverProps, 'anchorRef' | 'anchorRect' | 'getAnchorRect' > & {
125
+ }: Pick<
126
+ PopoverProps,
127
+ 'anchorRef' | 'anchorRect' | 'getAnchorRect' | 'anchor'
128
+ > & {
125
129
  fallbackReferenceElement: Element | null;
126
130
  fallbackDocument: Document;
127
131
  } ): Document => {
@@ -133,7 +137,9 @@ export const getReferenceOwnerDocument = ( {
133
137
  // with the `getBoundingClientRect()` function (like real elements).
134
138
  // See https://floating-ui.com/docs/virtual-elements for more info.
135
139
  let resultingReferenceOwnerDoc;
136
- if ( ( anchorRef as PopoverAnchorRefTopBottom | undefined )?.top ) {
140
+ if ( anchor ) {
141
+ resultingReferenceOwnerDoc = anchor.ownerDocument;
142
+ } else if ( ( anchorRef as PopoverAnchorRefTopBottom | undefined )?.top ) {
137
143
  resultingReferenceOwnerDoc = ( anchorRef as PopoverAnchorRefTopBottom )
138
144
  ?.top.ownerDocument;
139
145
  } else if ( ( anchorRef as Range | undefined )?.startContainer ) {
@@ -160,16 +166,22 @@ export const getReferenceOwnerDocument = ( {
160
166
  };
161
167
 
162
168
  export const getReferenceElement = ( {
169
+ anchor,
163
170
  anchorRef,
164
171
  anchorRect,
165
172
  getAnchorRect,
166
173
  fallbackReferenceElement,
167
- }: Pick< PopoverProps, 'anchorRef' | 'anchorRect' | 'getAnchorRect' > & {
174
+ }: Pick<
175
+ PopoverProps,
176
+ 'anchorRef' | 'anchorRect' | 'getAnchorRect' | 'anchor'
177
+ > & {
168
178
  fallbackReferenceElement: Element | null;
169
179
  } ): ReferenceType | null => {
170
180
  let referenceElement = null;
171
181
 
172
- if ( ( anchorRef as PopoverAnchorRefTopBottom | undefined )?.top ) {
182
+ if ( anchor ) {
183
+ referenceElement = anchor;
184
+ } else if ( ( anchorRef as PopoverAnchorRefTopBottom | undefined )?.top ) {
173
185
  // Create a virtual element for the ref. The expectation is that
174
186
  // if anchorRef.top is defined, then anchorRef.bottom is defined too.
175
187
  // Seems to be used by the block toolbar, when multiple blocks are selected
@@ -9,7 +9,6 @@ import {
9
9
  concatChildren,
10
10
  useEffect,
11
11
  useState,
12
- useRef,
13
12
  } from '@wordpress/element';
14
13
  import { useDebounce, useMergeRefs } from '@wordpress/compose';
15
14
 
@@ -60,7 +59,7 @@ const getRegularElement = ( {
60
59
  };
61
60
 
62
61
  const addPopoverToGrandchildren = ( {
63
- anchorRef,
62
+ anchor,
64
63
  grandchildren,
65
64
  isOver,
66
65
  offset,
@@ -78,7 +77,7 @@ const addPopoverToGrandchildren = ( {
78
77
  aria-hidden="true"
79
78
  animate={ false }
80
79
  offset={ offset }
81
- anchorRef={ anchorRef }
80
+ anchor={ anchor }
82
81
  shift
83
82
  >
84
83
  { text }
@@ -124,13 +123,18 @@ function Tooltip( props ) {
124
123
  const [ isMouseDown, setIsMouseDown ] = useState( false );
125
124
  const [ isOver, setIsOver ] = useState( false );
126
125
  const delayedSetIsOver = useDebounce( setIsOver, delay );
126
+ // Using internal state (instead of a ref) for the popover anchor to make sure
127
+ // that the component re-renders when the anchor updates.
128
+ const [ popoverAnchor, setPopoverAnchor ] = useState( null );
127
129
 
128
130
  // Create a reference to the Tooltip's child, to be passed to the Popover
129
131
  // so that the Tooltip can be correctly positioned. Also, merge with the
130
132
  // existing ref for the first child, so that its ref is preserved.
131
- const childRef = useRef( null );
132
133
  const existingChildRef = Children.toArray( children )[ 0 ]?.ref;
133
- const mergedChildRefs = useMergeRefs( [ childRef, existingChildRef ] );
134
+ const mergedChildRefs = useMergeRefs( [
135
+ setPopoverAnchor,
136
+ existingChildRef,
137
+ ] );
134
138
 
135
139
  const createMouseDown = ( event ) => {
136
140
  // In firefox, the mouse down event is also fired when the select
@@ -253,7 +257,7 @@ function Tooltip( props ) {
253
257
  : getRegularElement;
254
258
 
255
259
  const popoverData = {
256
- anchorRef: childRef,
260
+ anchor: popoverAnchor,
257
261
  isOver,
258
262
  offset: 4,
259
263
  position,
package/tsconfig.json CHANGED
@@ -18,6 +18,7 @@
18
18
  "strictNullChecks": true
19
19
  },
20
20
  "references": [
21
+ { "path": "../a11y" },
21
22
  { "path": "../compose" },
22
23
  { "path": "../date" },
23
24
  { "path": "../deprecated" },