@openedx/paragon 22.16.2 → 22.18.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 (42) hide show
  1. package/dist/Modal/ModalDialog.d.ts +2 -2
  2. package/dist/Modal/ModalDialog.js +2 -2
  3. package/dist/Modal/ModalDialog.js.map +1 -1
  4. package/dist/ProductTour/Checkpoint.js +23 -16
  5. package/dist/ProductTour/Checkpoint.js.map +1 -1
  6. package/dist/ProductTour/Checkpoint.scss +8 -36
  7. package/dist/ProductTour/CheckpointActionRow.js +17 -21
  8. package/dist/ProductTour/CheckpointActionRow.js.map +1 -1
  9. package/dist/ProductTour/CheckpointHeader.js +57 -0
  10. package/dist/ProductTour/CheckpointHeader.js.map +1 -0
  11. package/dist/ProductTour/index.js +120 -20
  12. package/dist/ProductTour/index.js.map +1 -1
  13. package/dist/ProductTour/messages.js +10 -0
  14. package/dist/paragon.css +1 -1
  15. package/dist/withDeprecatedProps.js +11 -3
  16. package/dist/withDeprecatedProps.js.map +1 -1
  17. package/package.json +1 -1
  18. package/src/Modal/ModalDialog.tsx +3 -3
  19. package/src/Modal/README.md +1 -1
  20. package/src/Modal/alert-modal.mdx +4 -0
  21. package/src/Modal/fullscreen-modal.mdx +1 -0
  22. package/src/Modal/marketing-modal.mdx +1 -0
  23. package/src/Modal/modal-dialog.mdx +2 -0
  24. package/src/Modal/standard-modal.mdx +1 -0
  25. package/src/Modal/tests/AlertModal.test.jsx +4 -0
  26. package/src/Modal/tests/ModalDialog.test.tsx +3 -0
  27. package/src/ProductTour/Checkpoint.jsx +22 -16
  28. package/src/ProductTour/Checkpoint.scss +8 -36
  29. package/src/ProductTour/Checkpoint.test.jsx +20 -53
  30. package/src/ProductTour/CheckpointActionRow.jsx +32 -32
  31. package/src/ProductTour/CheckpointHeader.jsx +60 -0
  32. package/src/ProductTour/ProductTour.test.jsx +69 -60
  33. package/src/ProductTour/README.md +11 -3
  34. package/src/ProductTour/index.jsx +125 -17
  35. package/src/ProductTour/messages.js +10 -0
  36. package/src/withDeprecatedProps.tsx +10 -3
  37. package/dist/ProductTour/CheckpointBreadcrumbs.js +0 -37
  38. package/dist/ProductTour/CheckpointBreadcrumbs.js.map +0 -1
  39. package/dist/TransitionReplace/DemoTransitionReplace.js +0 -32
  40. package/dist/TransitionReplace/DemoTransitionReplace.js.map +0 -1
  41. package/src/ProductTour/CheckpointBreadcrumbs.jsx +0 -45
  42. package/src/TransitionReplace/DemoTransitionReplace.jsx +0 -57
@@ -51,9 +51,17 @@ function withDeprecatedProps(WrappedComponent, componentName, deprecatedProps) {
51
51
  }
52
52
  break;
53
53
  case DeprTypes.MOVED_AND_FORMAT:
54
- this.warn(`${componentName}: The prop '${propName}' has been moved to '${newName}' and expects a new format. ${message}`);
55
- acc[newName] = transform(this.props[propName], this.props);
56
- break;
54
+ {
55
+ const propValue = this.props[propName];
56
+ let warningMessage = `${componentName}: The prop '${propName}' has been moved to '${newName}'`;
57
+ if (expect && !expect(propValue)) {
58
+ warningMessage += ' and expects a new format';
59
+ }
60
+ warningMessage += message ? `. ${message}` : '';
61
+ this.warn(warningMessage);
62
+ acc[newName] = transform ? transform(propValue, this.props) : propValue;
63
+ break;
64
+ }
57
65
  default:
58
66
  acc[propName] = this.props[propName];
