@patternfly/react-core 4.232.13 → 4.234.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.
Files changed (119) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/esm/components/ExpandableSection/ExpandableSection.d.ts +17 -3
  3. package/dist/esm/components/ExpandableSection/ExpandableSection.d.ts.map +1 -1
  4. package/dist/esm/components/ExpandableSection/ExpandableSection.js +39 -8
  5. package/dist/esm/components/ExpandableSection/ExpandableSection.js.map +1 -1
  6. package/dist/esm/components/ExpandableSection/ExpandableSectionToggle.d.ts +2 -0
  7. package/dist/esm/components/ExpandableSection/ExpandableSectionToggle.d.ts.map +1 -1
  8. package/dist/esm/components/ExpandableSection/ExpandableSectionToggle.js +4 -4
  9. package/dist/esm/components/ExpandableSection/ExpandableSectionToggle.js.map +1 -1
  10. package/dist/esm/components/InputGroup/InputGroup.d.ts.map +1 -1
  11. package/dist/esm/components/InputGroup/InputGroup.js +5 -3
  12. package/dist/esm/components/InputGroup/InputGroup.js.map +1 -1
  13. package/dist/esm/components/MenuToggle/MenuToggle.js +1 -1
  14. package/dist/esm/components/MenuToggle/MenuToggle.js.map +1 -1
  15. package/dist/esm/components/NumberInput/NumberInput.d.ts +5 -0
  16. package/dist/esm/components/NumberInput/NumberInput.d.ts.map +1 -1
  17. package/dist/esm/components/NumberInput/NumberInput.js +5 -4
  18. package/dist/esm/components/NumberInput/NumberInput.js.map +1 -1
  19. package/dist/esm/components/TimePicker/TimePicker.d.ts +1 -0
  20. package/dist/esm/components/TimePicker/TimePicker.d.ts.map +1 -1
  21. package/dist/esm/components/TimePicker/TimePicker.js +14 -2
  22. package/dist/esm/components/TimePicker/TimePicker.js.map +1 -1
  23. package/dist/esm/components/Timestamp/Timestamp.d.ts +72 -0
  24. package/dist/esm/components/Timestamp/Timestamp.d.ts.map +1 -0
  25. package/dist/esm/components/Timestamp/Timestamp.js +33 -0
  26. package/dist/esm/components/Timestamp/Timestamp.js.map +1 -0
  27. package/dist/esm/components/Timestamp/index.d.ts +2 -0
  28. package/dist/esm/components/Timestamp/index.d.ts.map +1 -0
  29. package/dist/esm/components/Timestamp/index.js +2 -0
  30. package/dist/esm/components/Timestamp/index.js.map +1 -0
  31. package/dist/esm/components/index.d.ts +1 -0
  32. package/dist/esm/components/index.d.ts.map +1 -1
  33. package/dist/esm/components/index.js +1 -0
  34. package/dist/esm/components/index.js.map +1 -1
  35. package/dist/js/components/ExpandableSection/ExpandableSection.d.ts +17 -3
  36. package/dist/js/components/ExpandableSection/ExpandableSection.d.ts.map +1 -1
  37. package/dist/js/components/ExpandableSection/ExpandableSection.js +40 -9
  38. package/dist/js/components/ExpandableSection/ExpandableSection.js.map +1 -1
  39. package/dist/js/components/ExpandableSection/ExpandableSectionToggle.d.ts +2 -0
  40. package/dist/js/components/ExpandableSection/ExpandableSectionToggle.d.ts.map +1 -1
  41. package/dist/js/components/ExpandableSection/ExpandableSectionToggle.js +4 -4
  42. package/dist/js/components/ExpandableSection/ExpandableSectionToggle.js.map +1 -1
  43. package/dist/js/components/InputGroup/InputGroup.d.ts.map +1 -1
  44. package/dist/js/components/InputGroup/InputGroup.js +5 -3
  45. package/dist/js/components/InputGroup/InputGroup.js.map +1 -1
  46. package/dist/js/components/MenuToggle/MenuToggle.js +1 -1
  47. package/dist/js/components/MenuToggle/MenuToggle.js.map +1 -1
  48. package/dist/js/components/NumberInput/NumberInput.d.ts +5 -0
  49. package/dist/js/components/NumberInput/NumberInput.d.ts.map +1 -1
  50. package/dist/js/components/NumberInput/NumberInput.js +4 -3
  51. package/dist/js/components/NumberInput/NumberInput.js.map +1 -1
  52. package/dist/js/components/TimePicker/TimePicker.d.ts +1 -0
  53. package/dist/js/components/TimePicker/TimePicker.d.ts.map +1 -1
  54. package/dist/js/components/TimePicker/TimePicker.js +14 -2
  55. package/dist/js/components/TimePicker/TimePicker.js.map +1 -1
  56. package/dist/js/components/Timestamp/Timestamp.d.ts +72 -0
  57. package/dist/js/components/Timestamp/Timestamp.d.ts.map +1 -0
  58. package/dist/js/components/Timestamp/Timestamp.js +37 -0
  59. package/dist/js/components/Timestamp/Timestamp.js.map +1 -0
  60. package/dist/js/components/Timestamp/index.d.ts +2 -0
  61. package/dist/js/components/Timestamp/index.d.ts.map +1 -0
  62. package/dist/js/components/Timestamp/index.js +5 -0
  63. package/dist/js/components/Timestamp/index.js.map +1 -0
  64. package/dist/js/components/index.d.ts +1 -0
  65. package/dist/js/components/index.d.ts.map +1 -1
  66. package/dist/js/components/index.js +1 -0
  67. package/dist/js/components/index.js.map +1 -1
  68. package/dist/styles/base-no-reset.css +2 -2
  69. package/dist/styles/base.css +2 -2
  70. package/dist/umd/react-core.css +58 -12
  71. package/dist/umd/react-core.js +861 -770
  72. package/dist/umd/react-core.min.css +312 -266
  73. package/dist/umd/react-core.min.js +5 -5
  74. package/package.json +6 -6
  75. package/src/components/Button/examples/Button.md +55 -24
  76. package/src/components/ContextSelector/examples/ContextSelectorBasic.tsx +4 -4
  77. package/src/components/ContextSelector/examples/ContextSelectorPlainText.tsx +3 -3
  78. package/src/components/ContextSelector/examples/ContextSelectorWithFooter.tsx +4 -4
  79. package/src/components/DualListSelector/examples/DualListSelectorComposable.tsx +8 -2
  80. package/src/components/DualListSelector/examples/DualListSelectorComposableDragDrop.tsx +3 -9
  81. package/src/components/DualListSelector/examples/DualListSelectorComposableTree.tsx +3 -3
  82. package/src/components/DualListSelector/examples/DualListSelectorTreeExample.tsx +8 -5
  83. package/src/components/ExpandableSection/ExpandableSection.tsx +73 -19
  84. package/src/components/ExpandableSection/ExpandableSectionToggle.tsx +15 -9
  85. package/src/components/ExpandableSection/__tests__/ExpandableSection.test.tsx +27 -1
  86. package/src/components/ExpandableSection/examples/ExpandableSection.md +7 -0
  87. package/src/components/ExpandableSection/examples/ExpandableSectionTruncateExpansion.tsx +27 -0
  88. package/src/components/InputGroup/InputGroup.tsx +5 -3
  89. package/src/components/InputGroup/__tests__/InputGroup.test.tsx +30 -0
  90. package/src/components/MenuToggle/MenuToggle.tsx +2 -2
  91. package/src/components/NumberInput/NumberInput.tsx +14 -8
  92. package/src/components/NumberInput/__tests__/NumberInput.test.tsx +16 -0
  93. package/src/components/NumberInput/__tests__/__snapshots__/NumberInput.test.tsx.snap +292 -18
  94. package/src/components/NumberInput/examples/NumberInput.md +5 -0
  95. package/src/components/NumberInput/examples/WithStatus.tsx +59 -0
  96. package/src/components/TimePicker/TimePicker.tsx +19 -11
  97. package/src/components/Timestamp/Timestamp.tsx +134 -0
  98. package/src/components/Timestamp/__tests__/Timestamp.test.tsx +177 -0
  99. package/src/components/Timestamp/__tests__/__snapshots__/Timestamp.test.tsx.snap +17 -0
  100. package/src/components/Timestamp/examples/Timestamp.md +57 -0
  101. package/src/components/Timestamp/examples/TimestampBasicFormats.tsx +26 -0
  102. package/src/components/Timestamp/examples/TimestampCustomContent.tsx +20 -0
  103. package/src/components/Timestamp/examples/TimestampCustomFormat.tsx +6 -0
  104. package/src/components/Timestamp/examples/TimestampCustomTooltip.tsx +19 -0
  105. package/src/components/Timestamp/examples/TimestampDefault.tsx +4 -0
  106. package/src/components/Timestamp/examples/TimestampDefaultTooltip.tsx +18 -0
  107. package/src/components/Timestamp/index.ts +1 -0
  108. package/src/components/index.ts +1 -0
  109. package/src/demos/Button.md +5 -1
  110. package/src/demos/ComposableMenu/examples/ComposableActionsMenu.tsx +12 -8
  111. package/src/demos/ComposableMenu/examples/ComposableApplicationLauncher.tsx +12 -11
  112. package/src/demos/ComposableMenu/examples/ComposableContextSelector.tsx +10 -12
  113. package/src/demos/ComposableMenu/examples/ComposableDrilldownMenu.tsx +7 -7
  114. package/src/demos/ComposableMenu/examples/ComposableFlyout.tsx +8 -8
  115. package/src/demos/ComposableMenu/examples/ComposableSimpleCheckboxSelect.tsx +11 -8
  116. package/src/demos/ComposableMenu/examples/ComposableSimpleDropdown.tsx +7 -7
  117. package/src/demos/ComposableMenu/examples/ComposableSimpleSelect.tsx +17 -8
  118. package/src/demos/ComposableMenu/examples/ComposableTreeViewMenu.tsx +11 -10
  119. package/src/demos/ComposableMenu/examples/ComposableTypeaheadSelect.tsx +2 -2
