@wordpress/components 23.0.0 → 23.1.0
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.
- package/CHANGELOG.md +10 -0
- package/CONTRIBUTING.md +0 -21
- package/build/autocomplete/index.js +1 -3
- package/build/autocomplete/index.js.map +1 -1
- package/build/border-box-control/border-box-control/component.js +0 -3
- package/build/border-box-control/border-box-control/component.js.map +1 -1
- package/build/border-box-control/border-box-control/hook.js +0 -2
- package/build/border-box-control/border-box-control/hook.js.map +1 -1
- package/build/border-box-control/border-box-control-split-controls/component.js +0 -2
- package/build/border-box-control/border-box-control-split-controls/component.js.map +1 -1
- package/build/border-box-control/border-box-control-split-controls/hook.js +0 -2
- package/build/border-box-control/border-box-control-split-controls/hook.js.map +1 -1
- package/build/border-control/border-control/component.js +0 -2
- package/build/border-control/border-control/component.js.map +1 -1
- package/build/border-control/border-control/hook.js +0 -2
- package/build/border-control/border-control/hook.js.map +1 -1
- package/build/border-control/border-control-dropdown/component.js +6 -11
- package/build/border-control/border-control-dropdown/component.js.map +1 -1
- package/build/border-control/border-control-dropdown/hook.js +0 -2
- package/build/border-control/border-control-dropdown/hook.js.map +1 -1
- package/build/color-palette/index.js +5 -8
- package/build/color-palette/index.js.map +1 -1
- package/build/dimension-control/index.js.map +1 -1
- package/build/dropdown/index.js +45 -10
- package/build/dropdown/index.js.map +1 -1
- package/build/gradient-picker/index.js +1 -2
- package/build/gradient-picker/index.js.map +1 -1
- package/build/higher-order/navigate-regions/index.js +4 -3
- package/build/higher-order/navigate-regions/index.js.map +1 -1
- package/build/index.js +0 -8
- package/build/index.js.map +1 -1
- package/build/mobile/bottom-sheet/picker-cell.native.js +1 -9
- package/build/mobile/bottom-sheet/picker-cell.native.js.map +1 -1
- package/build/mobile/global-styles-context/utils.native.js +30 -12
- package/build/mobile/global-styles-context/utils.native.js.map +1 -1
- package/build/tab-panel/index.js +5 -4
- package/build/tab-panel/index.js.map +1 -1
- package/build-module/autocomplete/index.js +1 -2
- package/build-module/autocomplete/index.js.map +1 -1
- package/build-module/border-box-control/border-box-control/component.js +0 -3
- package/build-module/border-box-control/border-box-control/component.js.map +1 -1
- package/build-module/border-box-control/border-box-control/hook.js +0 -2
- package/build-module/border-box-control/border-box-control/hook.js.map +1 -1
- package/build-module/border-box-control/border-box-control-split-controls/component.js +0 -2
- package/build-module/border-box-control/border-box-control-split-controls/component.js.map +1 -1
- package/build-module/border-box-control/border-box-control-split-controls/hook.js +0 -2
- package/build-module/border-box-control/border-box-control-split-controls/hook.js.map +1 -1
- package/build-module/border-control/border-control/component.js +0 -2
- package/build-module/border-control/border-control/component.js.map +1 -1
- package/build-module/border-control/border-control/hook.js +0 -2
- package/build-module/border-control/border-control/hook.js.map +1 -1
- package/build-module/border-control/border-control-dropdown/component.js +6 -11
- package/build-module/border-control/border-control-dropdown/component.js.map +1 -1
- package/build-module/border-control/border-control-dropdown/hook.js +0 -2
- package/build-module/border-control/border-control-dropdown/hook.js.map +1 -1
- package/build-module/color-palette/index.js +5 -8
- package/build-module/color-palette/index.js.map +1 -1
- package/build-module/dimension-control/index.js +1 -2
- package/build-module/dimension-control/index.js.map +1 -1
- package/build-module/dropdown/index.js +44 -10
- package/build-module/dropdown/index.js.map +1 -1
- package/build-module/gradient-picker/index.js +1 -2
- package/build-module/gradient-picker/index.js.map +1 -1
- package/build-module/higher-order/navigate-regions/index.js +4 -3
- package/build-module/higher-order/navigate-regions/index.js.map +1 -1
- package/build-module/index.js +0 -1
- package/build-module/index.js.map +1 -1
- package/build-module/mobile/bottom-sheet/picker-cell.native.js +1 -8
- package/build-module/mobile/bottom-sheet/picker-cell.native.js.map +1 -1
- package/build-module/mobile/global-styles-context/utils.native.js +31 -13
- package/build-module/mobile/global-styles-context/utils.native.js.map +1 -1
- package/build-module/tab-panel/index.js +5 -3
- package/build-module/tab-panel/index.js.map +1 -1
- package/build-style/style-rtl.css +18 -31
- package/build-style/style.css +18 -31
- package/build-types/border-box-control/border-box-control/component.d.ts +1 -1
- package/build-types/border-box-control/border-box-control/component.d.ts.map +1 -1
- package/build-types/border-box-control/border-box-control/hook.d.ts +0 -1
- package/build-types/border-box-control/border-box-control/hook.d.ts.map +1 -1
- package/build-types/border-box-control/border-box-control-split-controls/component.d.ts +1 -1
- package/build-types/border-box-control/border-box-control-split-controls/component.d.ts.map +1 -1
- package/build-types/border-box-control/border-box-control-split-controls/hook.d.ts +0 -1
- package/build-types/border-box-control/border-box-control-split-controls/hook.d.ts.map +1 -1
- package/build-types/border-box-control/stories/index.d.ts +1 -1
- package/build-types/border-control/border-control/component.d.ts +1 -1
- package/build-types/border-control/border-control/component.d.ts.map +1 -1
- package/build-types/border-control/border-control/hook.d.ts +0 -1
- package/build-types/border-control/border-control/hook.d.ts.map +1 -1
- package/build-types/border-control/border-control-dropdown/component.d.ts +1 -1
- package/build-types/border-control/border-control-dropdown/component.d.ts.map +1 -1
- package/build-types/border-control/border-control-dropdown/hook.d.ts +0 -1
- package/build-types/border-control/border-control-dropdown/hook.d.ts.map +1 -1
- package/build-types/border-control/stories/index.d.ts +6 -6
- package/build-types/border-control/stories/index.d.ts.map +1 -1
- package/build-types/border-control/types.d.ts +1 -1
- package/build-types/border-control/types.d.ts.map +1 -1
- package/build-types/color-palette/index.d.ts +2 -3
- package/build-types/color-palette/index.d.ts.map +1 -1
- package/build-types/color-palette/stories/index.d.ts +2 -9
- package/build-types/color-palette/stories/index.d.ts.map +1 -1
- package/build-types/color-palette/types.d.ts +3 -16
- package/build-types/color-palette/types.d.ts.map +1 -1
- package/build-types/disabled/stories/index.d.ts.map +1 -1
- package/build-types/dropdown/index.d.ts +29 -1
- package/build-types/dropdown/index.d.ts.map +1 -1
- package/build-types/dropdown/stories/index.d.ts +23 -0
- package/build-types/dropdown/stories/index.d.ts.map +1 -0
- package/build-types/dropdown/test/index.d.ts +2 -0
- package/build-types/dropdown/test/index.d.ts.map +1 -0
- package/build-types/dropdown/types.d.ts +101 -0
- package/build-types/dropdown/types.d.ts.map +1 -1
- package/build-types/icon/stories/index.d.ts +22 -0
- package/build-types/icon/stories/index.d.ts.map +1 -0
- package/build-types/tab-panel/index.d.ts.map +1 -1
- package/package.json +17 -17
- package/src/autocomplete/index.js +1 -3
- package/src/autocomplete/test/index.js +2 -0
- package/src/base-control/test/index.tsx +1 -0
- package/src/border-box-control/border-box-control/component.tsx +0 -7
- package/src/border-box-control/border-box-control/hook.ts +0 -2
- package/src/border-box-control/border-box-control-split-controls/component.tsx +0 -2
- package/src/border-box-control/border-box-control-split-controls/hook.ts +0 -2
- package/src/border-box-control/test/index.js +2 -0
- package/src/border-control/border-control/component.tsx +0 -4
- package/src/border-control/border-control/hook.ts +0 -2
- package/src/border-control/border-control-dropdown/component.tsx +11 -17
- package/src/border-control/border-control-dropdown/hook.ts +0 -2
- package/src/border-control/stories/index.tsx +0 -1
- package/src/border-control/test/index.js +70 -67
- package/src/border-control/types.ts +1 -4
- package/src/box-control/test/index.js +2 -0
- package/src/checkbox-control/test/index.tsx +2 -0
- package/src/color-palette/index.tsx +12 -12
- package/src/color-palette/stories/index.tsx +0 -13
- package/src/color-palette/test/index.tsx +2 -0
- package/src/color-palette/types.ts +3 -17
- package/src/color-picker/test/index.js +2 -0
- package/src/combobox-control/test/index.js +2 -0
- package/src/confirm-dialog/test/index.js +2 -0
- package/src/date-time/date/test/index.tsx +2 -0
- package/src/date-time/time/test/index.tsx +2 -0
- package/src/dimension-control/index.js +2 -3
- package/src/dimension-control/test/index.test.js +2 -0
- package/src/disabled/stories/index.tsx +6 -2
- package/src/disabled/test/index.tsx +2 -0
- package/src/dropdown/README.md +41 -46
- package/src/dropdown/{index.js → index.tsx} +57 -13
- package/src/dropdown/stories/{index.js → index.tsx} +21 -8
- package/src/dropdown/test/{index.js → index.tsx} +9 -9
- package/src/dropdown/types.ts +107 -0
- package/src/dropdown-menu/README.md +2 -3
- package/src/dropdown-menu/test/index.js +2 -0
- package/src/external-link/test/index.tsx +2 -0
- package/src/focal-point-picker/test/index.js +2 -0
- package/src/font-size-picker/test/index.tsx +2 -0
- package/src/form-file-upload/test/index.tsx +2 -0
- package/src/form-toggle/test/index.tsx +2 -0
- package/src/form-token-field/test/index.tsx +3 -0
- package/src/gradient-picker/index.js +1 -2
- package/src/gradient-picker/stories/index.js +0 -1
- package/src/guide/test/index.js +2 -0
- package/src/higher-order/navigate-regions/index.js +5 -2
- package/src/higher-order/navigate-regions/style.scss +13 -39
- package/src/higher-order/with-filters/test/index.js +70 -74
- package/src/higher-order/with-focus-outside/test/index.js +2 -0
- package/src/higher-order/with-focus-return/test/index.js +2 -0
- package/src/higher-order/with-notices/test/index.js +1 -0
- package/src/icon/stories/index.tsx +103 -0
- package/src/index.js +0 -1
- package/src/input-control/test/index.js +3 -0
- package/src/isolated-event-container/test/index.js +2 -0
- package/src/mobile/bottom-sheet/picker-cell.native.js +1 -6
- package/src/mobile/global-styles-context/utils.native.js +17 -16
- package/src/modal/test/index.tsx +1 -3
- package/src/navigable-container/test/navigable-menu.js +2 -0
- package/src/navigable-container/test/tababble-container.js +2 -0
- package/src/navigation/test/index.js +2 -0
- package/src/navigator/test/index.tsx +2 -0
- package/src/notice/test/index.js +8 -3
- package/src/number-control/test/index.tsx +2 -0
- package/src/panel/test/__snapshots__/body.js.snap +9 -0
- package/src/panel/test/body.js +71 -62
- package/src/placeholder/test/index.tsx +3 -0
- package/src/select-control/test/select-control.tsx +2 -0
- package/src/tab-panel/index.tsx +1 -2
- package/src/tab-panel/test/index.tsx +2 -0
- package/src/text-highlight/test/index.tsx +1 -0
- package/src/toggle-group-control/test/index.tsx +2 -0
- package/src/toolbar/style.scss +1 -1
- package/src/toolbar-group/test/index.js +2 -0
- package/src/tooltip/stories/index.js +68 -78
- package/src/tooltip/test/index.js +2 -0
- package/src/unit-control/test/index.tsx +3 -0
- package/src/utils/hooks/test/use-latest-ref.js +2 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/src/icon/stories/index.js +0 -128
package/src/dropdown/types.ts
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import type Popover from '../popover';
|
|
10
|
+
import type { PopoverProps } from '../popover/types';
|
|
11
|
+
|
|
12
|
+
type CallbackProps = {
|
|
13
|
+
isOpen: boolean;
|
|
14
|
+
onToggle: () => void;
|
|
15
|
+
onClose: () => void;
|
|
16
|
+
};
|
|
17
|
+
|
|
1
18
|
export type DropdownContentWrapperProps = {
|
|
2
19
|
/**
|
|
3
20
|
* Amount of padding to apply on the dropdown content.
|
|
@@ -6,3 +23,93 @@ export type DropdownContentWrapperProps = {
|
|
|
6
23
|
*/
|
|
7
24
|
paddingSize?: 'none' | 'small' | 'medium';
|
|
8
25
|
};
|
|
26
|
+
|
|
27
|
+
export type DropdownProps = {
|
|
28
|
+
/**
|
|
29
|
+
* The className of the global container.
|
|
30
|
+
*/
|
|
31
|
+
className?: string;
|
|
32
|
+
/**
|
|
33
|
+
* If you want to target the dropdown menu for styling purposes,
|
|
34
|
+
* you need to provide a contentClassName because it's not being rendered
|
|
35
|
+
* as a child of the container node.
|
|
36
|
+
*/
|
|
37
|
+
contentClassName?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Opt-in prop to show popovers fullscreen on mobile.
|
|
40
|
+
*
|
|
41
|
+
* @default false
|
|
42
|
+
*/
|
|
43
|
+
expandOnMobile?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* By default, the first tabbable element in the popover will receive focus
|
|
46
|
+
* when it mounts. This is the same as setting this prop to "firstElement".
|
|
47
|
+
* Specifying a true value will focus the container instead.
|
|
48
|
+
* Specifying a false value disables the focus handling entirely
|
|
49
|
+
* (this should only be done when an appropriately accessible
|
|
50
|
+
* substitute behavior exists).
|
|
51
|
+
*
|
|
52
|
+
* @default 'firstElement'
|
|
53
|
+
*/
|
|
54
|
+
focusOnMount?: 'firstElement' | boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Set this to customize the text that is shown in the dropdown's header
|
|
57
|
+
* when it is fullscreen on mobile.
|
|
58
|
+
*/
|
|
59
|
+
headerTitle?: string;
|
|
60
|
+
/**
|
|
61
|
+
* A callback invoked when the popover should be closed.
|
|
62
|
+
*/
|
|
63
|
+
onClose?: () => void;
|
|
64
|
+
/**
|
|
65
|
+
* A callback invoked when the state of the popover changes
|
|
66
|
+
* from open to closed and vice versa.
|
|
67
|
+
* The callback receives a boolean as a parameter.
|
|
68
|
+
* If true, the popover will open.
|
|
69
|
+
* If false, the popover will close.
|
|
70
|
+
*/
|
|
71
|
+
onToggle?: ( willOpen: boolean ) => void;
|
|
72
|
+
/**
|
|
73
|
+
* Properties of popoverProps object will be passed as props
|
|
74
|
+
* to the Popover component.
|
|
75
|
+
* Use this object to access properties/features
|
|
76
|
+
* of the Popover component that are not already exposed
|
|
77
|
+
* in the Dropdown component,
|
|
78
|
+
* e.g.: the ability to have the popover without an arrow.
|
|
79
|
+
*/
|
|
80
|
+
popoverProps?: Omit<
|
|
81
|
+
ComponentPropsWithoutRef< typeof Popover >,
|
|
82
|
+
'children'
|
|
83
|
+
>;
|
|
84
|
+
/**
|
|
85
|
+
* The direction in which the popover should open
|
|
86
|
+
* relative to its parent node.
|
|
87
|
+
* Specify a y- and an x-axis as a space-separated string.
|
|
88
|
+
* Supports "top", "bottom" y-axis,
|
|
89
|
+
* and "left", "center", "right" x-axis.
|
|
90
|
+
*
|
|
91
|
+
* @default 'top center'
|
|
92
|
+
*/
|
|
93
|
+
position?: PopoverProps[ 'position' ];
|
|
94
|
+
/**
|
|
95
|
+
* A callback invoked to render the content of the dropdown menu.
|
|
96
|
+
* Its first argument is the same as the renderToggle prop.
|
|
97
|
+
*/
|
|
98
|
+
renderContent: ( props: CallbackProps ) => ReactNode;
|
|
99
|
+
/**
|
|
100
|
+
* A callback invoked to render the Dropdown Toggle Button.
|
|
101
|
+
*
|
|
102
|
+
* The first argument of the callback is an object
|
|
103
|
+
* containing the following properties:
|
|
104
|
+
*
|
|
105
|
+
* - isOpen: whether the dropdown menu is opened or not
|
|
106
|
+
* - onToggle: A function switching the dropdown menu's state
|
|
107
|
+
* from open to closed and vice versa
|
|
108
|
+
* - onClose: A function that closes the menu if invoked
|
|
109
|
+
*/
|
|
110
|
+
renderToggle: ( props: CallbackProps ) => ReactNode;
|
|
111
|
+
/**
|
|
112
|
+
* The style of the global container.
|
|
113
|
+
*/
|
|
114
|
+
style?: CSSProperties;
|
|
115
|
+
};
|
|
@@ -101,14 +101,13 @@ const MyDropdownMenu = () => (
|
|
|
101
101
|
Alternatively, specify a `children` function which returns elements valid for use in a DropdownMenu: `MenuItem`, `MenuItemsChoice`, or `MenuGroup`.
|
|
102
102
|
|
|
103
103
|
```jsx
|
|
104
|
-
import { Fragment } from '@wordpress/element';
|
|
105
104
|
import { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components';
|
|
106
105
|
import { more, arrowUp, arrowDown, trash } from '@wordpress/icons';
|
|
107
106
|
|
|
108
107
|
const MyDropdownMenu = () => (
|
|
109
108
|
<DropdownMenu icon={ more } label="Select a direction">
|
|
110
109
|
{ ( { onClose } ) => (
|
|
111
|
-
|
|
110
|
+
<>
|
|
112
111
|
<MenuGroup>
|
|
113
112
|
<MenuItem icon={ arrowUp } onClick={ onClose }>
|
|
114
113
|
Move Up
|
|
@@ -122,7 +121,7 @@ const MyDropdownMenu = () => (
|
|
|
122
121
|
Remove
|
|
123
122
|
</MenuItem>
|
|
124
123
|
</MenuGroup>
|
|
125
|
-
|
|
124
|
+
</>
|
|
126
125
|
) }
|
|
127
126
|
</DropdownMenu>
|
|
128
127
|
);
|
|
@@ -15,6 +15,8 @@ import { arrowLeft, arrowRight, arrowUp, arrowDown } from '@wordpress/icons';
|
|
|
15
15
|
import DropdownMenu from '../';
|
|
16
16
|
import { MenuItem } from '../../';
|
|
17
17
|
|
|
18
|
+
jest.useFakeTimers();
|
|
19
|
+
|
|
18
20
|
describe( 'DropdownMenu', () => {
|
|
19
21
|
it( 'should not render when neither controls nor children are assigned', () => {
|
|
20
22
|
render( <DropdownMenu /> );
|
|
@@ -9,6 +9,8 @@ import userEvent from '@testing-library/user-event';
|
|
|
9
9
|
*/
|
|
10
10
|
import Picker from '..';
|
|
11
11
|
|
|
12
|
+
jest.useFakeTimers();
|
|
13
|
+
|
|
12
14
|
describe( 'FocalPointPicker', () => {
|
|
13
15
|
describe( 'focus and blur', () => {
|
|
14
16
|
it( 'clicking the draggable area should focus it', async () => {
|
|
@@ -10,6 +10,8 @@ import userEvent from '@testing-library/user-event';
|
|
|
10
10
|
import FontSizePicker from '../';
|
|
11
11
|
import type { FontSize } from '../types';
|
|
12
12
|
|
|
13
|
+
jest.useFakeTimers();
|
|
14
|
+
|
|
13
15
|
describe( 'FontSizePicker', () => {
|
|
14
16
|
test.each( [
|
|
15
17
|
// Use units when initial value uses units.
|
|
@@ -14,6 +14,8 @@ import FormFileUpload from '..';
|
|
|
14
14
|
*/
|
|
15
15
|
const { File } = window;
|
|
16
16
|
|
|
17
|
+
jest.useFakeTimers();
|
|
18
|
+
|
|
17
19
|
// @testing-library/user-event considers changing <input type="file"> to a string as a change, but it do not occur on real browsers, so the comparisons will be against this result
|
|
18
20
|
const fakePath = expect.objectContaining( {
|
|
19
21
|
target: expect.objectContaining( {
|
|
@@ -15,6 +15,8 @@ import { useState } from '@wordpress/element';
|
|
|
15
15
|
import FormToggle, { noop } from '..';
|
|
16
16
|
import type { FormToggleProps } from '../types';
|
|
17
17
|
|
|
18
|
+
jest.useFakeTimers();
|
|
19
|
+
|
|
18
20
|
const getInput = () => screen.getByRole( 'checkbox' ) as HTMLInputElement;
|
|
19
21
|
|
|
20
22
|
const ControlledFormToggle = ( { onChange }: FormToggleProps ) => {
|
|
@@ -21,6 +21,8 @@ import { useState } from '@wordpress/element';
|
|
|
21
21
|
*/
|
|
22
22
|
import FormTokenField from '../';
|
|
23
23
|
|
|
24
|
+
jest.useFakeTimers();
|
|
25
|
+
|
|
24
26
|
const FormTokenFieldWithState = ( {
|
|
25
27
|
onChange,
|
|
26
28
|
value,
|
|
@@ -486,6 +488,7 @@ describe( 'FormTokenField', () => {
|
|
|
486
488
|
|
|
487
489
|
// This is testing implementation details, but I'm not sure there's
|
|
488
490
|
// a better way.
|
|
491
|
+
// eslint-disable-next-line testing-library/no-node-access
|
|
489
492
|
expect( input.parentElement?.parentElement ).toHaveClass(
|
|
490
493
|
'test-classname'
|
|
491
494
|
);
|
|
@@ -99,7 +99,6 @@ export default function GradientPicker( {
|
|
|
99
99
|
value,
|
|
100
100
|
clearable = true,
|
|
101
101
|
disableCustomGradients = false,
|
|
102
|
-
__experimentalHasMultipleOrigins,
|
|
103
102
|
__experimentalIsRenderedInSidebar,
|
|
104
103
|
} ) {
|
|
105
104
|
const clearGradient = useCallback(
|
|
@@ -107,7 +106,7 @@ export default function GradientPicker( {
|
|
|
107
106
|
[ onChange ]
|
|
108
107
|
);
|
|
109
108
|
const Component =
|
|
110
|
-
|
|
109
|
+
gradients?.length && gradients[ 0 ].gradients
|
|
111
110
|
? MultipleOrigin
|
|
112
111
|
: SingleOrigin;
|
|
113
112
|
|
|
@@ -87,7 +87,6 @@ WithNoExistingGradients.args = {
|
|
|
87
87
|
export const MultipleOrigins = Template.bind( {} );
|
|
88
88
|
MultipleOrigins.args = {
|
|
89
89
|
...Default.args,
|
|
90
|
-
__experimentalHasMultipleOrigins: true,
|
|
91
90
|
gradients: [
|
|
92
91
|
{ name: 'Origin 1', gradients: GRADIENTS },
|
|
93
92
|
{ name: 'Origin 2', gradients: GRADIENTS },
|
package/src/guide/test/index.js
CHANGED
|
@@ -42,14 +42,17 @@ export function useNavigateRegions( shortcuts = defaultShortcuts ) {
|
|
|
42
42
|
|
|
43
43
|
function focusRegion( offset ) {
|
|
44
44
|
const regions = Array.from(
|
|
45
|
-
ref.current.querySelectorAll( '[role="region"]' )
|
|
45
|
+
ref.current.querySelectorAll( '[role="region"][tabindex="-1"]' )
|
|
46
46
|
);
|
|
47
47
|
if ( ! regions.length ) {
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
50
|
let nextRegion = regions[ 0 ];
|
|
51
|
+
// Based off the current element, use closest to determine the wrapping region since this operates up the DOM. Also, match tabindex to avoid edge cases with regions we do not want.
|
|
51
52
|
const selectedIndex = regions.indexOf(
|
|
52
|
-
ref.current.ownerDocument.activeElement
|
|
53
|
+
ref.current.ownerDocument.activeElement.closest(
|
|
54
|
+
'[role="region"][tabindex="-1"]'
|
|
55
|
+
)
|
|
53
56
|
);
|
|
54
57
|
if ( selectedIndex !== -1 ) {
|
|
55
58
|
let nextIndex = selectedIndex + offset;
|
|
@@ -4,14 +4,17 @@
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
.is-focusing-regions {
|
|
7
|
-
[role="region"]:focus {
|
|
7
|
+
[role="region"]:focus::after {
|
|
8
|
+
position: absolute;
|
|
9
|
+
top: 0;
|
|
10
|
+
left: 0;
|
|
11
|
+
right: 0;
|
|
12
|
+
bottom: 0;
|
|
13
|
+
content: "";
|
|
14
|
+
pointer-events: none;
|
|
8
15
|
outline: 4px solid $components-color-accent;
|
|
9
16
|
outline-offset: -4px;
|
|
10
|
-
|
|
11
|
-
.interface-navigable-region__stacker {
|
|
12
|
-
position: relative;
|
|
13
|
-
z-index: z-index(".is-focusing-regions [role='region']:focus .interface-navigable-region__stacker");
|
|
14
|
-
}
|
|
17
|
+
z-index: z-index(".is-focusing-regions {region} :focus::after");
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
// Fixes for edge cases.
|
|
@@ -25,40 +28,11 @@
|
|
|
25
28
|
// regardles of the CSS used on other components.
|
|
26
29
|
|
|
27
30
|
// Header top bar when Distraction free mode is on.
|
|
28
|
-
&.is-distraction-free .interface-interface-skeleton__header
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
outline-offset: inherit;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Sidebar toggle button shown when navigating regions.
|
|
37
|
-
.interface-interface-skeleton__sidebar {
|
|
38
|
-
.interface-navigable-region__stacker,
|
|
39
|
-
.edit-post-layout__toggle-sidebar-panel {
|
|
40
|
-
outline: inherit;
|
|
41
|
-
outline-offset: inherit;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Publish sidebar toggle button shown when navigating regions.
|
|
46
|
-
.interface-interface-skeleton__actions {
|
|
47
|
-
.interface-navigable-region__stacker,
|
|
48
|
-
.edit-post-layout__toggle-publish-panel {
|
|
49
|
-
outline: inherit;
|
|
50
|
-
outline-offset: inherit;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Publish sidebar.
|
|
55
|
-
[role="region"].interface-interface-skeleton__actions:focus .editor-post-publish-panel {
|
|
31
|
+
&.is-distraction-free .interface-interface-skeleton__header .edit-post-header,
|
|
32
|
+
.interface-interface-skeleton__sidebar .edit-post-layout__toggle-sidebar-panel,
|
|
33
|
+
.interface-interface-skeleton__actions .edit-post-layout__toggle-publish-panel,
|
|
34
|
+
.editor-post-publish-panel {
|
|
56
35
|
outline: 4px solid $components-color-accent;
|
|
57
36
|
outline-offset: -4px;
|
|
58
37
|
}
|
|
59
38
|
}
|
|
60
|
-
|
|
61
|
-
.interface-navigable-region__stacker {
|
|
62
|
-
height: 100%;
|
|
63
|
-
width: 100%;
|
|
64
|
-
}
|
|
@@ -13,6 +13,8 @@ import { addFilter, removeAllFilters, removeFilter } from '@wordpress/hooks';
|
|
|
13
13
|
*/
|
|
14
14
|
import withFilters from '..';
|
|
15
15
|
|
|
16
|
+
jest.useFakeTimers();
|
|
17
|
+
|
|
16
18
|
describe( 'withFilters', () => {
|
|
17
19
|
const hookName = 'EnhancedComponent';
|
|
18
20
|
const MyComponent = () => <div>My component</div>;
|
|
@@ -79,14 +81,13 @@ describe( 'withFilters', () => {
|
|
|
79
81
|
|
|
80
82
|
const { container } = render( <EnhancedComponent /> );
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
jest.runAllTimers();
|
|
84
|
+
act( () => jest.runAllTimers() );
|
|
85
85
|
|
|
86
86
|
expect( SpiedComponent ).toHaveBeenCalledTimes( 1 );
|
|
87
|
+
expect( container ).toMatchSnapshot();
|
|
87
88
|
} );
|
|
88
89
|
|
|
89
|
-
it( 'should re-render component once when new filter added after component was mounted',
|
|
90
|
+
it( 'should re-render component once when new filter added after component was mounted', () => {
|
|
90
91
|
const SpiedComponent = jest.fn( () => <div>Spied component</div> );
|
|
91
92
|
const EnhancedComponent = withFilters( hookName )( SpiedComponent );
|
|
92
93
|
|
|
@@ -94,25 +95,24 @@ describe( 'withFilters', () => {
|
|
|
94
95
|
|
|
95
96
|
SpiedComponent.mockClear();
|
|
96
97
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
(
|
|
102
|
-
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
} );
|
|
98
|
+
addFilter(
|
|
99
|
+
hookName,
|
|
100
|
+
'test/enhanced-component-spy-1',
|
|
101
|
+
( FilteredComponent ) => () =>
|
|
102
|
+
(
|
|
103
|
+
<blockquote>
|
|
104
|
+
<FilteredComponent />
|
|
105
|
+
</blockquote>
|
|
106
|
+
)
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
act( () => jest.runAllTimers() );
|
|
110
110
|
|
|
111
111
|
expect( SpiedComponent ).toHaveBeenCalledTimes( 1 );
|
|
112
112
|
expect( container ).toMatchSnapshot();
|
|
113
113
|
} );
|
|
114
114
|
|
|
115
|
-
it( 'should re-render component once when two filters added in the same animation frame',
|
|
115
|
+
it( 'should re-render component once when two filters added in the same animation frame', () => {
|
|
116
116
|
const SpiedComponent = jest.fn( () => <div>Spied component</div> );
|
|
117
117
|
const EnhancedComponent = withFilters( hookName )( SpiedComponent );
|
|
118
118
|
|
|
@@ -120,65 +120,62 @@ describe( 'withFilters', () => {
|
|
|
120
120
|
|
|
121
121
|
SpiedComponent.mockClear();
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
(
|
|
128
|
-
|
|
129
|
-
<
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
(
|
|
138
|
-
|
|
139
|
-
<
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
} );
|
|
123
|
+
addFilter(
|
|
124
|
+
hookName,
|
|
125
|
+
'test/enhanced-component-spy-1',
|
|
126
|
+
( FilteredComponent ) => () =>
|
|
127
|
+
(
|
|
128
|
+
<blockquote>
|
|
129
|
+
<FilteredComponent />
|
|
130
|
+
</blockquote>
|
|
131
|
+
)
|
|
132
|
+
);
|
|
133
|
+
addFilter(
|
|
134
|
+
hookName,
|
|
135
|
+
'test/enhanced-component-spy-2',
|
|
136
|
+
( FilteredComponent ) => () =>
|
|
137
|
+
(
|
|
138
|
+
<section>
|
|
139
|
+
<FilteredComponent />
|
|
140
|
+
</section>
|
|
141
|
+
)
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
act( () => jest.runAllTimers() );
|
|
146
145
|
|
|
147
146
|
expect( SpiedComponent ).toHaveBeenCalledTimes( 1 );
|
|
148
147
|
expect( container ).toMatchSnapshot();
|
|
149
148
|
} );
|
|
150
149
|
|
|
151
|
-
it( 'should re-render component twice when new filter added and removed in two different animation frames',
|
|
150
|
+
it( 'should re-render component twice when new filter added and removed in two different animation frames', () => {
|
|
152
151
|
const SpiedComponent = jest.fn( () => <div>Spied component</div> );
|
|
153
152
|
const EnhancedComponent = withFilters( hookName )( SpiedComponent );
|
|
154
153
|
const { container } = render( <EnhancedComponent /> );
|
|
155
154
|
|
|
156
155
|
SpiedComponent.mockClear();
|
|
157
156
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
(
|
|
163
|
-
|
|
164
|
-
<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
jest.runAllTimers();
|
|
175
|
-
} );
|
|
157
|
+
addFilter(
|
|
158
|
+
hookName,
|
|
159
|
+
'test/enhanced-component-spy',
|
|
160
|
+
( FilteredComponent ) => () =>
|
|
161
|
+
(
|
|
162
|
+
<div>
|
|
163
|
+
<FilteredComponent />
|
|
164
|
+
</div>
|
|
165
|
+
)
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
act( () => jest.runAllTimers() );
|
|
169
|
+
|
|
170
|
+
removeFilter( hookName, 'test/enhanced-component-spy' );
|
|
171
|
+
|
|
172
|
+
act( () => jest.runAllTimers() );
|
|
176
173
|
|
|
177
174
|
expect( SpiedComponent ).toHaveBeenCalledTimes( 2 );
|
|
178
175
|
expect( container ).toMatchSnapshot();
|
|
179
176
|
} );
|
|
180
177
|
|
|
181
|
-
it( 'should re-render both components once each when one filter added',
|
|
178
|
+
it( 'should re-render both components once each when one filter added', () => {
|
|
182
179
|
const SpiedComponent = jest.fn( () => <div>Spied component</div> );
|
|
183
180
|
const EnhancedComponent = withFilters( hookName )( SpiedComponent );
|
|
184
181
|
|
|
@@ -192,19 +189,18 @@ describe( 'withFilters', () => {
|
|
|
192
189
|
|
|
193
190
|
SpiedComponent.mockClear();
|
|
194
191
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
(
|
|
200
|
-
|
|
201
|
-
<
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
} );
|
|
192
|
+
addFilter(
|
|
193
|
+
hookName,
|
|
194
|
+
'test/enhanced-component-spy-1',
|
|
195
|
+
( FilteredComponent ) => () =>
|
|
196
|
+
(
|
|
197
|
+
<blockquote>
|
|
198
|
+
<FilteredComponent />
|
|
199
|
+
</blockquote>
|
|
200
|
+
)
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
act( () => jest.runAllTimers() );
|
|
208
204
|
|
|
209
205
|
expect( SpiedComponent ).toHaveBeenCalledTimes( 2 );
|
|
210
206
|
expect( container ).toMatchSnapshot();
|
|
@@ -101,6 +101,7 @@ describe( 'withNotices operations', () => {
|
|
|
101
101
|
act( () => {
|
|
102
102
|
handle.current.createErrorNotice( message );
|
|
103
103
|
} );
|
|
104
|
+
// eslint-disable-next-line testing-library/no-node-access
|
|
104
105
|
expect( getByText( message )?.closest( '.is-error' ) ).not.toBeNull();
|
|
105
106
|
} );
|
|
106
107
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { ComponentMeta, ComponentStory } from '@storybook/react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* WordPress dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { SVG, Path } from '@wordpress/primitives';
|
|
10
|
+
import { wordpress } from '@wordpress/icons';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Internal dependencies
|
|
14
|
+
*/
|
|
15
|
+
import Icon from '..';
|
|
16
|
+
import { VStack } from '../../v-stack';
|
|
17
|
+
|
|
18
|
+
const meta: ComponentMeta< typeof Icon > = {
|
|
19
|
+
title: 'Components/Icon',
|
|
20
|
+
component: Icon,
|
|
21
|
+
parameters: {
|
|
22
|
+
controls: { expanded: true },
|
|
23
|
+
docs: { source: { state: 'open' } },
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
export default meta;
|
|
27
|
+
|
|
28
|
+
const Template: ComponentStory< typeof Icon > = ( args ) => (
|
|
29
|
+
<Icon { ...args } />
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export const Default = Template.bind( {} );
|
|
33
|
+
Default.args = {
|
|
34
|
+
icon: wordpress,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const FillColor: ComponentStory< typeof Icon > = ( args ) => {
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
style={ {
|
|
41
|
+
fill: 'blue',
|
|
42
|
+
} }
|
|
43
|
+
>
|
|
44
|
+
<Icon { ...args } />
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
FillColor.args = {
|
|
49
|
+
...Default.args,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const WithAFunction = Template.bind( {} );
|
|
53
|
+
WithAFunction.args = {
|
|
54
|
+
...Default.args,
|
|
55
|
+
icon: () => (
|
|
56
|
+
<SVG>
|
|
57
|
+
<Path d="M5 4v3h5.5v12h3V7H19V4z" />
|
|
58
|
+
</SVG>
|
|
59
|
+
),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const MyIconComponent = () => (
|
|
63
|
+
<SVG>
|
|
64
|
+
<Path d="M5 4v3h5.5v12h3V7H19V4z" />
|
|
65
|
+
</SVG>
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
export const WithAComponent = Template.bind( {} );
|
|
69
|
+
WithAComponent.args = {
|
|
70
|
+
...Default.args,
|
|
71
|
+
icon: MyIconComponent,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const WithAnSVG = Template.bind( {} );
|
|
75
|
+
WithAnSVG.args = {
|
|
76
|
+
...Default.args,
|
|
77
|
+
icon: (
|
|
78
|
+
<SVG>
|
|
79
|
+
<Path d="M5 4v3h5.5v12h3V7H19V4z" />
|
|
80
|
+
</SVG>
|
|
81
|
+
),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Although it's preferred to use icons from the `@wordpress/icons` package, Dashicons are still supported,
|
|
86
|
+
* as long as you are in a context where the Dashicons stylesheet is loaded. To simulate that here,
|
|
87
|
+
* use the Global CSS Injector in the Storybook toolbar at the top and select the "WordPress" preset.
|
|
88
|
+
*/
|
|
89
|
+
export const WithADashicon: ComponentStory< typeof Icon > = ( args ) => {
|
|
90
|
+
return (
|
|
91
|
+
<VStack>
|
|
92
|
+
<Icon { ...args } />
|
|
93
|
+
<small>
|
|
94
|
+
This won’t show an icon if the Dashicons stylesheet isn’t
|
|
95
|
+
loaded.
|
|
96
|
+
</small>
|
|
97
|
+
</VStack>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
WithADashicon.args = {
|
|
101
|
+
...Default.args,
|
|
102
|
+
icon: 'wordpress',
|
|
103
|
+
};
|