59
67
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"withDeprecatedProps.js","names":["React","DeprTypes","withDeprecatedProps","WrappedComponent","componentName","deprecatedProps","WithDeprecatedProps","Component","displayName","constructor","props","transformProps","bind","warn","message","process","env","NODE_ENV","console","acc","propName","undefined","deprType","newName","expect","transform","MOVED","REMOVED","FORMAT","MOVED_AND_FORMAT","render","children","transformedProps","Object","keys","reduce","createElement"],"sources":["../src/withDeprecatedProps.tsx"],"sourcesContent":["/* eslint no-console: 0 */\nimport React from 'react';\n\nexport enum DeprTypes {\n MOVED = 'MOVED',\n REMOVED = 'REMOVED',\n FORMAT = 'FORMAT',\n MOVED_AND_FORMAT = 'MOVED_AND_FORMAT',\n}\n\nexport interface DeprecatedProps extends Record<string, any> {\n deprType: DeprTypes,\n newName?: string,\n expect?: (propValue: any) => boolean,\n transform?: (propValue: any, allProps: Record<string, any>) => any,\n message?: string,\n}\n\nfunction withDeprecatedProps<T extends Record<string, any>>(\n WrappedComponent: React.ComponentType<any>,\n componentName: string,\n deprecatedProps: Record<string, DeprecatedProps>,\n) : any {\n class WithDeprecatedProps extends React.Component<T> {\n // eslint-disable-next-line react/static-property-placement\n public static displayName = `withDeprecatedProps(${componentName})`;\n\n constructor(props: T) {\n super(props);\n this.transformProps = this.transformProps.bind(this);\n }\n\n warn(message: string) {\n if (process.env.NODE_ENV === 'development') {\n if (console) { console.warn(`[Deprecated] ${message}`); }\n }\n }\n\n transformProps(acc: Record<string, any>, propName: string) : Record<string, any> {\n if (deprecatedProps[propName] === undefined) {\n acc[propName] = this.props[propName];\n return acc;\n }\n\n const {\n deprType,\n newName,\n expect,\n transform,\n message,\n } = deprecatedProps[propName];\n\n switch (deprType) {\n case DeprTypes.MOVED:\n this.warn(`${componentName}: The prop '${propName}' has been moved to '${newName}'.`);\n acc[newName!] = this.props[propName];\n break;\n case DeprTypes.REMOVED:\n this.warn(`${componentName}: The prop '${propName}' has been removed. '${message}'`);\n break;\n case DeprTypes.FORMAT:\n if (!expect!(this.props[propName])) {\n this.warn(`${componentName}: The prop '${propName}' expects a new format. ${message}`);\n acc[propName] = transform!(this.props[propName], this.props);\n } else {\n acc[propName] = this.props[propName];\n }\n break;\n case DeprTypes.MOVED_AND_FORMAT:\n this.warn(`${componentName}: The prop '${propName}' has been moved to '${newName}' and expects a new format. ${message}`);\n acc[newName!] = transform!(this.props[propName], this.props);\n break;\n default:\n acc[propName] = this.props[propName];\n break;\n }\n\n return acc;\n }\n\n render() {\n const { children, ...transformedProps } = Object\n .keys(this.props)\n .reduce(this.transformProps, {});\n\n return (\n <WrappedComponent {...transformedProps as T}>\n {this.props.children || children}\n </WrappedComponent>\n );\n }\n }\n\n return WithDeprecatedProps;\n}\n\nexport default withDeprecatedProps;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"withDeprecatedProps.js","names":["React","DeprTypes","withDeprecatedProps","WrappedComponent","componentName","deprecatedProps","WithDeprecatedProps","Component","displayName","constructor","props","transformProps","bind","warn","message","process","env","NODE_ENV","console","acc","propName","undefined","deprType","newName","expect","transform","MOVED","REMOVED","FORMAT","MOVED_AND_FORMAT","propValue","warningMessage","render","children","transformedProps","Object","keys","reduce","createElement"],"sources":["../src/withDeprecatedProps.tsx"],"sourcesContent":["/* eslint no-console: 0 */\nimport React from 'react';\n\nexport enum DeprTypes {\n MOVED = 'MOVED',\n REMOVED = 'REMOVED',\n FORMAT = 'FORMAT',\n MOVED_AND_FORMAT = 'MOVED_AND_FORMAT',\n}\n\nexport interface DeprecatedProps extends Record<string, any> {\n deprType: DeprTypes,\n newName?: string,\n expect?: (propValue: any) => boolean,\n transform?: (propValue: any, allProps: Record<string, any>) => any,\n message?: string,\n}\n\nfunction withDeprecatedProps<T extends Record<string, any>>(\n WrappedComponent: React.ComponentType<any>,\n componentName: string,\n deprecatedProps: Record<string, DeprecatedProps>,\n) : any {\n class WithDeprecatedProps extends React.Component<T> {\n // eslint-disable-next-line react/static-property-placement\n public static displayName = `withDeprecatedProps(${componentName})`;\n\n constructor(props: T) {\n super(props);\n this.transformProps = this.transformProps.bind(this);\n }\n\n warn(message: string) {\n if (process.env.NODE_ENV === 'development') {\n if (console) { console.warn(`[Deprecated] ${message}`); }\n }\n }\n\n transformProps(acc: Record<string, any>, propName: string) : Record<string, any> {\n if (deprecatedProps[propName] === undefined) {\n acc[propName] = this.props[propName];\n return acc;\n }\n\n const {\n deprType,\n newName,\n expect,\n transform,\n message,\n } = deprecatedProps[propName];\n\n switch (deprType) {\n case DeprTypes.MOVED:\n this.warn(`${componentName}: The prop '${propName}' has been moved to '${newName}'.`);\n acc[newName!] = this.props[propName];\n break;\n case DeprTypes.REMOVED:\n this.warn(`${componentName}: The prop '${propName}' has been removed. '${message}'`);\n break;\n case DeprTypes.FORMAT:\n if (!expect!(this.props[propName])) {\n this.warn(`${componentName}: The prop '${propName}' expects a new format. ${message}`);\n acc[propName] = transform!(this.props[propName], this.props);\n } else {\n acc[propName] = this.props[propName];\n }\n break;\n case DeprTypes.MOVED_AND_FORMAT: {\n const propValue = this.props[propName];\n let warningMessage = `${componentName}: The prop '${propName}' has been moved to '${newName}'`;\n if (expect && !expect(propValue)) {\n warningMessage += ' and expects a new format';\n }\n warningMessage += message ? `. ${message}` : '';\n this.warn(warningMessage);\n acc[newName!] = transform ? transform(propValue, this.props) : propValue;\n break;\n }\n default:\n acc[propName] = this.props[propName];\n break;\n }\n\n return acc;\n }\n\n render() {\n const { children, ...transformedProps } = Object\n .keys(this.props)\n .reduce(this.transformProps, {});\n\n return (\n <WrappedComponent {...transformedProps as T}>\n {this.props.children || children}\n </WrappedComponent>\n );\n }\n }\n\n return WithDeprecatedProps;\n}\n\nexport default withDeprecatedProps;\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openedx/paragon",
3
- "version": "22.16.2",
3
+ "version": "22.18.0",
4
4
  "description": "Accessible, responsive UI component library based on Bootstrap.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -53,7 +53,7 @@ interface Props {
53
53
  /** Specifies the z-index of the modal */
54
54
  zIndex?: number;
55
55
  /** Specifies whether overflow is visible in the modal */
56
- isOverflowVisible?: boolean;
56
+ isOverflowVisible: boolean;
57
57
  }
58
58
 
59
59
  function ModalDialog({
@@ -70,7 +70,7 @@ function ModalDialog({
70
70
  isFullscreenOnMobile = false,
71
71
  isBlocking = false,
72
72
  zIndex,
73
- isOverflowVisible = true,
73
+ isOverflowVisible,
74
74
  }: Props) {
75
75
  const isMobile = useMediaQuery({ query: '(max-width: 767.98px)' });
76
76
  const showFullScreen = (isFullscreenOnMobile && isMobile);
@@ -163,7 +163,7 @@ ModalDialog.propTypes = {
163
163
  */
164
164
  zIndex: PropTypes.number,
165
165
  /** Specifies whether overflow is visible in the modal */
166
- isOverflowVisible: PropTypes.bool,
166
+ isOverflowVisible: PropTypes.bool.isRequired,
167
167
  };
168
168
 
169
169
  ModalDialog.Header = ModalDialogHeader;
@@ -145,4 +145,4 @@ class ModalWrapper extends React.Component {
145
145
  }
146
146
  onClose={() => {}}
147
147
  />
148
- ```
148
+ ```
@@ -36,6 +36,7 @@ This is the alert style `ModalDialog` composition. `AlertModal` passes all of it
36
36
  <Button variant="danger">Submit</Button>
37
37
  </ActionRow>
38
38
  )}
39
+ isOverflowVisible={false}
39
40
  >
40
41
  <p>
41
42
  I'm baby palo santo ugh celiac fashion axe. La croix lo-fi venmo whatever.
@@ -67,6 +68,7 @@ const [isOpen, open, close] = useToggle(false);
67
68
  <Button variant="primary">Delete</Button>
68
69
  </ActionRow>
69
70
  )}
71
+ isOverflowVisible={false}
70
72
  >
71
73
  <p>
72
74
  Are your sure you want to delete this file? You can't undo this action.
@@ -95,6 +97,7 @@ const [isOpen, open, close] = useToggle(false);
95
97
  <Button variant="danger">Acknowledge errror</Button>
96
98
  </ActionRow>
97
99
  )}
