@patternfly/react-core 4.224.10 → 4.224.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "4.224.10",
3
+ "version": "4.224.11",
4
4
  "description": "This library provides a set of common React components for use with the PatternFly reference implementation.",
5
5
  "main": "dist/js/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -34,9 +34,9 @@
34
34
  "generate": "node scripts/copyStyles.js"
35
35
  },
36
36
  "dependencies": {
37
- "@patternfly/react-icons": "^4.75.10",
38
- "@patternfly/react-styles": "^4.74.10",
39
- "@patternfly/react-tokens": "^4.76.10",
37
+ "@patternfly/react-icons": "^4.75.11",
38
+ "@patternfly/react-styles": "^4.74.11",
39
+ "@patternfly/react-tokens": "^4.76.11",
40
40
  "focus-trap": "6.9.2",
41
41
  "react-dropzone": "9.0.0",
42
42
  "tippy.js": "5.1.2",
@@ -60,5 +60,5 @@
60
60
  "react": "^16.8.0 || ^17.0.0",
61
61
  "react-dom": "^16.8.0 || ^17.0.0"
62
62
  },
63
- "gitHead": "5242f54a3eeae9d5ca2958620454a8d67b7926e8"
63
+ "gitHead": "030baae8a3dd4fe4a5bd0dda43804835cfc453bb"
64
64
  }
@@ -1,14 +1,49 @@
1
- import * as React from 'react';
2
- import { render } from '@testing-library/react';
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
3
  import { ActionList } from '../ActionList';
4
4
 
