@wordpress/components 29.8.0 → 29.10.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/.stylelintrc.js +1 -1
- package/CHANGELOG.md +31 -1
- package/build/color-picker/color-copy-button.js +3 -2
- package/build/color-picker/color-copy-button.js.map +1 -1
- package/build/guide/index.js +4 -2
- package/build/guide/index.js.map +1 -1
- package/build/guide/types.js.map +1 -1
- package/build/item-group/styles.js +10 -10
- package/build/item-group/styles.js.map +1 -1
- package/build/notice/types.js.map +1 -1
- package/build/popover/index.js +9 -1
- package/build/popover/index.js.map +1 -1
- package/build/popover/types.js.map +1 -1
- package/build/snackbar/index.js +16 -11
- package/build/snackbar/index.js.map +1 -1
- package/build/snackbar/types.js.map +1 -1
- package/build/spinner/index.js +5 -5
- package/build/spinner/index.js.map +1 -1
- package/build/textarea-control/styles/textarea-control-styles.js +3 -3
- package/build/textarea-control/styles/textarea-control-styles.js.map +1 -1
- package/build/toggle-group-control/toggle-group-control/component.js +1 -1
- package/build/toggle-group-control/toggle-group-control/component.js.map +1 -1
- package/build/unit-control/utils.js +9 -8
- package/build/unit-control/utils.js.map +1 -1
- package/build/utils/with-ignore-ime-events.js +5 -5
- package/build/utils/with-ignore-ime-events.js.map +1 -1
- package/build-module/color-picker/color-copy-button.js +4 -3
- package/build-module/color-picker/color-copy-button.js.map +1 -1
- package/build-module/guide/index.js +4 -2
- package/build-module/guide/index.js.map +1 -1
- package/build-module/guide/types.js.map +1 -1
- package/build-module/item-group/styles.js +10 -10
- package/build-module/item-group/styles.js.map +1 -1
- package/build-module/notice/types.js.map +1 -1
- package/build-module/popover/index.js +9 -1
- package/build-module/popover/index.js.map +1 -1
- package/build-module/popover/types.js.map +1 -1
- package/build-module/snackbar/index.js +16 -11
- package/build-module/snackbar/index.js.map +1 -1
- package/build-module/snackbar/types.js.map +1 -1
- package/build-module/spinner/index.js +5 -5
- package/build-module/spinner/index.js.map +1 -1
- package/build-module/textarea-control/styles/textarea-control-styles.js +3 -3
- package/build-module/textarea-control/styles/textarea-control-styles.js.map +1 -1
- package/build-module/toggle-group-control/toggle-group-control/component.js +1 -1
- package/build-module/toggle-group-control/toggle-group-control/component.js.map +1 -1
- package/build-module/unit-control/utils.js +9 -8
- package/build-module/unit-control/utils.js.map +1 -1
- package/build-module/utils/with-ignore-ime-events.js +5 -5
- package/build-module/utils/with-ignore-ime-events.js.map +1 -1
- package/build-style/style-rtl.css +78 -64
- package/build-style/style.css +78 -64
- package/build-types/guide/index.d.ts +1 -1
- package/build-types/guide/index.d.ts.map +1 -1
- package/build-types/guide/stories/index.story.d.ts.map +1 -1
- package/build-types/guide/types.d.ts +12 -0
- package/build-types/guide/types.d.ts.map +1 -1
- package/build-types/notice/types.d.ts +3 -1
- package/build-types/notice/types.d.ts.map +1 -1
- package/build-types/popover/index.d.ts.map +1 -1
- package/build-types/popover/types.d.ts +4 -0
- package/build-types/popover/types.d.ts.map +1 -1
- package/build-types/snackbar/index.d.ts +1 -1
- package/build-types/snackbar/index.d.ts.map +1 -1
- package/build-types/snackbar/types.d.ts +1 -1
- package/build-types/snackbar/types.d.ts.map +1 -1
- package/build-types/spinner/index.d.ts +5 -5
- package/build-types/textarea-control/styles/textarea-control-styles.d.ts.map +1 -1
- package/build-types/unit-control/utils.d.ts.map +1 -1
- package/build-types/utils/with-ignore-ime-events.d.ts +4 -4
- package/build-types/utils/with-ignore-ime-events.d.ts.map +1 -1
- package/package.json +19 -19
- package/src/color-picker/color-copy-button.tsx +4 -4
- package/src/color-picker/test/index.tsx +103 -26
- package/src/duotone-picker/style.scss +4 -0
- package/src/guide/README.md +16 -0
- package/src/guide/index.tsx +4 -2
- package/src/guide/stories/index.story.tsx +2 -0
- package/src/guide/types.ts +12 -0
- package/src/item-group/styles.ts +1 -1
- package/src/item-group/test/__snapshots__/index.js.snap +1 -1
- package/src/notice/README.md +3 -2
- package/src/notice/types.ts +3 -1
- package/src/popover/README.md +11 -0
- package/src/popover/index.tsx +12 -1
- package/src/popover/types.ts +4 -0
- package/src/snackbar/index.tsx +30 -17
- package/src/snackbar/style.scss +2 -1
- package/src/snackbar/types.ts +4 -1
- package/src/spinner/index.tsx +5 -5
- package/src/text-control/style.scss +3 -1
- package/src/textarea-control/styles/textarea-control-styles.ts +2 -0
- package/src/toggle-group-control/toggle-group-control/component.tsx +1 -1
- package/src/unit-control/test/utils.ts +36 -0
- package/src/unit-control/utils.ts +8 -11
- package/src/utils/with-ignore-ime-events.ts +5 -5
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { fireEvent, screen, render, waitFor } from '@testing-library/react';
|
|
5
5
|
import userEvent from '@testing-library/user-event';
|
|
6
|
+
import { click } from '@ariakit/test';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* WordPress dependencies
|
|
@@ -13,7 +14,6 @@ import { useState } from '@wordpress/element';
|
|
|
13
14
|
* Internal dependencies
|
|
14
15
|
*/
|
|
15
16
|
import { ColorPicker } from '..';
|
|
16
|
-
import { click } from '@ariakit/test';
|
|
17
17
|
|
|
18
18
|
const hslaMatcher = expect.objectContaining( {
|
|
19
19
|
h: expect.any( Number ),
|
|
@@ -41,6 +41,34 @@ const legacyColorMatcher = {
|
|
|
41
41
|
source: 'hex',
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
+
// Without the controlled component, slider values don't update after changes.
|
|
45
|
+
// Controlled component with state helps synchronize input box and slider during testing.
|
|
46
|
+
const ControlledColorPicker = ( {
|
|
47
|
+
onChange: onChangeProp,
|
|
48
|
+
initialColor = '#000000',
|
|
49
|
+
...restProps
|
|
50
|
+
}: React.ComponentProps< typeof ColorPicker > & { initialColor?: string } ) => {
|
|
51
|
+
const [ colorState, setColorState ] = useState( initialColor );
|
|
52
|
+
|
|
53
|
+
const internalOnChange: typeof onChangeProp = ( newColor ) => {
|
|
54
|
+
onChangeProp?.( newColor );
|
|
55
|
+
setColorState( newColor );
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<>
|
|
60
|
+
<ColorPicker
|
|
61
|
+
{ ...restProps }
|
|
62
|
+
onChange={ internalOnChange }
|
|
63
|
+
color={ colorState }
|
|
64
|
+
/>
|
|
65
|
+
<button onClick={ () => setColorState( '#4d87ba' ) }>
|
|
66
|
+
Set color to #4d87ba
|
|
67
|
+
</button>
|
|
68
|
+
</>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
44
72
|
describe( 'ColorPicker', () => {
|
|
45
73
|
describe( 'legacy props', () => {
|
|
46
74
|
it( 'should fire onChangeComplete with the legacy color format', async () => {
|
|
@@ -144,31 +172,6 @@ describe( 'ColorPicker', () => {
|
|
|
144
172
|
const user = userEvent.setup();
|
|
145
173
|
const onChange = jest.fn();
|
|
146
174
|
|
|
147
|
-
const ControlledColorPicker = ( {
|
|
148
|
-
onChange: onChangeProp,
|
|
149
|
-
...restProps
|
|
150
|
-
}: React.ComponentProps< typeof ColorPicker > ) => {
|
|
151
|
-
const [ colorState, setColorState ] = useState( '#000000' );
|
|
152
|
-
|
|
153
|
-
const internalOnChange: typeof onChangeProp = ( newColor ) => {
|
|
154
|
-
onChangeProp?.( newColor );
|
|
155
|
-
setColorState( newColor );
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
return (
|
|
159
|
-
<>
|
|
160
|
-
<ColorPicker
|
|
161
|
-
{ ...restProps }
|
|
162
|
-
onChange={ internalOnChange }
|
|
163
|
-
color={ colorState }
|
|
164
|
-
/>
|
|
165
|
-
<button onClick={ () => setColorState( '#4d87ba' ) }>
|
|
166
|
-
Set color to #4d87ba
|
|
167
|
-
</button>
|
|
168
|
-
</>
|
|
169
|
-
);
|
|
170
|
-
};
|
|
171
|
-
|
|
172
175
|
render(
|
|
173
176
|
<ControlledColorPicker
|
|
174
177
|
onChange={ onChange }
|
|
@@ -342,4 +345,78 @@ describe( 'ColorPicker', () => {
|
|
|
342
345
|
} );
|
|
343
346
|
} );
|
|
344
347
|
} );
|
|
348
|
+
|
|
349
|
+
describe.each( [
|
|
350
|
+
[ 'hsl', 'HSL' ],
|
|
351
|
+
[ 'rgb', 'RGB' ],
|
|
352
|
+
] )( 'Alpha-enabled %s format', ( format, formatLabel ) => {
|
|
353
|
+
it( `should update alpha correctly when ${ formatLabel } format is selected`, async () => {
|
|
354
|
+
const user = userEvent.setup();
|
|
355
|
+
const onChange = jest.fn();
|
|
356
|
+
|
|
357
|
+
render(
|
|
358
|
+
<ControlledColorPicker
|
|
359
|
+
onChange={ onChange }
|
|
360
|
+
enableAlpha
|
|
361
|
+
initialColor="#ffffff80"
|
|
362
|
+
/>
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
const formatSelector = screen.getByRole( 'combobox' );
|
|
366
|
+
expect( formatSelector ).toBeVisible();
|
|
367
|
+
await user.selectOptions( formatSelector, format );
|
|
368
|
+
|
|
369
|
+
const alphaInput = screen.getByRole( 'spinbutton', {
|
|
370
|
+
name: 'Alpha',
|
|
371
|
+
} );
|
|
372
|
+
expect( alphaInput ).toBeVisible();
|
|
373
|
+
|
|
374
|
+
const alphaSliders = screen.getAllByRole( 'slider', {
|
|
375
|
+
name: 'Alpha',
|
|
376
|
+
} );
|
|
377
|
+
|
|
378
|
+
expect( alphaSliders ).toHaveLength( 2 );
|
|
379
|
+
|
|
380
|
+
// Choose the second slider which is the actual slider of type: input[type="range"]
|
|
381
|
+
const alphaSlider = alphaSliders.at( -1 )!;
|
|
382
|
+
|
|
383
|
+
expect( alphaSlider ).toHaveValue( '50' );
|
|
384
|
+
expect( alphaInput ).toHaveValue( 50 );
|
|
385
|
+
|
|
386
|
+
expect( onChange ).not.toHaveBeenCalled();
|
|
387
|
+
|
|
388
|
+
// Test pattern 1: Update the slider
|
|
389
|
+
fireEvent.change( alphaSlider, {
|
|
390
|
+
target: { value: 75 },
|
|
391
|
+
} );
|
|
392
|
+
|
|
393
|
+
await waitFor( () => {
|
|
394
|
+
expect( onChange ).toHaveBeenCalledTimes( 1 );
|
|
395
|
+
} );
|
|
396
|
+
|
|
397
|
+
expect( onChange ).toHaveBeenLastCalledWith( '#ffffffbf' );
|
|
398
|
+
expect( alphaInput ).toHaveValue( 75 );
|
|
399
|
+
expect( alphaSlider ).toHaveValue( '75' );
|
|
400
|
+
|
|
401
|
+
onChange.mockClear();
|
|
402
|
+
|
|
403
|
+
// Test pattern 2: Update the alphaInput
|
|
404
|
+
await user.clear( alphaInput );
|
|
405
|
+
expect( onChange ).toHaveBeenCalledTimes( 1 );
|
|
406
|
+
|
|
407
|
+
// Initially type 7 in the alpha input, we expect it to be called with #ffffff12
|
|
408
|
+
await user.keyboard( '7' );
|
|
409
|
+
|
|
410
|
+
// Now with 75% opacity we expect it to be called with #ffffffbf
|
|
411
|
+
await user.keyboard( '5' );
|
|
412
|
+
|
|
413
|
+
// Called twice, once per key stroke (`7` and `5`)
|
|
414
|
+
expect( onChange ).toHaveBeenCalledTimes( 3 );
|
|
415
|
+
expect( onChange ).toHaveBeenNthCalledWith( 2, '#ffffff12' );
|
|
416
|
+
expect( onChange ).toHaveBeenNthCalledWith( 3, '#ffffffbf' );
|
|
417
|
+
|
|
418
|
+
expect( alphaSlider ).toHaveValue( '75' );
|
|
419
|
+
expect( alphaInput ).toHaveValue( 75 );
|
|
420
|
+
} );
|
|
421
|
+
} );
|
|
345
422
|
} );
|
package/src/guide/README.md
CHANGED
|
@@ -59,6 +59,22 @@ Use this to customize the label of the _Finish_ button shown at the end of the g
|
|
|
59
59
|
- Required: No
|
|
60
60
|
- Default: `'Finish'`
|
|
61
61
|
|
|
62
|
+
### nextButtonText
|
|
63
|
+
|
|
64
|
+
Use this to customize the label of the _Next_ button shown on each page of the guide.
|
|
65
|
+
|
|
66
|
+
- Type: `string`
|
|
67
|
+
- Required: No
|
|
68
|
+
- Default: `'Next'`
|
|
69
|
+
|
|
70
|
+
### previousButtonText
|
|
71
|
+
|
|
72
|
+
Use this to customize the label of the _Previous_ button shown on each page of the guide except the first.
|
|
73
|
+
|
|
74
|
+
- Type: `string`
|
|
75
|
+
- Required: No
|
|
76
|
+
- Default: `'Previous'`
|
|
77
|
+
|
|
62
78
|
### onFinish
|
|
63
79
|
|
|
64
80
|
A function which is called when the guide is finished. The guide is finished when the modal is closed or when the user clicks _Finish_ on the last page of the guide.
|
package/src/guide/index.tsx
CHANGED
|
@@ -55,6 +55,8 @@ function Guide( {
|
|
|
55
55
|
className,
|
|
56
56
|
contentLabel,
|
|
57
57
|
finishButtonText = __( 'Finish' ),
|
|
58
|
+
nextButtonText = __( 'Next' ),
|
|
59
|
+
previousButtonText = __( 'Previous' ),
|
|
58
60
|
onFinish,
|
|
59
61
|
pages = [],
|
|
60
62
|
}: GuideProps ) {
|
|
@@ -146,7 +148,7 @@ function Guide( {
|
|
|
146
148
|
onClick={ goBack }
|
|
147
149
|
__next40pxDefaultSize
|
|
148
150
|
>
|
|
149
|
-
{
|
|
151
|
+
{ previousButtonText }
|
|
150
152
|
</Button>
|
|
151
153
|
) }
|
|
152
154
|
{ canGoForward && (
|
|
@@ -156,7 +158,7 @@ function Guide( {
|
|
|
156
158
|
onClick={ goForward }
|
|
157
159
|
__next40pxDefaultSize
|
|
158
160
|
>
|
|
159
|
-
{
|
|
161
|
+
{ nextButtonText }
|
|
160
162
|
</Button>
|
|
161
163
|
) }
|
|
162
164
|
{ ! canGoForward && (
|
|
@@ -20,6 +20,8 @@ const meta: Meta< typeof Guide > = {
|
|
|
20
20
|
argTypes: {
|
|
21
21
|
contentLabel: { control: 'text' },
|
|
22
22
|
finishButtonText: { control: 'text' },
|
|
23
|
+
nextButtonText: { control: 'text' },
|
|
24
|
+
previousButtonText: { control: 'text' },
|
|
23
25
|
onFinish: { action: 'onFinish' },
|
|
24
26
|
},
|
|
25
27
|
};
|
package/src/guide/types.ts
CHANGED
|
@@ -40,6 +40,18 @@ export type GuideProps = {
|
|
|
40
40
|
* @default 'Finish'
|
|
41
41
|
*/
|
|
42
42
|
finishButtonText?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Use this to customize the label of the _Next_ button shown on each page of the guide.
|
|
45
|
+
*
|
|
46
|
+
* @default 'Next'
|
|
47
|
+
*/
|
|
48
|
+
nextButtonText?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Use this to customize the label of the _Previous_ button shown on each page of the guide except the first.
|
|
51
|
+
*
|
|
52
|
+
* @default 'Previous'
|
|
53
|
+
*/
|
|
54
|
+
previousButtonText?: string;
|
|
43
55
|
/**
|
|
44
56
|
* A function which is called when the guide is finished.
|
|
45
57
|
*/
|
package/src/item-group/styles.ts
CHANGED
|
@@ -115,7 +115,7 @@ Snapshot Diff:
|
|
|
115
115
|
<div>
|
|
116
116
|
<div
|
|
117
117
|
- class="components-item-group css-1iattls-PolymorphicDiv-rounded e19lxcc00"
|
|
118
|
-
+ class="components-item-group css-
|
|
118
|
+
+ class="components-item-group css-1hvp0tq-PolymorphicDiv-separated-rounded e19lxcc00"
|
|
119
119
|
data-wp-c16t="true"
|
|
120
120
|
data-wp-component="ItemGroup"
|
|
121
121
|
role="list"
|
package/src/notice/README.md
CHANGED
|
@@ -61,7 +61,7 @@ If an icon is included in the Notice, it should be color-coded to match the Noti
|
|
|
61
61
|
To display a plain notice, pass `Notice` a string:
|
|
62
62
|
|
|
63
63
|
```jsx
|
|
64
|
-
import { Notice } from
|
|
64
|
+
import { Notice } from '@wordpress/components';
|
|
65
65
|
|
|
66
66
|
const MyNotice = () => (
|
|
67
67
|
<Notice status="error">An unknown error occurred.</Notice>
|
|
@@ -71,7 +71,7 @@ const MyNotice = () => (
|
|
|
71
71
|
For more complex markup, you can pass any JSX element:
|
|
72
72
|
|
|
73
73
|
```jsx
|
|
74
|
-
import { Notice } from
|
|
74
|
+
import { Notice } from '@wordpress/components';
|
|
75
75
|
|
|
76
76
|
const MyNotice = () => (
|
|
77
77
|
<Notice status="error">
|
|
@@ -145,6 +145,7 @@ An array of notice actions. Each member object should contain:
|
|
|
145
145
|
|
|
146
146
|
- `label`: `string` containing the text of the button/link
|
|
147
147
|
- `url`: `string` OR `onClick`: `( event: SyntheticEvent ) => void` to specify what the action does.
|
|
148
|
+
- `openInNewTab`: `boolean` (optional) When set to `true`, opens the URL in a new browser tab.
|
|
148
149
|
- `className`: `string` (optional) to add custom classes to the button styles.
|
|
149
150
|
- `noDefaultClasses`: `boolean` (optional) A value of `true` will remove all default styling.
|
|
150
151
|
- `variant`: `'primary' | 'secondary' | 'link'` (optional) You can denote a primary button action for a notice by passing a value of `primary`.
|
package/src/notice/types.ts
CHANGED
|
@@ -14,11 +14,13 @@ type CommonNoticeActionProps = {
|
|
|
14
14
|
// `onClick` will be ignored.
|
|
15
15
|
type NoticeActionWithURL = CommonNoticeActionProps & {
|
|
16
16
|
url: string;
|
|
17
|
+
openInNewTab?: boolean;
|
|
17
18
|
onClick?: never;
|
|
18
19
|
};
|
|
19
20
|
type NoticeActionWithOnClick = CommonNoticeActionProps & {
|
|
20
21
|
url?: never;
|
|
21
|
-
|
|
22
|
+
openInNewTab?: never;
|
|
23
|
+
onClick: MouseEventHandler< HTMLButtonElement | HTMLAnchorElement >;
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
export type NoticeAction = NoticeActionWithURL | NoticeActionWithOnClick;
|
package/src/popover/README.md
CHANGED
|
@@ -223,9 +223,20 @@ Possible values:
|
|
|
223
223
|
|
|
224
224
|
Adjusts the size of the popover to prevent its contents from going out of view when meeting the viewport edges.
|
|
225
225
|
|
|
226
|
+
**Note:** The `resize` and `shift` props are not intended to be used together. Enabling both can cause unexpected behavior.
|
|
227
|
+
|
|
226
228
|
- Required: No
|
|
227
229
|
- Default: `true`
|
|
228
230
|
|
|
231
|
+
### `shift`: `boolean`
|
|
232
|
+
|
|
233
|
+
Enables the `Popover` to shift in order to stay in view when meeting the viewport edges.
|
|
234
|
+
|
|
235
|
+
**Note:** The `shift` and `resize` props are not intended to be used together. If you enable `shift`, set `resize` to `false`.
|
|
236
|
+
|
|
237
|
+
- Required: No
|
|
238
|
+
- Default: `false`
|
|
239
|
+
|
|
229
240
|
### `variant`: `'toolbar' | 'unstyled'`
|
|
230
241
|
|
|
231
242
|
Specifies the popover's style.
|
package/src/popover/index.tsx
CHANGED
|
@@ -71,6 +71,13 @@ import { StyleProvider } from '../style-provider';
|
|
|
71
71
|
*/
|
|
72
72
|
export const SLOT_NAME = 'Popover';
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Virtual padding to account for overflow boundaries.
|
|
76
|
+
*
|
|
77
|
+
* @type {number}
|
|
78
|
+
*/
|
|
79
|
+
const OVERFLOW_PADDING = 8;
|
|
80
|
+
|
|
74
81
|
// An SVG displaying a triangle facing down, filled with a solid
|
|
75
82
|
// color and bordered in such a way to create an arrow-like effect.
|
|
76
83
|
// Keeping the SVG's viewbox squared simplify the arrow positioning
|
|
@@ -224,6 +231,7 @@ const UnforwardedPopover = (
|
|
|
224
231
|
computedFlipProp && flipMiddleware(),
|
|
225
232
|
computedResizeProp &&
|
|
226
233
|
size( {
|
|
234
|
+
padding: OVERFLOW_PADDING,
|
|
227
235
|
apply( sizeProps ) {
|
|
228
236
|
const { firstElementChild } = refs.floating.current ?? {};
|
|
229
237
|
|
|
@@ -234,7 +242,10 @@ const UnforwardedPopover = (
|
|
|
234
242
|
|
|
235
243
|
// Reduce the height of the popover to the available space.
|
|
236
244
|
Object.assign( firstElementChild.style, {
|
|
237
|
-
maxHeight: `${
|
|
245
|
+
maxHeight: `${ Math.max(
|
|
246
|
+
0,
|
|
247
|
+
sizeProps.availableHeight
|
|
248
|
+
) }px`,
|
|
238
249
|
overflow: 'auto',
|
|
239
250
|
} );
|
|
240
251
|
},
|
package/src/popover/types.ts
CHANGED
|
@@ -129,6 +129,8 @@ export type PopoverProps = {
|
|
|
129
129
|
/**
|
|
130
130
|
* Adjusts the size of the popover to prevent its contents from going out of
|
|
131
131
|
* view when meeting the viewport edges.
|
|
132
|
+
* _Note: The `resize` and `shift` props are not intended to be used together.
|
|
133
|
+
* Enabling both can cause unexpected behavior._
|
|
132
134
|
*
|
|
133
135
|
* @default true
|
|
134
136
|
*/
|
|
@@ -136,6 +138,8 @@ export type PopoverProps = {
|
|
|
136
138
|
/**
|
|
137
139
|
* Enables the `Popover` to shift in order to stay in view when meeting the
|
|
138
140
|
* viewport edges.
|
|
141
|
+
* _Note: The `resize` and `shift` props are not intended to be used together.
|
|
142
|
+
* Enabling both can cause unexpected behavior._
|
|
139
143
|
*
|
|
140
144
|
* @default false
|
|
141
145
|
*/
|
package/src/snackbar/index.tsx
CHANGED
|
@@ -22,6 +22,7 @@ import warning from '@wordpress/warning';
|
|
|
22
22
|
* Internal dependencies
|
|
23
23
|
*/
|
|
24
24
|
import Button from '../button';
|
|
25
|
+
import ExternalLink from '../external-link';
|
|
25
26
|
import type { SnackbarProps } from './types';
|
|
26
27
|
import type { NoticeAction } from '../notice/types';
|
|
27
28
|
import type { WordPressComponentProps } from '../context';
|
|
@@ -80,7 +81,7 @@ function UnforwardedSnackbar(
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
function onActionClick(
|
|
83
|
-
event: MouseEvent< HTMLButtonElement >,
|
|
84
|
+
event: MouseEvent< HTMLButtonElement | HTMLAnchorElement >,
|
|
84
85
|
onClick: NoticeAction[ 'onClick' ]
|
|
85
86
|
) {
|
|
86
87
|
event.stopPropagation();
|
|
@@ -147,22 +148,34 @@ function UnforwardedSnackbar(
|
|
|
147
148
|
<div className="components-snackbar__icon">{ icon }</div>
|
|
148
149
|
) }
|
|
149
150
|
{ children }
|
|
150
|
-
{ actions.map(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
151
|
+
{ actions.map(
|
|
152
|
+
( { label, onClick, url, openInNewTab = false }, index ) =>
|
|
153
|
+
url !== undefined && openInNewTab ? (
|
|
154
|
+
<ExternalLink
|
|
155
|
+
key={ index }
|
|
156
|
+
href={ url }
|
|
157
|
+
onClick={ ( event ) =>
|
|
158
|
+
onActionClick( event, onClick )
|
|
159
|
+
}
|
|
160
|
+
className="components-snackbar__action"
|
|
161
|
+
>
|
|
162
|
+
{ label }
|
|
163
|
+
</ExternalLink>
|
|
164
|
+
) : (
|
|
165
|
+
<Button
|
|
166
|
+
__next40pxDefaultSize
|
|
167
|
+
key={ index }
|
|
168
|
+
href={ url }
|
|
169
|
+
variant="link"
|
|
170
|
+
onClick={ (
|
|
171
|
+
event: MouseEvent< HTMLButtonElement >
|
|
172
|
+
) => onActionClick( event, onClick ) }
|
|
173
|
+
className="components-snackbar__action"
|
|
174
|
+
>
|
|
175
|
+
{ label }
|
|
176
|
+
</Button>
|
|
177
|
+
)
|
|
178
|
+
) }
|
|
166
179
|
{ explicitDismiss && (
|
|
167
180
|
<span
|
|
168
181
|
role="button"
|
package/src/snackbar/style.scss
CHANGED
package/src/snackbar/types.ts
CHANGED
|
@@ -56,7 +56,10 @@ export type SnackbarProps = Pick<
|
|
|
56
56
|
*
|
|
57
57
|
* @default []
|
|
58
58
|
*/
|
|
59
|
-
actions?: Pick<
|
|
59
|
+
actions?: Pick<
|
|
60
|
+
NoticeAction,
|
|
61
|
+
'label' | 'url' | 'onClick' | 'openInNewTab'
|
|
62
|
+
>[];
|
|
60
63
|
};
|
|
61
64
|
|
|
62
65
|
export type SnackbarListProps = {
|
package/src/spinner/index.tsx
CHANGED
|
@@ -50,12 +50,12 @@ export function UnforwardedSpinner(
|
|
|
50
50
|
/**
|
|
51
51
|
* `Spinner` is a component used to notify users that their action is being processed.
|
|
52
52
|
*
|
|
53
|
-
* ```
|
|
54
|
-
*
|
|
53
|
+
* ```jsx
|
|
54
|
+
* import { Spinner } from '@wordpress/components';
|
|
55
55
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
56
|
+
* function Example() {
|
|
57
|
+
* return <Spinner />;
|
|
58
|
+
* }
|
|
59
59
|
* ```
|
|
60
60
|
*/
|
|
61
61
|
export const Spinner = forwardRef( UnforwardedSpinner );
|
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
height: $grid-unit-40;
|
|
17
17
|
// Override input style margin in WP forms.css.
|
|
18
18
|
margin: 0;
|
|
19
|
-
|
|
19
|
+
background: $components-color-background;
|
|
20
|
+
color: $components-color-foreground;
|
|
21
|
+
@include input-control( $components-color-accent);
|
|
20
22
|
|
|
21
23
|
&.is-next-40px-default-size {
|
|
22
24
|
height: $grid-unit-50;
|
|
@@ -37,6 +37,8 @@ export const StyledTextarea = styled.textarea`
|
|
|
37
37
|
display: block;
|
|
38
38
|
font-family: ${ font( 'default.fontFamily' ) };
|
|
39
39
|
line-height: 20px;
|
|
40
|
+
background: ${ COLORS.theme.background };
|
|
41
|
+
color: ${ COLORS.theme.foreground };
|
|
40
42
|
|
|
41
43
|
// Vertical padding is to match the standard 40px control height when rows=1,
|
|
42
44
|
// in conjunction with the 20px line-height.
|
|
@@ -54,7 +54,7 @@ function UnconnectedToggleGroupControl(
|
|
|
54
54
|
const [ controlElement, setControlElement ] = useState< HTMLElement >();
|
|
55
55
|
const refs = useMergeRefs( [ setControlElement, forwardedRef ] );
|
|
56
56
|
const selectedRect = useTrackElementOffsetRect(
|
|
57
|
-
value
|
|
57
|
+
value !== null && value !== undefined ? selectedElement : undefined
|
|
58
58
|
);
|
|
59
59
|
useAnimatedOffsetRect( controlElement, selectedRect, {
|
|
60
60
|
prefix: 'selected',
|
|
@@ -42,6 +42,42 @@ describe( 'UnitControl utils', () => {
|
|
|
42
42
|
] );
|
|
43
43
|
} );
|
|
44
44
|
|
|
45
|
+
it( 'should not mutate default units argument definiton', () => {
|
|
46
|
+
const unitsA = useCustomUnits( {
|
|
47
|
+
availableUnits: [ 'px', 'em', 'rem' ],
|
|
48
|
+
defaultValues: { px: 8, em: 0.5, rem: 0.5 },
|
|
49
|
+
} );
|
|
50
|
+
|
|
51
|
+
const unitsB = useCustomUnits( {
|
|
52
|
+
availableUnits: [ 'px', 'em', 'rem' ],
|
|
53
|
+
defaultValues: { px: 16, em: 1, rem: 1 },
|
|
54
|
+
} );
|
|
55
|
+
|
|
56
|
+
expect( unitsA ).not.toEqual( unitsB );
|
|
57
|
+
} );
|
|
58
|
+
|
|
59
|
+
it( 'should not mutate custon units argument definitons', () => {
|
|
60
|
+
const units = [
|
|
61
|
+
{ value: 'px', label: 'pixel' },
|
|
62
|
+
{ value: 'em', label: 'em' },
|
|
63
|
+
{ value: 'rem', label: 'rem' },
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
const unitsA = useCustomUnits( {
|
|
67
|
+
availableUnits: [ 'px', 'em', 'rem' ],
|
|
68
|
+
defaultValues: { px: 8, em: 0.5, rem: 0.5 },
|
|
69
|
+
units,
|
|
70
|
+
} );
|
|
71
|
+
|
|
72
|
+
const unitsB = useCustomUnits( {
|
|
73
|
+
availableUnits: [ 'px', 'em', 'rem' ],
|
|
74
|
+
defaultValues: { px: 16, em: 1, rem: 1 },
|
|
75
|
+
units,
|
|
76
|
+
} );
|
|
77
|
+
|
|
78
|
+
expect( unitsA ).not.toEqual( unitsB );
|
|
79
|
+
} );
|
|
80
|
+
|
|
45
81
|
it( 'should add default values to available units even if the default values are strings', () => {
|
|
46
82
|
// Although the public APIs of the component expect a `number` as the type of the
|
|
47
83
|
// default values, it's still good to test for strings (as it can happen in un-typed
|
|
@@ -428,19 +428,16 @@ export const useCustomUnits = ( {
|
|
|
428
428
|
units
|
|
429
429
|
);
|
|
430
430
|
|
|
431
|
-
if ( defaultValues ) {
|
|
432
|
-
customUnitsToReturn
|
|
433
|
-
if ( defaultValues[ unit.value ] ) {
|
|
434
|
-
const [ parsedDefaultValue ] = parseQuantityAndUnitFromRawValue(
|
|
435
|
-
defaultValues[ unit.value ]
|
|
436
|
-
);
|
|
437
|
-
|
|
438
|
-
customUnitsToReturn[ i ].default = parsedDefaultValue;
|
|
439
|
-
}
|
|
440
|
-
} );
|
|
431
|
+
if ( ! defaultValues ) {
|
|
432
|
+
return customUnitsToReturn;
|
|
441
433
|
}
|
|
442
434
|
|
|
443
|
-
return customUnitsToReturn
|
|
435
|
+
return customUnitsToReturn.map( ( unit ) => {
|
|
436
|
+
const [ defaultValue ] = defaultValues[ unit.value ]
|
|
437
|
+
? parseQuantityAndUnitFromRawValue( defaultValues[ unit.value ] )
|
|
438
|
+
: [];
|
|
439
|
+
return { ...unit, default: defaultValue };
|
|
440
|
+
} );
|
|
444
441
|
};
|
|
445
442
|
|
|
446
443
|
/**
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A higher-order function that wraps a
|
|
2
|
+
* A higher-order function that wraps a keyboard event handler to ensure it is not an IME event.
|
|
3
3
|
*
|
|
4
4
|
* In CJK languages, an IME (Input Method Editor) is used to input complex characters.
|
|
5
|
-
* During an IME composition,
|
|
5
|
+
* During an IME composition, keyboard events (e.g. Enter or Escape) can be fired
|
|
6
6
|
* which are intended to control the IME and not the application.
|
|
7
7
|
* These events should be ignored by any application logic.
|
|
8
8
|
*
|
|
9
|
-
* @param
|
|
9
|
+
* @param handler The keyboard event handler to execute after ensuring it was not an IME event.
|
|
10
10
|
*
|
|
11
11
|
* @return A wrapped version of the given event handler that ignores IME events.
|
|
12
12
|
*/
|
|
13
13
|
export function withIgnoreIMEEvents<
|
|
14
14
|
E extends React.KeyboardEvent | KeyboardEvent,
|
|
15
|
-
>(
|
|
15
|
+
>( handler: ( event: E ) => void ) {
|
|
16
16
|
return ( event: E ) => {
|
|
17
17
|
const { isComposing } =
|
|
18
18
|
'nativeEvent' in event ? event.nativeEvent : event;
|
|
@@ -27,6 +27,6 @@ export function withIgnoreIMEEvents<
|
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
handler( event );
|
|
31
31
|
};
|
|
32
32
|
}
|