100
+ isOverflowVisible={false}
98
101
  >
99
102
  <p>
100
103
  An unknown error has occured.
@@ -123,6 +126,7 @@ const [isOpen, open, close] = useToggle(false);
123
126
  <Button variant="success">Confirm</Button>
124
127
  </ActionRow>
125
128
  )}
129
+ isOverflowVisible={false}
126
130
  >
127
131
  <p>
128
132
  All good!
@@ -38,6 +38,7 @@ The fullscreen `ModalDialog` composition. `FullscreenModal` passes all of its pr
38
38
  <Button>Submit</Button>
39
39
  </ActionRow>
40
40
  )}
41
+ isOverflowVisible={false}
41
42
  >
42
43
  <Container size="md">
43
44
  <p>
@@ -50,6 +50,7 @@ The ``MarketingModal`` is a preconfigured `ModalDialog` that accepts an image an
50
50
  <Button>Submit</Button>
51
51
  </ActionRow>
52
52
  )}
53
+ isOverflowVisible={false}
53
54
  >
54
55
  <p>
55
56
  I'm baby palo santo ugh celiac fashion axe. La croix lo-fi venmo whatever. Beard man braid migas single-origin coffee forage ramps. Tumeric messenger bag bicycle rights wayfarers, try-hard cronut blue bottle health goth. Sriracha tumblr cardigan, cloud bread succulents tumeric copper mug marfa semiotics woke next level organic roof party +1 try-hard.