@@ -270,6 +270,11 @@ class DisabledNumberInput extends React.Component {
270
270
  );
271
271
  }
272
272
  }
273
+
274
+ ```
275
+ ### With status
276
+
277
+ ```ts file="./WithStatus.tsx"
273
278
  ```
274
279
 
275
280
  ### Varying sizes
@@ -0,0 +1,59 @@
1
+ import React from 'react';
2
+ import { NumberInput, ValidatedOptions } from '@patternfly/react-core';
3
+
4
+ export const WithStatus: React.FunctionComponent = () => {
5
+ const max = 10;
6
+ const min = 0;
7
+
8
+ const [validated, setValidated] = React.useState<ValidatedOptions>(ValidatedOptions.success);
9
+ const [value, setValue] = React.useReducer((state, newVal) => Math.max(min, Math.min(max, Number(newVal))), 5);
10
+
11
+ const onPlus = () => {
12
+ const newVal = value + 1;
13
+ setValue(newVal);
14
+ validate(newVal);
15
+ };
16
+
17
+ const onMinus = () => {
18
+ const newVal = value - 1;
19
+ setValue(newVal);
20
+ validate(newVal);
21
+ };
22
+
23
+ const onChange = event => {
24
+ const newVal = isNaN(event.target.value) ? 5 : Number(event.target.value);
25
+ setValue(newVal);
26
+ validate(newVal);
27
+ };
28
+
29
+ const validate = newVal => {
30
+ const diff = Math.abs(5 - newVal);
31
+ if (diff > 3) {
32
+ setValidated(ValidatedOptions.error);
33
+ } else if (diff > 1) {
34
+ setValidated(ValidatedOptions.warning);
35
+ } else {
36
+ setValidated(ValidatedOptions.success);
37
+ }
38
+ };
39
+ return (
40
+ <>
41
+ In the following example, the validated status will update based on the value of the number input and how far from
42
+ the number 5 it is.
43
+ <br />
44
+ <NumberInput
45
+ validated={validated}
46
+ value={value}
47
+ min={0}
48
+ max={10}
49
+ onMinus={onMinus}
50
+ onPlus={onPlus}
51
+ onChange={onChange}
52
+ inputName="input"
53
+ inputAriaLabel="number input"
54
+ minusBtnAriaLabel="minus"
55
+ plusBtnAriaLabel="plus"
56
+ />
57
+ </>
58
+ );
59
+ };
@@ -107,6 +107,7 @@ export class TimePicker extends React.Component<TimePickerProps, TimePickerState
107
107
  inputProps: {},
108
108
  minTime: '',
109
109
  maxTime: '',
110
+ isOpen: false,
110
111
  setIsOpen: () => {}
111
112
  };
112
113
 
@@ -490,24 +491,31 @@ export class TimePicker extends React.Component<TimePickerProps, TimePickerState
490
491
  />
491
492
  );
492
493
 
494
+ let calculatedAppendTo;
495
+ switch (menuAppendTo) {
496
+ case 'inline':
497
+ calculatedAppendTo = () => this.toggleRef.current;
498
+ break;
499
+ case 'parent':
500
+ calculatedAppendTo = getParentElement;
501
+ break;
502
+ default:
503
+ calculatedAppendTo = menuAppendTo as HTMLElement;
504
+ }
505
+
493
506
  return (
494
507
  <div ref={this.baseComponentRef} className={css(datePickerStyles.datePicker, className)}>
495
508
  <div className={css(datePickerStyles.datePickerInput)} style={style} {...props}>
496
509
  <InputGroup>
497
510
  <div id={randomId}>
498
511
  <div ref={this.toggleRef} style={{ paddingLeft: '0' }}>
499
- {menuAppendTo !== 'inline' ? (
500
- <Popper
501
- appendTo={menuAppendTo === 'parent' ? getParentElement() : menuAppendTo}
502
- trigger={textInput}
503
- popper={menuContainer}
504
- isVisible={isTimeOptionsOpen}
505
- />
506
- ) : (
507
- textInput
508
- )}
512
+ <Popper
513
+ appendTo={calculatedAppendTo}
514
+ trigger={textInput}
515
+ popper={menuContainer}
516
+ isVisible={isTimeOptionsOpen}
517
+ />
509
518
  </div>
510
- {isTimeOptionsOpen && menuAppendTo === 'inline' && menuContainer}
511
519
  </div>
512
520
  </InputGroup>
513
521
  {isInvalid && (
@@ -0,0 +1,134 @@
1
+ import * as React from 'react';
2
+ import styles from '@patternfly/react-styles/css/components/Timestamp/timestamp';
3
+ import { css } from '@patternfly/react-styles';
4
+ import { Tooltip } from '../Tooltip';
5
+
6
+ export enum TimestampFormat {
7
+ full = 'full',
8
+ long = 'long',
9
+ medium = 'medium',
10
+ short = 'short'
11
+ }
12
+
13
+ export enum TimestampTooltipVariant {
14
+ default = 'default',
15
+ custom = 'custom'
16
+ }
17
+
18
+ export interface TimestampTooltip {
19
+ /** The variant of the tooltip. The "default" variant displays the date passed into
20
+ * the timestamp's date prop as a UTC string.
21
+ */
22
+ variant: 'default' | 'custom';
23
+ /** Content displayed in the tooltip when using the "custom" variant. */
24
+ content?: React.ReactNode;
25
+ /** Additional props passed to the tooltip. */
26
+ tooltipProps?: any;
27
+ /** A custom suffix to apply to a "default" variant tooltip. */
28
+ suffix?: string;
29
+ }
30
+
31
+ export interface TimestampProps extends React.HTMLProps<HTMLSpanElement> {
32
+ /** Displays custom content inside the timestamp, such as a relative time. This prop will
33
+ * override the default content that is displayed. Custom content will not be affected by
34
+ * any props that format or add to displayed content.
35
+ */
36
+ children?: React.ReactNode;
37
+ /** Class to add to the outer span. */
38
+ className?: string;
39
+ /** Applies custom formatting to the displayed date and/or time. Passing this prop in will
40
+ * override the dateFormat and timeFormat props.
41
+ */
42
+ customFormat?: { [key: string]: string };
43
+ /** Determines the default content that is displayed inside the timestamp and the value of
44
+ * the inner time element's datetime attribute. */
45
+ date?: Date;
46
+ /** Determines the format of the displayed date in the timestamp and UTC tooltip. Examples:
47
+ * "Full" => Tuesday, August 9, 2022;
48
+ * "Long" => August 9, 2022;
49
+ * "Medium" => Aug 9, 2022;
50
+ * "Short" => 8/9/22
51
+ */
52
+ dateFormat?: 'full' | 'long' | 'medium' | 'short';
53
+ /** Applies a custom suffix to the displayed content, usually after the time, such as a
54
+ * custom time zone.
55
+ */
56
+ displaySuffix?: string;
57
+ /** Flag for displaying the time in a 12 hour format. If this prop is not passed in,
58
+ * the hour format will be based on the locale prop's value.
59
+ */
60
+ is12Hour?: boolean;
61
+ /** Determines which locale to use in the displayed content. Defaults to the current locale
62
+ * when this prop is not passed in. For more information about locale's:
63
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation
64
+ */
65
+ locale?: string;
66
+ /** Determines the format of the displayed time in the timestamp and UTC tooltip. Examples:
67
+ * "Full" => 11:25:00 AM Eastern Daylight Time
68
+ * "Long" => 11:25:00 AM EDT
69
+ * "Medium" => 11:25:00 AM
70
+ * "Short" => 11:25 AM
71
+ */
72
+ timeFormat?: 'full' | 'long' | 'medium' | 'short';
73
+ /** Adds a tooltip to the timestamp. */
74
+ tooltip?: TimestampTooltip;
75
+ }
76
+
77
+ export const Timestamp: React.FunctionComponent<TimestampProps> = ({
78
+ children,
79
+ className,
80
+ customFormat,
81
+ date: dateProp = new Date(),
82
+ dateFormat,
83
+ displaySuffix = '',
84
+ is12Hour,
85
+ locale,
86
+ timeFormat,
87
+ tooltip,
88
+ ...props
89
+ }: TimestampProps) => {
90
+ const hasTimeFormat = timeFormat && !customFormat;
91
+ const formatOptions = {
92
+ ...(dateFormat && !customFormat && { dateStyle: dateFormat }),
93
+ ...(customFormat && { ...customFormat }),
94
+ ...(is12Hour !== undefined && { hour12: is12Hour })
95
+ };
96
+
97
+ const dateAsLocaleString = new Date(dateProp).toLocaleString(locale, {
98
+ ...formatOptions,
99
+ ...(hasTimeFormat && { timeStyle: timeFormat })
100
+ });
101
+ const defaultDisplay = `${dateAsLocaleString}${displaySuffix ? ' ' + displaySuffix : ''}`;
102
+
103
+ const utcTimeFormat = timeFormat !== 'short' ? 'medium' : 'short';
104
+ const convertToUTCString = (date: Date) => new Date(date).toUTCString().slice(0, -3);
105
+ const utcDateString = new Date(convertToUTCString(dateProp)).toLocaleString(locale, {
106
+ ...formatOptions,
107
+ ...(hasTimeFormat && { timeStyle: utcTimeFormat })
108
+ });
109
+ const defaultTooltipContent = `${utcDateString}${tooltip?.suffix ? ' ' + tooltip.suffix : ' UTC'}`;
110
+
111
+ const timestamp = (
112
+ <span
113
+ className={css(styles.timestamp, tooltip && styles.modifiers.helpText, className)}
114
+ {...(tooltip && { tabIndex: 0 })}
115
+ {...props}
116
+ >
117
+ <time className="pf-c-timestamp__text" dateTime={props.dateTime || new Date(dateProp).toISOString()}>
118
+ {!children ? defaultDisplay : children}
119
+ </time>
120
+ </span>
121
+ );
122
+
123
+ return tooltip ? (
124
+ <Tooltip
125
+ content={tooltip.variant === TimestampTooltipVariant.default ? defaultTooltipContent : tooltip.content}
126
+ {...tooltip.tooltipProps}
127
+ >
128
+ {timestamp}
129
+ </Tooltip>
130
+ ) : (
131
+ timestamp
132
+ );
133
+ };
134
+ Timestamp.displayName = 'Timestamp';
@@ -0,0 +1,177 @@
1
+ import * as React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { Timestamp, TimestampFormat, TimestampTooltipVariant } from '../Timestamp';
4
+
5
+ jest.mock('../../Tooltip', () => ({
6
+ Tooltip: ({ content, children, ...props }) => (
7
+ <div data-testid="timestamp-tooltip-mock" {...props}>
8
+ <div data-testid="timestamp-tooltip-mock-content">{content}</div>
9
+ {children}
10
+ </div>
11
+ )
12
+ }));
13
+
14
+ test('Matches snapshot', () => {
15
+ /** Due to how the datetime attribute is contstructed internally, dateTime must be
16
+ * manually passed for this snapshot to pass on GitHub.
17
+ */
18
+ const { asFragment } = render(<Timestamp dateTime="2022-01-01T00:00:00.000Z" date={new Date(2022, 0, 1)} />);
19
+
20
+ expect(asFragment()).toMatchSnapshot();
21
+ });
22
+
23
+ test('Renders component', () => {
24
+ render(
25
+ <div data-testid="timestamp-container">
26
+ <Timestamp />
27
+ </div>
28
+ );
29
+
30
+ expect(screen.getByTestId('timestamp-container').firstChild).toBeVisible();
31
+ });
32
+
33
+ test('Renders with current date by default with default formatting', () => {
34
+ render(<Timestamp />);
35
+
36
+ expect(screen.getByText(new Date().toLocaleString())).toBeInTheDocument();
37
+ });
38
+
39
+ test('Renders passed in date with default formatting', () => {
40
+ render(<Timestamp date={new Date(2022, 0, 1)} />);
41
+
42
+ expect(screen.getByText('1/1/2022, 12:00:00 AM')).toBeInTheDocument();
43
+ });
44
+
45
+ test('Renders with custom formatting when dateFormat and timeFormat are passed in', () => {
46
+ render(
47
+ <Timestamp date={new Date(2022, 0, 1)} dateFormat={TimestampFormat.full} timeFormat={TimestampFormat.short} />
48
+ );
49
+
50
+ expect(screen.getByText('Saturday, January 1, 2022 at 12:00 AM')).toBeInTheDocument();
51
+ });
52
+
53
+ test('Renders with only date when dateFormat is passed in', () => {
54
+ render(<Timestamp date={new Date('1 Jan 2022 00:00:00 EST')} dateFormat={TimestampFormat.full} />);
55
+
56
+ expect(screen.getByText('Saturday, January 1, 2022')).toBeInTheDocument();
57
+ });
58
+
59
+ test('Renders with only time when timeFormat is passed in', () => {
60
+ render(<Timestamp date={new Date(2022, 0, 1)} timeFormat={TimestampFormat.short} />);
61
+
62
+ expect(screen.getByText('12:00 AM')).toBeInTheDocument();
63
+ });
64
+
65
+ test('Renders with custom formatting when customFormat is passed in', () => {
66
+ render(
67
+ <Timestamp
68
+ date={new Date(2022, 0, 1)}
69
+ customFormat={{ year: '2-digit', month: 'short', weekday: 'short', day: 'numeric', hour: 'numeric' }}
70
+ />
71
+ );
72
+
73
+ expect(screen.getByText('Sat, Jan 1, 22, 12 AM')).toBeInTheDocument();
74
+ });
75
+
76
+ test('Renders with custom content', () => {
77
+ render(<Timestamp>2 days ago</Timestamp>);
78
+
79
+ expect(screen.getByText('2 days ago')).toBeInTheDocument();
80
+ });
81
+
82
+ test('Renders with a custom suffix when displaySuffix is passed in', () => {
83
+ render(<Timestamp date={new Date(2022, 0, 1)} displaySuffix="US Eastern" />);
84
+
85
+ expect(screen.getByText('1/1/2022, 12:00:00 AM US Eastern')).toBeInTheDocument();
86
+ });
87
+
88
+ test('Renders with 12 hour time when is12Hour is passed', () => {
89
+ render(<Timestamp date={new Date(2022, 0, 1, 13, 0)} is12Hour />);
90
+
91
+ expect(screen.getByText('1/1/2022, 1:00:00 PM')).toBeInTheDocument();
92
+ });
93
+
94
+ test('Renders with 24 hour time when is12Hour is set to false', () => {
95
+ render(<Timestamp date={new Date(2022, 0, 1, 13, 0)} is12Hour={false} />);
96
+
97
+ expect(screen.getByText('1/1/2022, 13:00:00')).toBeInTheDocument();
98
+ });
99
+
100
+ test('Renders with locale passed in', () => {
101
+ render(<Timestamp date={new Date(2022, 1, 1)} locale="en-GB" />);
102
+
103
+ expect(screen.getByText('01/02/2022, 00:00:00')).toBeInTheDocument();
104
+ });
105
+
106
+ test('Renders with 12 hour time by default for US locale', () => {
107
+ render(<Timestamp date={new Date(2022, 1, 1, 13, 0)} locale="en-US" />);
108
+
109
+ expect(screen.getByText('2/1/2022, 1:00:00 PM')).toBeInTheDocument();
110
+ });
111
+
112
+ test('Renders with 24 hour time for US locale when is12Hour is false', () => {
113
+ render(<Timestamp date={new Date(2022, 1, 1, 13, 0)} locale="en-US" is12Hour={false} />);
114
+
115
+ expect(screen.getByText('2/1/2022, 13:00:00')).toBeInTheDocument();
116
+ });
117
+
118
+ test('Renders with 12 hour time for a 24 hour locale when is12Hour is passed', () => {
119
+ render(<Timestamp date={new Date(2022, 1, 1, 13, 0)} locale="en-GB" is12Hour />);
120
+
121
+ expect(screen.getByText('01/02/2022, 1:00:00 pm')).toBeInTheDocument();
122
+ });
123
+
124
+ test('Renders with pf-c-timestamp by default', () => {
125
+ render(<Timestamp date={new Date(2022, 0, 1)} />);
126
+
127
+ expect(screen.getByText('1/1/2022, 12:00:00 AM').parentElement).toHaveClass('pf-c-timestamp');
128
+ });
129
+
130
+ test('Renders with pf-c-timestamp__text by default', () => {
131
+ render(<Timestamp date={new Date(2022, 0, 1)} />);
132
+
133
+ expect(screen.getByText('1/1/2022, 12:00:00 AM')).toHaveClass('pf-c-timestamp__text');
134
+ });
135
+
136
+ test('Renders with custom class names', () => {
137
+ render(<Timestamp date={new Date(2022, 0, 1)} className="custom-time-class" />);
138
+
139
+ expect(screen.getByText('1/1/2022, 12:00:00 AM').parentElement).toHaveClass('custom-time-class');
140
+ });
141
+
142
+ test('Renders with pf-m-help-text class when tooltip is passed in with default variant', () => {
143
+ render(<Timestamp date={new Date(2022, 0, 1)} tooltip={{ variant: TimestampTooltipVariant.default }} />);
144
+
145
+ expect(screen.getByText('1/1/2022, 12:00:00 AM').parentElement).toHaveClass('pf-m-help-text');
146
+ });
147
+
148
+ test('Renders with pf-m-help-text class when tooltip is passed in with custom variant', () => {
149
+ render(<Timestamp date={new Date(2022, 0, 1)} tooltip={{ variant: TimestampTooltipVariant.custom }} />);
150
+
151
+ expect(screen.getByText('1/1/2022, 12:00:00 AM').parentElement).toHaveClass('pf-m-help-text');
152
+ });
153
+
154
+ test('Renders with default tooltip content for default variant', () => {
155
+ render(
156
+ <Timestamp date={new Date('1 Jan 2022 00:00:00 EST')} tooltip={{ variant: TimestampTooltipVariant.default }} />
157
+ );
158
+
159
+ expect(screen.getByText('1/1/2022, 5:00:00 AM UTC')).toBeInTheDocument();
160
+ });
161
+
162
+ test('Renders with custom tooltip suffix for default variant', () => {
163
+ render(
164
+ <Timestamp
165
+ date={new Date('1 Jan 2022 00:00:00 EST')}
166
+ tooltip={{ variant: TimestampTooltipVariant.default, suffix: 'Coordinated Universal Time' }}
167
+ />
168
+ );
169
+
170
+ expect(screen.getByText('1/1/2022, 5:00:00 AM Coordinated Universal Time')).toBeInTheDocument();
171
+ });
172
+
173
+ test('Renders with custom tooltip content', () => {
174
+ render(<Timestamp tooltip={{ variant: TimestampTooltipVariant.custom, content: 'Custom tooltip content' }} />);
175
+
176
+ expect(screen.getByText('Custom tooltip content')).toBeInTheDocument();
177
+ });
@@ -0,0 +1,17 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Matches snapshot 1`] = `
4
+ <DocumentFragment>
5
+ <span
6
+ class="pf-c-timestamp"
7
+ datetime="2022-01-01T00:00:00.000Z"
8
+ >
9
+ <time
10
+ class="pf-c-timestamp__text"
11
+ datetime="2022-01-01T00:00:00.000Z"
12
+ >
13
+ 1/1/2022, 12:00:00 AM
14
+ </time>
15
+ </span>
16
+ </DocumentFragment>
17
+ `;
@@ -0,0 +1,57 @@
1
+ ---
2
+ id: Timestamp
3
+ section: components
4
+ cssPrefix: pf-c-timestamp
5
+ propComponents: ['Timestamp', 'TimestampTooltip']
6
+ beta: true
7
+ ---
8
+
9
+ ## Examples
10
+
11
+ ### Default
12
+
13
+ By default, a timestamp will display the current date and time based on the current locale if the `date` prop is not passed in.
14
+
15
+ ```ts file="./TimestampDefault.tsx"
16
+ ```
17
+
18
+ ### Basic formats
19
+
20
+ The format of the displayed content can be customized by passing in the `dateFormat` and/or `timeFormat` props. Passing in only one of the props will display only the date or time, depending on which prop is passed in. The possible options are "full", "long", "medium", and "short".
21
+
22
+ You can also pass in the `displaySuffix` prop to display a custom suffix at the end of the displayed content. This will not override a timezone that is already displayed from the applied time format.
23
+
24
+ ```ts file="./TimestampBasicFormats.tsx"
25
+ ```
26
+
27
+ ### Custom format
28
+
29
+ The format of the displayed content can be further customized by passing in the `customFormat` prop. Read [datetime format options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options) for a list of options that can be passed in.
30
+
31
+ ```ts file="./TimestampCustomFormat.tsx"
32
+ ```
33
+
34
+ ### Default tooltip
35
+
36
+ To render a tooltip that displays the timestamp content as a UTC time, you can pass in the `tooltip` prop with a variant of "default". The format of the default tooltip content will match the format of the timestamp content.
37
+
38
+ You can customize the suffix of this default tooltip variant by passing in `suffix` to the `tooltip` prop.
39
+
40
+ ```ts file="./TimestampDefaultTooltip.tsx"
41
+ ```
42
+
43
+ ### Custom content
44
+
45
+ To display custom content, such as a relative time or prefacing text, you can pass in content to the `children` prop.
46
+
47
+ When also rendering a default tooltip with the `tooltip` prop, you can pass in the `dateFormat` and/or `timeFormat` props to customize the tooltip content without affecting the custom timestamp content.
48
+
49
+ ```ts file="TimestampCustomContent.tsx"
50
+ ```
51
+
52
+ ### Custom tooltip
53
+
54
+ By passing in `variant="custom"` and `content` to the `tooltip` prop, you can display custom content within the timestamp's tooltip.
55
+
56
+ ```ts file="TimestampCustomTooltip.tsx"
57
+ ```
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import { Timestamp, TimestampFormat } from '@patternfly/react-core';
3
+
4
+ export const TimestampBasicFormats: React.FunctionComponent = () => {
5
+ const currentDate = new Date();
6
+
7
+ return (
8
+ <>
9
+ <Timestamp date={currentDate} dateFormat={TimestampFormat.full} timeFormat={TimestampFormat.full} />
10
+ <br />
11
+ <br />
12
+ <Timestamp date={currentDate} dateFormat={TimestampFormat.full} />
13
+ <br />
14
+ <br />
15
+ <Timestamp date={currentDate} timeFormat={TimestampFormat.full} />
16
+ <br />
17
+ <br />
18
+ <Timestamp
19
+ date={currentDate}
20
+ dateFormat={TimestampFormat.medium}
21
+ timeFormat={TimestampFormat.short}
22
+ displaySuffix="US Eastern"
23
+ />
24
+ </>
25
+ );
26
+ };
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { Timestamp, TimestampFormat, TimestampTooltipVariant } from '@patternfly/react-core';
3
+
4
+ export const TimestampCustomContent: React.FunctionComponent = () => (
5
+ <>
6
+ <Timestamp date={new Date(2022, 7, 9, 14, 57, 0)} tooltip={{ variant: TimestampTooltipVariant.default }}>
7
+ 1 hour ago
8
+ </Timestamp>
9
+ <br />
10
+ <br />
11
+ <Timestamp
12
+ date={new Date(2022, 7, 9, 14, 57, 0)}
13
+ dateFormat={TimestampFormat.medium}
14
+ timeFormat={TimestampFormat.short}
15
+ tooltip={{ variant: TimestampTooltipVariant.default }}
16
+ >
17
+ Last updated August 9th, 2022 at 2:57 PM EDT
18
+ </Timestamp>
19
+ </>
20
+ );
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { Timestamp } from '@patternfly/react-core';
3
+
4
+ export const TimestampCustomFormat: React.FunctionComponent = () => (
5
+ <Timestamp customFormat={{ year: '2-digit', month: 'short', weekday: 'short', day: 'numeric', hour: 'numeric' }} />
6
+ );
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { Timestamp, TimestampTooltipVariant } from '@patternfly/react-core';
3
+
4
+ export const TimestampCustomTooltip: React.FunctionComponent = () => (
5
+ <>
6
+ <Timestamp
7
+ date={new Date(2022, 7, 9, 14, 57, 0)}
8
+ tooltip={{ variant: TimestampTooltipVariant.custom, content: 'Last updated on August 9th, 2022 - 2:57 PM UTC' }}
9
+ />
10
+ <br />
11
+ <br />
12
+ <Timestamp
13
+ date={new Date(2022, 9, 31)}
14
+ tooltip={{ variant: TimestampTooltipVariant.custom, content: '31st of October, 2022' }}
15
+ >
16
+ Halloween
17
+ </Timestamp>
18
+ </>
19
+ );
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { Timestamp } from '@patternfly/react-core';
3
+
4
+ export const TimestampDefault: React.FunctionComponent = () => <Timestamp />;
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { Timestamp, TimestampTooltipVariant } from '@patternfly/react-core';
3
+
4
+ export const TimestampDefaultTooltip: React.FunctionComponent = () => {
5
+ const currentDate = new Date();
6
+
7
+ return (
8
+ <>
9
+ <Timestamp date={currentDate} tooltip={{ variant: TimestampTooltipVariant.default }} />
10
+ <br />
11
+ <br />
12
+ <Timestamp
13
+ date={currentDate}
14
+ tooltip={{ variant: TimestampTooltipVariant.default, suffix: 'Coordinated Universal Time' }}
15
+ />
16
+ </>
17
+ );
18
+ };
@@ -0,0 +1 @@
1
+ export * from './Timestamp';
@@ -73,6 +73,7 @@ export * from './TextArea';
73
73
  export * from './TextInput';
74
74
  export * from './Tile';
75
75
  export * from './TimePicker';
76
+ export * from './Timestamp';
76
77
  export * from './Title';
77
78
  export * from './ToggleGroup';
78
79
  export * from './Toolbar';
@@ -5,10 +5,14 @@ section: components
5
5
 
6
6
  import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle-icon';
7
7
 
8
- ## Demos
8
+ ## Demos
9
9
 
10
10
  ### Progress button
11
11
 
12
+ The following demo shows the intended flow for a button that visually indicates progress. This example demonstrates a login process, which updates the button label based on the `loginState`.
13
+
14
+ Please note that only the button can be interacted with in this example. The username and password input fields cannot be edited as the focus is on the button behavior.
15
+
12
16
  ```ts
13
17
  import React from 'react';
14
18
  import { Form, FormGroup, ActionGroup, InputGroup, TextInput, Button } from '@patternfly/react-core';