5
- describe('action list', () => {
6
- test('renders successfully', () => {
7
- const { asFragment } = render(<ActionList>test</ActionList>);
8
- expect(asFragment()).toMatchSnapshot();
9
- });
10
- test('isIconList flag adds modifier', () => {
11
- const { asFragment } = render(<ActionList isIconList>test</ActionList>);
12
- expect(asFragment()).toMatchSnapshot();
13
- });
5
+ test('Renders without children', () => {
6
+ render(<ActionList data-testid="action-list" />);
7
+ expect(screen.getByTestId('action-list')).toBeVisible();
8
+ });
9
+
10
+ test('Renders children', () => {
11
+ render(<ActionList>Test</ActionList>);
12
+
13
+ expect(screen.getByText('Test')).toBeVisible();
14
+ });
15
+
16
+ test('Renders with class pf-c-action-list', () => {
17
+ render(<ActionList>Test</ActionList>);
18
+
19
+ expect(screen.getByText('Test')).toHaveClass('pf-c-action-list');
20
+ });
21
+
22
+ test('Renders with custom class names provided via prop', () => {
23
+ render(<ActionList className="custom-class">Test</ActionList>);
24
+
25
+ expect(screen.getByText('Test')).toHaveClass('custom-class');
26
+ });
27
+
28
+ test('Does not render with class pf-m-icons by default', () => {
29
+ render(<ActionList>Test</ActionList>);
30
+
31
+ expect(screen.getByText('Test')).not.toHaveClass('pf-m-icons');
32
+ });
33
+
34
+ test('Renders with class pf-m-icons when isIconList is true', () => {
35
+ render(<ActionList isIconList={true}>Test</ActionList>);
36
+
37
+ expect(screen.getByText('Test')).toHaveClass('pf-m-icons');
38
+ });
39
+
40
+ test('Renders with inherited element props spread to the component', () => {
41
+ render(<ActionList aria-label="Test label">Test</ActionList>);
42
+
43
+ expect(screen.getByText('Test')).toHaveAccessibleName('Test label');
44
+ })
45
+
46
+ test('Matches the snapshot', () => {
47
+ const { asFragment } = render(<ActionList>test</ActionList>);
48
+ expect(asFragment()).toMatchSnapshot();
14
49
  });
@@ -1,10 +1,37 @@
1
- import * as React from 'react';
2
- import { render } from '@testing-library/react';
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
3
  import { ActionListGroup } from '../ActionListGroup';
4
4
 
5
- describe('action list group', () => {
6
- test('renders successfully', () => {
7
- const { asFragment } = render(<ActionListGroup>test</ActionListGroup>);
8
- expect(asFragment()).toMatchSnapshot();
9
- });
5
+ test('Renders without children', () => {
6
+ render(<ActionListGroup data-testid="action-list-group" />);
7
+ expect(screen.getByTestId('action-list-group')).toBeVisible();
8
+ });
9
+
10
+ test('Renders children', () => {
11
+ render(<ActionListGroup>Test</ActionListGroup>);
12
+
13
+ expect(screen.getByText('Test')).toBeVisible();
14
+ });
15
+
16
+ test('Renders with class pf-c-action-list__group', () => {
17
+ render(<ActionListGroup>Test</ActionListGroup>);
18
+
19
+ expect(screen.getByText('Test')).toHaveClass('pf-c-action-list__group');
20
+ });
21
+
22
+ test('Renders with custom class names provided via prop', () => {
23
+ render(<ActionListGroup className="custom-class">Test</ActionListGroup>);
24
+
25
+ expect(screen.getByText('Test')).toHaveClass('custom-class');
26
+ });
27
+
28
+ test('Renders with inherited element props spread to the component', () => {
29
+ render(<ActionListGroup aria-label="Test label">Test</ActionListGroup>);
30
+
31
+ expect(screen.getByText('Test')).toHaveAccessibleName('Test label');
32
+ })
33
+
34
+ test('Matches the snapshot', () => {
35
+ const { asFragment } = render(<ActionListGroup>test</ActionListGroup>);
36
+ expect(asFragment()).toMatchSnapshot();
10
37
  });
@@ -1,10 +1,37 @@
1
- import * as React from 'react';
2
- import { render } from '@testing-library/react';
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
3
  import { ActionListItem } from '../ActionListItem';
4
4
 
5
- describe('action list item', () => {
6
- test('renders successfully', () => {
7
- const { asFragment } = render(<ActionListItem>test</ActionListItem>);
8
- expect(asFragment()).toMatchSnapshot();
9
- });
5
+ test('Renders without children', () => {
6
+ render(<ActionListItem data-testid="action-list-item" />);
7
+ expect(screen.getByTestId('action-list-item')).toBeVisible();
8
+ });
9
+
10
+ test('Renders children', () => {
11
+ render(<ActionListItem>Test</ActionListItem>);
12
+
13
+ expect(screen.getByText('Test')).toBeVisible();
14
+ });
15
+
16
+ test('Renders with class pf-c-action-list__item', () => {
17
+ render(<ActionListItem>Test</ActionListItem>);
18
+
19
+ expect(screen.getByText('Test')).toHaveClass('pf-c-action-list__item');
20
+ });
21
+
22
+ test('Renders with custom class names provided via prop', () => {
23
+ render(<ActionListItem className="custom-class">Test</ActionListItem>);
24
+
25
+ expect(screen.getByText('Test')).toHaveClass('custom-class');
26
+ });
27
+
28
+ test('Renders with inherited element props spread to the component', () => {
29
+ render(<ActionListItem aria-label="Test label">Test</ActionListItem>);
30
+
31
+ expect(screen.getByText('Test')).toHaveAccessibleName('Test label');
32
+ })
33
+
34
+ test('Matches the snapshot', () => {
35
+ const { asFragment } = render(<ActionListItem>test</ActionListItem>);
36
+ expect(asFragment()).toMatchSnapshot();
10
37
  });
@@ -1,16 +1,6 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`action list isIconList flag adds modifier 1`] = `
4
- <DocumentFragment>
5
- <div
6
- class="pf-c-action-list pf-m-icons"
7
- >
8
- test
9
- </div>
10
- </DocumentFragment>
11
- `;
12
-
13
- exports[`action list renders successfully 1`] = `
3
+ exports[`Matches the snapshot 1`] = `
14
4
  <DocumentFragment>
15
5
  <div
16
6
  class="pf-c-action-list"
@@ -1,6 +1,6 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`action list group renders successfully 1`] = `
3
+ exports[`Matches the snapshot 1`] = `
4
4
  <DocumentFragment>
5
5
  <div
6
6
  class="pf-c-action-list__group"
@@ -1,6 +1,6 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`action list item renders successfully 1`] = `
3
+ exports[`Matches the snapshot 1`] = `
4
4
  <DocumentFragment>
5
5
  <div
6
6
  class="pf-c-action-list__item"
@@ -1,6 +1,5 @@
1
1
  import * as React from 'react';
2
2
  import { css } from '@patternfly/react-styles';
3
- import styles from '@patternfly/react-styles/css/components/SearchInput/search-input';
4
3
  import { Button, ButtonVariant } from '../Button';
5
4
  import { Badge } from '../Badge';
6
5
  import AngleDownIcon from '@patternfly/react-icons/dist/esm/icons/angle-down-icon';
@@ -12,6 +11,7 @@ import ArrowRightIcon from '@patternfly/react-icons/dist/esm/icons/arrow-right-i
12
11
  import { AdvancedSearchMenu } from './AdvancedSearchMenu';
13
12
  import { TextInputGroup, TextInputGroupMain, TextInputGroupUtilities } from '../TextInputGroup';
14
13
  import { InputGroup } from '../InputGroup';
14
+ import { Popper } from '../../helpers';
15
15
 
16
16
  export interface SearchAttribute {
17
17
  /** The search attribute's value to be provided in the search input's query string.
@@ -83,6 +83,13 @@ export interface SearchInputProps extends Omit<React.HTMLProps<HTMLDivElement>,
83
83
  /** Delimiter in the query string for pairing attributes with search values.
84
84
  * Required whenever attributes are passed as props */
85
85
  advancedSearchDelimiter?: string;
86
+ /** The container to append the menu to.
87
+ * If your menu is being cut off you can append it to an element higher up the DOM tree.
88
+ * Some examples:
89
+ * appendTo={() => document.body}
90
+ * appendTo={document.getElementById('target')}
91
+ */
92
+ appendTo?: HTMLElement | (() => HTMLElement) | 'inline';
86
93
  }
87
94
 
88
95
  const SearchInputBase: React.FunctionComponent<SearchInputProps> = ({
@@ -112,6 +119,7 @@ const SearchInputBase: React.FunctionComponent<SearchInputProps> = ({
112
119
  nextNavigationButtonAriaLabel = 'Next',
113
120
  submitSearchButtonLabel = 'Search',
114
121
  isDisabled = false,
122
+ appendTo,
115
123
  ...props
116
124
  }: SearchInputProps) => {
117
125
  const [isSearchMenuOpen, setIsSearchMenuOpen] = React.useState(false);
@@ -277,11 +285,9 @@ const SearchInputBase: React.FunctionComponent<SearchInputProps> = ({
277
285
 
278
286
  if (!!onSearch || attributes.length > 0 || !!onToggleAdvancedSearch) {
279
287
  if (attributes.length > 0) {
280
- return (
281
- <div className={css(className, styles.searchInput)} ref={searchInputRef} {...props}>
282
- {buildSearchTextInputGroupWithExtraButtons()}
288
+ const AdvancedSearch = (
289
+ <span>
283
290
  <AdvancedSearchMenu
284
- className={styles.searchInputMenu}
285
291
  value={value}
286
292
  parentRef={searchInputRef}
287
293
  parentInputRef={searchInputInputRef}
@@ -298,8 +304,29 @@ const SearchInputBase: React.FunctionComponent<SearchInputProps> = ({
298
304
  getAttrValueMap={getAttrValueMap}
299
305
  isSearchMenuOpen={isSearchMenuOpen}
300
306
  />
307
+ </span>
308
+ );
309
+
310
+ const AdvancedSearchWithPopper = (
311
+ <div className={css(className)} ref={searchInputRef} {...props}>
312
+ <Popper
313
+ trigger={buildSearchTextInputGroupWithExtraButtons()}
314
+ popper={AdvancedSearch}
315
+ isVisible={isSearchMenuOpen}
316
+ enableFlip={true}
317
+ appendTo={() => appendTo || searchInputRef.current}
318
+ />
301
319
  </div>
302
320
  );
321
+
322
+ const AdvancedSearchInline = (
323
+ <div className={css(className)} ref={searchInputRef} {...props}>
324
+ {buildSearchTextInputGroupWithExtraButtons()}
325
+ {AdvancedSearch}
326
+ </div>
327
+ );
328
+
329
+ return appendTo !== 'inline' ? AdvancedSearchWithPopper : AdvancedSearchInline;
303
330
  }
304
331
 
305
332
  return buildSearchTextInputGroupWithExtraButtons({ ...searchInputProps });
@@ -81,6 +81,7 @@ describe('SearchInput', () => {
81
81
  test('advanced search with custom attributes', () => {
82
82
  const { asFragment } = render(
83
83
  <SearchInput
84
+ data-testid="test-id"
84
85
  attributes={[
85
86
  { attr: 'username', display: 'Username' },
86
87
  { attr: 'firstname', display: 'First name' }
@@ -102,7 +103,43 @@ describe('SearchInput', () => {
102
103
 
103
104
  userEvent.click(screen.getByRole('button', { name: 'Search' }));
104
105
 
106
+ userEvent.click(screen.getByRole('button', { name: 'Open advanced search' }));
107
+ expect(screen.getByTestId('test-id')).toContainElement(screen.getByText('First name'))
108
+
105
109
  expect(props.onSearch).toHaveBeenCalled();
106
110
  expect(asFragment()).toMatchSnapshot();
107
111
  });
112
+
113
+ test('advanced search with custom attributes and appendTo="inline', () => {
114
+ const {container} = render(
115
+ <SearchInput
116
+ data-testid="test-id"
117
+ attributes={[
118
+ { attr: 'test', display: 'test' },
119
+ ]}
120
+ appendTo='inline'
121
+ />
122
+ );
123
+
124
+ userEvent.click(screen.getByRole('button', { name: 'Open advanced search' }));
125
+
126
+ expect(screen.getByTestId('test-id')).toContainElement(screen.getByText('test'))
127
+ });
128
+
129
+ test('advanced search with custom attributes and appendTo external DOM element', () => {
130
+ const {container} = render(
131
+ <SearchInput
132
+ data-testid="test-id"
133
+ attributes={[
134
+ { attr: 'test', display: 'test' },
135
+ ]}
136
+ appendTo={document.body}
137
+ />
138
+ );
139
+
140
+ userEvent.click(screen.getByRole('button', { name: 'Open advanced search' }));
141
+
142
+ expect(screen.getByTestId('test-id')).not.toContainElement(screen.getByText('test'))
143
+ expect(document.body).toContainElement(screen.getByText('test'))
144
+ });
108
145
  });
@@ -3,7 +3,7 @@
3
3
  exports[`SearchInput advanced search 1`] = `
4
4
  <DocumentFragment>
5
5
  <div
6
- class="pf-c-search-input"
6
+ class=""
7
7
  >
8
8
  <div
9
9
  class="pf-c-input-group"
@@ -125,7 +125,8 @@ exports[`SearchInput advanced search 1`] = `
125
125
  exports[`SearchInput advanced search with custom attributes 1`] = `
126
126
  <DocumentFragment>
127
127
  <div
128
- class="pf-c-search-input"
128
+ class=""
129
+ data-testid="test-id"
129
130
  >
130
131
  <div
131
132
  class="pf-c-input-group"
@@ -194,9 +195,9 @@ exports[`SearchInput advanced search with custom attributes 1`] = `
194
195
  </div>
195
196
  <button
196
197
  aria-disabled="false"
197
- aria-expanded="false"
198
+ aria-expanded="true"
198
199
  aria-label="Open advanced search"
199
- class="pf-c-button pf-m-control"
200
+ class="pf-c-button pf-m-control pf-m-expanded"
200
201
  data-ouia-component-id="OUIA-Generated-Button-control-8"
201
202
  data-ouia-component-type="PF4/Button"
202
203
  data-ouia-safe="true"
@@ -240,6 +241,194 @@ exports[`SearchInput advanced search with custom attributes 1`] = `
240
241
  </svg>
241
242
  </button>
242
243
  </div>
244
+ <span
245
+ class=""
246
+ style="position: absolute; left: 0px; top: 0px; z-index: 9999; width: 0px;"
247
+ >
248
+ <div
249
+ class="pf-c-panel pf-m-raised"
250
+ >
251
+ <div
252
+ class="pf-c-panel__main"
253
+ >
254
+ <div
255
+ class="pf-c-panel__main-body"
256
+ >
257
+ <form
258
+ class="pf-c-form"
259
+ novalidate=""
260
+ >
261
+ <div
262
+ class="pf-c-form__group"
263
+ >
264
+ <div
265
+ class="pf-c-form__group-label"
266
+ >
267
+ <label
268
+ class="pf-c-form__label"
269
+ for="username_0"
270
+ >
271
+ <span
272
+ class="pf-c-form__label-text"
273
+ >
274
+ Username
275
+ </span>
276
+ </label>
277
+
278
+ </div>
279
+ <div
280
+ class="pf-c-form__group-control"
281
+ >
282
+ <input
283
+ aria-invalid="false"
284
+ class="pf-c-form-control"
285
+ data-ouia-component-id="OUIA-Generated-TextInputBase-1"
286
+ data-ouia-component-type="PF4/TextInput"
287
+ data-ouia-safe="true"
288
+ id="username_0"
289
+ type="text"
290
+ value="player"
291
+ />
292
+ </div>
293
+ </div>
294
+ <div
295
+ class="pf-c-form__group"
296
+ >
297
+ <div
298
+ class="pf-c-form__group-label"
299
+ >
300
+ <label
301
+ class="pf-c-form__label"
302
+ for="firstname_1"
303
+ >
304
+ <span
305
+ class="pf-c-form__label-text"
306
+ >
307
+ First name
308
+ </span>
309
+ </label>
310
+
311
+ </div>
312
+ <div
313
+ class="pf-c-form__group-control"
314
+ >
315
+ <input
316
+ aria-invalid="false"
317
+ class="pf-c-form-control"
318
+ data-ouia-component-id="OUIA-Generated-TextInputBase-2"
319
+ data-ouia-component-type="PF4/TextInput"
320
+ data-ouia-safe="true"
321
+ id="firstname_1"
322
+ type="text"
323
+ value="john"
324
+ />
325
+ </div>
326
+ </div>
327
+ <div
328
+ class="pf-c-form__group"
329
+ >
330
+ <div
331
+ class="pf-c-form__group-label"
332
+ >
333
+ <label
334
+ class="pf-c-form__label"
335
+ for="pf-random-id-2"
336
+ >
337
+ <span
338
+ class="pf-c-form__label-text"
339
+ >
340
+ Has words
341
+ </span>
342
+ </label>
343
+
344
+ </div>
345
+ <div
346
+ class="pf-c-form__group-control"
347
+ >
348
+ <input
349
+ aria-invalid="false"
350
+ class="pf-c-form-control"
351
+ data-ouia-component-id="OUIA-Generated-TextInputBase-3"
352
+ data-ouia-component-type="PF4/TextInput"
353
+ data-ouia-safe="true"
354
+ id="pf-random-id-2"
355
+ type="text"
356
+ value=""
357
+ />
358
+ </div>
359
+ </div>
360
+ <div
361
+ class="pf-c-form__group"
362
+ >
363
+ <div
364
+ class="pf-c-form__group-control"
365
+ >
366
+ <button
367
+ aria-disabled="false"
368
+ class="pf-c-button pf-m-link pf-m-inline"
369
+ data-ouia-component-id="OUIA-Generated-Button-link-1"
370
+ data-ouia-component-type="PF4/Button"
371
+ data-ouia-safe="true"
372
+ type="button"
373
+ >
374
+ Link
375
+ <span
376
+ class="pf-c-button__icon pf-m-end"
377
+ >
378
+ <svg
379
+ aria-hidden="true"
380
+ fill="currentColor"
381
+ height="1em"
382
+ role="img"
383
+ style="vertical-align: -0.125em;"
384
+ viewBox="0 0 448 512"
385
+ width="1em"
386
+ >
387
+ <path
388
+ d="M448 80v352c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h352c26.51 0 48 21.49 48 48zm-88 16H248.029c-21.313 0-32.08 25.861-16.971 40.971l31.984 31.987L67.515 364.485c-4.686 4.686-4.686 12.284 0 16.971l31.029 31.029c4.687 4.686 12.285 4.686 16.971 0l195.526-195.526 31.988 31.991C358.058 263.977 384 253.425 384 231.979V120c0-13.255-10.745-24-24-24z"
389
+ />
390
+ </svg>
391
+ </span>
392
+ </button>
393
+ </div>
394
+ </div>
395
+ <div
396
+ class="pf-c-form__group pf-m-action"
397
+ >
398
+ <div
399
+ class="pf-c-form__group-control"
400
+ >
401
+ <div
402
+ class="pf-c-form__actions"
403
+ >
404
+ <button
405
+ aria-disabled="false"
406
+ class="pf-c-button pf-m-primary"
407
+ data-ouia-component-id="OUIA-Generated-Button-primary-1"
408
+ data-ouia-component-type="PF4/Button"
409
+ data-ouia-safe="true"
410
+ type="submit"
411
+ >
412
+ Search
413
+ </button>
414
+ <button
415
+ aria-disabled="false"
416
+ class="pf-c-button pf-m-link"
417
+ data-ouia-component-id="OUIA-Generated-Button-link-2"
418
+ data-ouia-component-type="PF4/Button"
419
+ data-ouia-safe="true"
420
+ type="reset"
421
+ >
422
+ Reset
423
+ </button>
424
+ </div>
425
+ </div>
426
+ </div>
427
+ </form>
428
+ </div>
429
+ </div>
430
+ </div>
431
+ </span>
243
432
  </div>
244
433
  </DocumentFragment>
245
434
  `;