@@ -44,6 +44,7 @@ label for the dialog element.
44
44
  variant={modalVariant}
45
45
  hasCloseButton
46
46
  isFullscreenOnMobile
47
+ isOverflowVisible={false}
47
48
  >
48
49
  <ModalDialog.Header>
49
50
  <ModalDialog.Title>
@@ -114,6 +115,7 @@ label for the dialog element.
114
115
  size={modalSize}
115
116
  variant={modalVariant}
116
117
  hasCloseButton
118
+ isOverflowVisible={false}
117
119
  >
118
120
  <ModalDialog.Hero>
119
121
  <ModalDialog.Hero.Background
@@ -38,6 +38,7 @@ The standard `ModalDialog` composition. `StandardModal` passes all of its props
38
38
  <Button>Submit</Button>
39
39
  </ActionRow>
40
40
  )}
41
+ isOverflowVisible={false}
41
42
  >
42
43
  <p>
43
44
  I'm baby palo santo ugh celiac fashion axe. La croix lo-fi venmo whatever. Beard man braid migas single-origin coffee forage ramps. Tumeric messenger bag bicycle rights wayfarers, try-hard cronut blue bottle health goth. Sriracha tumblr cardigan, cloud bread succulents tumeric copper mug marfa semiotics woke next level organic roof party +1 try-hard.
@@ -42,6 +42,7 @@ describe('<AlertModal />', () => {
42
42
  isOpen={isOpen}
43
43
  onClose={closeFn}
44
44
  footerNode={<p>footer</p>}
45
+ isOverflowVisible={false}
45
46
  >
46
47
  <Body />
47
48
  </AlertModal>,
@@ -60,6 +61,7 @@ describe('<AlertModal />', () => {
60
61
  onClose={closeFn}
61
62
  icon={Info}
62
63
  footerNode={<p>footer</p>}
64
+ isOverflowVisible={false}
63
65
  >
64
66
  <Body />
65
67
  </AlertModal>,
@@ -77,6 +79,7 @@ describe('<AlertModal />', () => {
77
79
  onClose={closeFn}
78
80
  icon={Info}
79
81
  footerNode={<p>footer</p>}
82
+ isOverflowVisible={false}
80
83
  >
81
84
  <Body />
82
85
  </AlertModal>,
@@ -94,6 +97,7 @@ describe('<AlertModal />', () => {
94
97
  onClose={closeFn}
95
98
  icon={Info}
96
99
  footerNode={<p>footer</p>}
100
+ isOverflowVisible={false}
97
101
  >
98
102
  <Body />
99
103
  </AlertModal>,
@@ -14,6 +14,7 @@ describe('ModalDialog', () => {
14
14
  size="md"
15
15
  variant="default"
16
16
  hasCloseButton
17
+ isOverflowVisible={false}
17
18
  >
18
19
  <ModalDialog.Header>
19
20
  <ModalDialog.Title>The title</ModalDialog.Title>
@@ -42,6 +43,7 @@ describe('ModalDialog', () => {
42
43
  <ModalDialog
43
44
  title="My dialog"
44
45
  onClose={onClose}
46
+ isOverflowVisible={false}
45
47
  >
46
48
  <ModalDialog.Header><ModalDialog.Title>The title</ModalDialog.Title></ModalDialog.Header>
47
49
  <ModalDialog.Body><p>The hidden content</p></ModalDialog.Body>
@@ -64,6 +66,7 @@ describe('ModalDialog with Hero', () => {
64
66
  size="md"
65
67
  variant="default"
66
68
  hasCloseButton
69
+ isOverflowVisible={false}
67
70
  >
68
71
  <ModalDialog.Hero>
69
72
  <ModalDialog.Hero.Background backgroundSrc="imageurl" />
@@ -5,16 +5,17 @@ import { createPopper } from '@popperjs/core';
5
5
  import { FormattedMessage } from 'react-intl';
6
6
 
7
7
  import breakpoints from '../utils/breakpoints';
8
-
9
8
  import CheckpointActionRow from './CheckpointActionRow';
10
9
  import CheckpointBody from './CheckpointBody';
11
- import CheckpointBreadcrumbs from './CheckpointBreadcrumbs';
12
- import CheckpointTitle from './CheckpointTitle';
10
+ import CheckpointHeader from './CheckpointHeader';
13
11
  import messages from './messages';
14
12
 
15
13
  const Checkpoint = React.forwardRef(({
16
14
  body,
15
+ dismissAltText,
17
16
  index,
17
+ onBack,
18
+ onDismiss,
18
19
  placement,
19
20
  target,
20
21
  title,
@@ -87,7 +88,6 @@ const Checkpoint = React.forwardRef(({
87
88
  }, [target, checkpointVisible, placement]);
88
89
 
89
90
  const isLastCheckpoint = index + 1 === totalCheckpoints;
90
- const isOnlyCheckpoint = totalCheckpoints === 1;
91
91
 
92
92
  return (
93
93
  <div
@@ -104,14 +104,17 @@ const Checkpoint = React.forwardRef(({
104
104
  values={{ step: index + 1 }}
105
105
  />
106
106
  </span>
107
- {(title || !isOnlyCheckpoint) && (
108
- <div className="pgn__checkpoint-header">
109
- <CheckpointTitle>{title}</CheckpointTitle>
110
- <CheckpointBreadcrumbs currentIndex={index} totalCheckpoints={totalCheckpoints} />
111
- </div>
112
- )}
107
+ <CheckpointHeader
108
+ dismissAltText={dismissAltText}
109
+ index={index}
110
+ onDismiss={onDismiss}
111
+ title={title}
112
+ totalCheckpoints={totalCheckpoints}
113
+ />
113
114
  <CheckpointBody>{body}</CheckpointBody>
114
115
  <CheckpointActionRow
116
+ onBack={onBack}
117
+ onDismiss={onDismiss}
115
118
  isLastCheckpoint={isLastCheckpoint}
116
119
  index={index}
117
120
  {...props}
@@ -129,21 +132,23 @@ const Checkpoint = React.forwardRef(({
129
132
 
130
133
  Checkpoint.defaultProps = {
131
134
  advanceButtonText: null,
135
+ backButtonText: null,
132
136
  body: null,
133
- dismissButtonText: null,
137
+ dismissAltText: null,
134
138
  endButtonText: null,
135
139
  placement: 'top',
136
140
  title: null,
137
- showDismissButton: undefined,
138
141
  };
139
142
 
140
143
  Checkpoint.propTypes = {
141
144
  /** The text displayed on the button used to advance the tour for the given Checkpoint. */
142
145
  advanceButtonText: PropTypes.node,
146
+ /** The text displayed on the button used go back in the tour for the given Checkpoint. */
147
+ backButtonText: PropTypes.string,
143
148
  /** The text displayed in the body of the Checkpoint */
144
149
  body: PropTypes.node,
145
- /** The text displayed on the button used to dismiss the tour for the given Checkpoint. */
146
- dismissButtonText: PropTypes.node,
150
+ /** The text used in the alt for the icon used to dismiss the tour for the given Checkpoint */
151
+ dismissAltText: PropTypes.string,
147
152
  /** The text displayed on the button used to end the tour for the given Checkpoint. */
148
153
  endButtonText: PropTypes.node,
149
154
  /** The current index of the given Checkpoint */
@@ -151,6 +156,9 @@ Checkpoint.propTypes = {
151
156
  /** A function that runs when triggering the `onClick` event of the advance
152
157
  * button for the given Checkpoint. */
153
158
  onAdvance: PropTypes.func.isRequired,
159
+ /** A function that runs when triggering the `onBack` event of the back
160
+ * button for the given Checkpoint. */
161
+ onBack: PropTypes.func.isRequired,
154
162
  /** A function that runs when triggering the `onClick` event of the dismiss
155
163
  * button for the given Checkpoint. */
156
164
  onDismiss: PropTypes.func.isRequired,
@@ -168,8 +176,6 @@ Checkpoint.propTypes = {
168
176
  title: PropTypes.node,
169
177
  /** The total number of Checkpoints in a tour */
170
178
  totalCheckpoints: PropTypes.number.isRequired,
171
- /** Enforces visibility of the dismiss button under all circumstances */
172
- showDismissButton: PropTypes.bool,
173
179
  };
174
180
 
175
181
  export default Checkpoint;
@@ -10,7 +10,7 @@ $checkpoint-arrow-transparent: solid $checkpoint-arrow-width transparent;
10
10
  background: $checkpoint-background-color;
11
11
  border-top: $checkpoint-border-width solid $checkpoint-border-color;
12
12
  border-radius: $border-radius;
13
- padding: map.get($spacers, 4);
13
+ padding: map.get($spacers, 3\.5);
14
14
  box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .3);
15
15
  z-index: $checkpoint-z-index;
16
16
  max-width: $checkpoint-max-width;
@@ -47,39 +47,6 @@ $checkpoint-arrow-transparent: solid $checkpoint-arrow-width transparent;
47
47
  margin-inline-end: map.get($spacers, 2);
48
48
  }
49
49
 
50
- .pgn__checkpoint-breadcrumb {
51
- height: 6px;
52
- width: 6px;
53
- border-radius: 50%;
54
-
55
- &.pgn__checkpoint-breadcrumb_active {
56
- background: $checkpoint-breadcrumb-color;
57
- }
58
-
59
- &.pgn__checkpoint-breadcrumb_inactive {
60
- border: 1px solid $checkpoint-breadcrumb-color;
61
- background: transparent;
62
- }
63
-
64
- &:not(:first-child) {
65
- margin-left: map.get($spacers, 1\.5);
66
- }
67
-
68
- [dir="rtl"] & {
69
- margin-left: map.get($spacers, 1\.5);
70
- margin-right: 0;
71
-
72
- &:last-child {
73
- margin-left: 0;
74
- }
75
- }
76
- }
77
-
78
- .pgn__checkpoint-breadcrumb-container {
79
- display: flex;
80
- align-items: center;
81
- }
82
-
83
50
  .pgn__checkpoint-body {
84
51
  color: $checkpoint-body-color;
85
52
  margin-bottom: map.get($spacers, 3\.5);
@@ -89,13 +56,18 @@ $checkpoint-arrow-transparent: solid $checkpoint-arrow-width transparent;
89
56
  .pgn__checkpoint-header {
90
57
  display: flex;
91
58
  justify-content: space-between;
92
- margin-bottom: map.get($spacers, 2\.5);
59
+ margin-bottom: map.get($spacers, 2);
60
+ align-items: center;
93
61
  }
94
62
 
95
63
  #pgn__checkpoint-title {
96
64
  font-size: $h3-font-size;
97
65
  margin-inline-end: map.get($spacers, 2\.5);
98
- margin-bottom: 0;
66
+ margin-bottom: map.get($spacers, 2);;
67
+ }
68
+
69
+ .pgn__checkpoint-page-index {
70
+ font-size: $small-font-size;
99
71
  }
100
72
  }
101
73
 
@@ -11,6 +11,7 @@ const popperMock = jest.spyOn(popper, 'createPopper');
11
11
 
12
12
  describe('Checkpoint', () => {
13
13
  const handleAdvance = jest.fn();
14
+ const handleBack = jest.fn();
14
15
  const handleDismiss = jest.fn();
15
16
  const handleEnd = jest.fn();
16
17
 
@@ -29,11 +30,12 @@ describe('Checkpoint', () => {
29
30
  <div id="target-element">...</div>
30
31
  <Checkpoint
31
32
  advanceButtonText="Next"
33
+ backButtonText="Back"
32
34
  body="Lorem ipsum checkpoint body"
33
- dismissButtonText="Dismiss"
34
35
  endButtonText="End"
35
36
  index={1}
36
37
  onAdvance={handleAdvance}
38
+ onBack={handleBack}
37
39
  onDismiss={handleDismiss}
38
40
  onEnd={handleEnd}
39
41
  target="#target-element"
@@ -44,31 +46,22 @@ describe('Checkpoint', () => {
44
46
  );
45
47
  });
46
48
 
47
- it('renders correct active breadcrumb', () => {
48
- expect(screen.getByText('Checkpoint title')).toBeInTheDocument();
49
- const breadcrumbs = screen.getAllByTestId('pgn__checkpoint-breadcrumb_', { exact: false });
50
- expect(breadcrumbs.length).toEqual(5);
51
- expect(breadcrumbs[0].classList).toContain('pgn__checkpoint-breadcrumb_inactive');
52
- expect(breadcrumbs[1].classList).toContain('pgn__checkpoint-breadcrumb_active');
53
- expect(breadcrumbs[2].classList).toContain('pgn__checkpoint-breadcrumb_inactive');
54
- expect(breadcrumbs[3].classList).toContain('pgn__checkpoint-breadcrumb_inactive');
55
- expect(breadcrumbs[4].classList).toContain('pgn__checkpoint-breadcrumb_inactive');
56
- });
57
-
58
- it('only renders advance and dismiss buttons (i.e. does not render end button)', () => {
59
- expect(screen.getByRole('button', { name: 'Dismiss' })).toBeInTheDocument();
49
+ it('only renders advance and back buttons (i.e. does not render end button)', () => {
50
+ expect(screen.getByRole('button', { name: 'Back' })).toBeInTheDocument();
60
51
  expect(screen.getByRole('button', { name: 'Next' })).toBeInTheDocument();
61
52
  });
62
53
 
63
- it('dismiss button onClick calls handleDismiss', async () => {
64
- const dismissButton = screen.getByRole('button', { name: 'Dismiss' });
65
- await userEvent.click(dismissButton);
66
- expect(handleDismiss).toHaveBeenCalledTimes(1);
54
+ it('back button onClick calls handleBack', async () => {
55
+ const user = userEvent.setup();
56
+ const backButton = screen.getByRole('button', { name: 'Back' });
57
+ await user.click(backButton);
58
+ expect(handleBack).toHaveBeenCalledTimes(1);
67
59
  });
68
60
 
69
61
  it('advance button onClick calls handleAdvance', async () => {
62
+ const user = userEvent.setup();
70
63
  const advanceButton = screen.getByRole('button', { name: 'Next' });
71
- await userEvent.click(advanceButton);
64
+ await user.click(advanceButton);
72
65
  expect(handleAdvance).toHaveBeenCalledTimes(1);
73
66
  });
74
67
  });
@@ -80,8 +73,9 @@ describe('Checkpoint', () => {
80
73
  <div id="#last-element" />
81
74
  <Checkpoint
82
75
  advanceButtonText="Next"
76
+ backButtonText="Back"
83
77
  body="Lorem ipsum checkpoint body"
84
- dismissButtonText="Dismiss"
78
+ dismissAltText="Escape"
85
79
  endButtonText="End"
86
80
  index={4}
87
81
  onAdvance={handleAdvance}
@@ -95,10 +89,15 @@ describe('Checkpoint', () => {
95
89
  );
96
90
  });
97
91
 
98
- it('only renders end button (i.e. neither advance nor dismiss buttons)', () => {
92
+ it('only renders end button (i.e. neither advance nor back buttons)', () => {
99
93
  expect(screen.getByText('End', { selector: 'button' })).toBeInTheDocument();
100
94
  });
101
95
 
96
+ it('uses customized alt text on the close icon', () => {
97
+ const closeButton = screen.getByTestId('dismiss-tour');
98
+ expect(closeButton).toHaveAttribute('aria-label', 'Escape');
99
+ });
100
+
102
101
  it('end button onClick calls handleEnd', async () => {
103
102
  const user = userEvent.setup({ pointerEventsCheck: PointerEventsCheckLevel.Never });
104
103
  const endButton = screen.getByText('End', { selector: 'button' });
@@ -115,7 +114,6 @@ describe('Checkpoint', () => {
115
114
  <Checkpoint
116
115
  advanceButtonText="Next"
117
116
  body="Lorem ipsum checkpoint body"
118
- dismissButtonText="Dismiss"
119
117
  endButtonText="End"
120
118
  index={0}
121
119
  onAdvance={handleAdvance}
@@ -132,36 +130,5 @@ describe('Checkpoint', () => {
132
130
  it('only renders end button (i.e. neither advance nor dismiss buttons)', () => {
133
131
  expect(screen.getByText('End', { selector: 'button' })).toBeInTheDocument();
134
132
  });
135
-
136
- it('does not render breadcrumbs', () => {
137
- const breadcrumbs = screen.queryAllByTestId('pgn__checkpoint-breadcrumb_', { exact: false });
138
- expect(breadcrumbs.length).toEqual(0);
139
- });
140
- });
141
-
142
- describe('only one Checkpoint in Tour and showDismissButton set to true', () => {
143
- it('it renders dismiss button and end button', () => {
144
- render(
145
- <IntlProvider locale="en" messages={{}}>
146
- <div id="#target-element" />
147
- <Checkpoint
148
- advanceButtonText="Next"
149
- body="Lorem ipsum checkpoint body"
150
- dismissButtonText="Dismiss"
151
- endButtonText="End"
152
- index={0}
153
- onAdvance={handleAdvance}
154
- onDismiss={handleDismiss}
155
- onEnd={handleEnd}
156
- target="#target-element"
157
- title="Checkpoint title"
158
- totalCheckpoints={1}
159
- showDismissButton
160
- />
161
- </IntlProvider>,
162
- );
163
- expect(screen.getByText('Dismiss', { selector: 'button' })).toBeInTheDocument();
164
- expect(screen.getByText('End', { selector: 'button' })).toBeInTheDocument();
165
- });
166
133
  });
167
134
  });
@@ -1,68 +1,68 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
+
4
+ import ActionRow from '../ActionRow';
3
5
  import Button from '../Button';
4
6
 
5
7
  const CheckpointActionRow = React.forwardRef(({
6
8
  advanceButtonText,
7
- dismissButtonText,
9
+ backButtonText,
8
10
  endButtonText,
9
11
  isLastCheckpoint,
10
12
  onAdvance,
11
- onDismiss,
13
+ onBack,
12
14
  onEnd,
13
- showDismissButton,
14
15
  index,
15
- }, ref) => (
16
- <div className="pgn__checkpoint-action-row" ref={ref}>
17
- {(showDismissButton === undefined ? !isLastCheckpoint : showDismissButton) && (
16
+ }) => {
17
+ const isFirstCheckpoint = index === 0;
18
+ return (
19
+ <ActionRow className="pgn__checkpoint-action-row">
20
+ {!isFirstCheckpoint && (
21
+ <Button
22
+ className="pgn__checkpoint-button-back"
23
+ variant="tertiary"
24
+ onClick={onBack}
25
+ >
26
+ {backButtonText}
27
+ </Button>
28
+ )}
18
29
  <Button
19
- variant="tertiary"
20
- className="pgn__checkpoint-button_dismiss"
21
- onClick={onDismiss}
30
+ autoFocus
31
+ className="pgn__checkpoint-button_advance"
32
+ onClick={isLastCheckpoint ? () => onEnd(index) : () => onAdvance(index)}
22
33
  >
23
- {dismissButtonText}
34
+ {isLastCheckpoint ? endButtonText : advanceButtonText}
24
35
  </Button>
25
- )}
26
- <Button
27
- autoFocus
28
- className="pgn__checkpoint-button_advance"
29
- variant="primary"
30
- onClick={isLastCheckpoint ? () => onEnd(index) : () => onAdvance(index)}
31
- >
32
- {isLastCheckpoint ? endButtonText : advanceButtonText}
33
- </Button>
34
- </div>
35
- ));
36
+ </ActionRow>
37
+ );
38
+ });
36
39
 
37
40
  CheckpointActionRow.defaultProps = {
38
41
  advanceButtonText: '',
39
- dismissButtonText: '',
42
+ backButtonText: '',
40
43
  endButtonText: '',
41
44
  isLastCheckpoint: false,
42
- onAdvance: () => {},
43
- onDismiss: () => {},
44
- onEnd: () => {},
45
- showDismissButton: undefined,
45
+ onAdvance: () => { },
46
+ onBack: () => { },
47
+ onEnd: () => { },
46
48
  index: 0,
47
49
  };
48
50
 
49
51
  CheckpointActionRow.propTypes = {
50
52
  /** The text displayed on the button used to advance the tour. */
51
53
  advanceButtonText: PropTypes.node,
52
- /** The text displayed on the button used to dismiss the tour. */
53
- dismissButtonText: PropTypes.node,
54
+ /** The text displayed on the button used to go back on the tour */
55
+ backButtonText: PropTypes.string,
54
56
  /** The text displayed on the button used to end the tour. */
55
57
  endButtonText: PropTypes.node,
56
58
  /** Whether the parent Checkpoint is the last in the tour. */
57
59
  isLastCheckpoint: PropTypes.bool,
58
60
  /** A function that runs when triggering the `onClick` event of the advance button. */
59
61
  onAdvance: PropTypes.func,
60
- /** A function that runs when triggering the `onClick` event of the dismiss button. */
61
- onDismiss: PropTypes.func,
62
+ /** A function that runs when triggering the `onClick` event of the back button. */
63
+ onBack: PropTypes.func,
62
64
  /** A function that runs when triggering the `onClick` event of the advance button if isLastCheckpoint is true. */
63
65
  onEnd: PropTypes.func,
64
- /** Enforces visibility of the dismiss button under all circumstances */
65
- showDismissButton: PropTypes.bool,
66
66
  /** Allows visibility of last index value for onEnd checkpoint compatibility */
67
67
  index: PropTypes.number,
68
68
  };