@patternfly/quickstarts 1.2.1 → 1.4.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/README.md CHANGED
@@ -27,9 +27,26 @@ import '@patternfly/react-core/dist/styles/base.css';
27
27
  import '@patternfly/quickstarts/dist/quickstarts.min.css';
28
28
  ```
29
29
 
30
+ ### Stylesheets if you use an older version of PatternFly
31
+ If you use an older version of @patternfly/react-core (older than "4.115.2"), and you can't upgrade yet, you can pull in the necessary PatternFly styles that @patternfly/quickstarts depends upon.
32
+
33
+ Ideally @patternfly/quickstarts will use the consumer provided PatternFly styles, only use these stylesheets if really needed.
34
+
35
+ `quickstarts-standalone.min.css` nests the css classes within a **.pfext-quick-start__base** parent, so that they have higher specificity. `patternfly-global.css` includes component styles that we cannot nest with more specificiy (for example Drawer since it can include consumer components that depend on an older PF version).
36
+
37
+ > Note: Only use these stylesheets if necessary!
38
+ ```js
39
+ // import base from PatternFly to get the font
40
+ import '@patternfly/react-core/dist/styles/base.css';
41
+ // some global styles and variables that quickstarts uses (Drawer, Popover, Modal, Backdrop, Bullseye)
42
+ import '@patternfly/quickstarts/dist/patternfly-global.css';
43
+ // PF and quickstarts styles nested within .pfext-quick-start__base
44
+ import '@patternfly/quickstarts/dist/quickstarts-standalone.min.css';
45
+ ```
46
+
30
47
  ## Usage example
31
48
 
32
- Note: You can also view this example on [codesandbox](https://codesandbox.io/s/patternflyquickstarts-1386f?file=/src/App.js)!
49
+ Note: You can also view this example on [codesandbox](https://codesandbox.io/s/patternfly-quickstarts-finished-cnv53)!
33
50
 
34
51
  ```js
35
52
  import "./styles.css";
@@ -204,4 +221,26 @@ You can have inline or block copyable text.
204
221
  ```{{copy}}
205
222
  ```
206
223
 
224
+ ## Localization
225
+ We use English as the default language. You can override the default by providing your own key/value pairs to the `QuickStartContainer` or `QuickStartContextProvider` resourceBundle prop.
226
+
227
+ Example:
228
+ ```js
229
+ // load my own resource Czech translations resource bundle using i18next
230
+ const resourceBundle = i18n.getResourceBundle('cs', 'quickstart');
231
+ const resources = {
232
+ ...resourceBundle,
233
+ Start: "Let's go!",
234
+ Continue: 'Resume',
235
+ Restart: 'Start over',
236
+ };
237
+ return (
238
+ <QuickStartContainer resourceBundle={resources}>
239
+ </QuickStartContainer>
240
+ )
241
+ ```
242
+
243
+ Use this [file](https://github.com/patternfly/patternfly-quickstarts/blob/main/packages/module/src/locales/en/quickstart.json) as a base for your translations.
244
+ Each language is different, especially when it comes to plurals. Try [this utility](https://jsfiddle.net/6bpxsgd4) sourced from [i18next](https://www.i18next.com/translation-function/plurals#how-to-find-the-correct-plural-suffix) to determine the suffixes for the right plural format.
245
+
207
246
  ####
@@ -18,6 +18,7 @@ export interface QuickStartContainerProps extends React.HTMLProps<HTMLDivElement
18
18
  language?: string;
19
19
  loading?: boolean;
20
20
  useQueryParams?: boolean;
21
+ alwaysShowTaskReview?: boolean;
21
22
  /**
22
23
  * Additional markdown extensions and renderers to use
23
24
  * TODO: example usage - In the meantime you can take a look at:
@@ -2,6 +2,7 @@ import * as React from 'react';
2
2
  import { QuickStartExternal } from '../utils/quick-start-types';
3
3
  declare type QuickStartTileFooterProps = {
4
4
  link: QuickStartExternal;
5
+ quickStartId?: string;
5
6
  };
6
7
  declare const QuickStartTileFooterExternal: React.FC<QuickStartTileFooterProps>;
7
8
  export default QuickStartTileFooterExternal;
@@ -6,6 +6,7 @@ declare type QuickStartTileHeaderProps = {
6
6
  duration: number;
7
7
  name: string;
8
8
  type?: QuickStartType;
9
+ quickStartId?: string;
9
10
  };
10
11
  declare const QuickStartTileHeader: React.FC<QuickStartTileHeaderProps>;
11
12
  export default QuickStartTileHeader;
@@ -4,7 +4,7 @@ declare type QuickStartConclusionProps = {
4
4
  tasks: QuickStartTask[];
5
5
  conclusion: string;
6
6
  allTaskStatuses: QuickStartTaskStatus[];
7
- nextQuickStart?: QuickStart;
7
+ nextQuickStarts?: QuickStart[];
8
8
  onQuickStartChange: (quickStartid: string) => void;
9
9
  onTaskSelect: (selectedTaskNumber: number) => void;
10
10
  };
@@ -1,9 +1,11 @@
1
1
  import * as React from 'react';
2
2
  import { QuickStartTask, QuickStartTaskStatus } from '../utils/quick-start-types';
3
+ import './QuickStartIntroduction.scss';
3
4
  declare type QuickStartIntroductionProps = {
4
5
  introduction: string;
5
6
  tasks: QuickStartTask[];
6
7
  allTaskStatuses: QuickStartTaskStatus[];
8
+ prerequisites?: string[];
7
9
  onTaskSelect: (selectedTaskNumber: number) => void;
8
10
  };
9
11
  declare const QuickStartIntroduction: React.FC<QuickStartIntroductionProps>;
package/dist/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { createContext, useCallback, useEffect, useState } from 'react';
3
- import { Card, CardHeader, CardActions, CardTitle, CardBody, CardFooter, Modal as Modal$1, Tooltip, Popover, PopoverPosition, Button, Text, TextVariants, TextList, TextListItem, Flex, FlexItem, Title, Label, Gallery, GalleryItem, ToolbarItem, SearchInput, Select, SelectVariant, SelectOption, Toolbar, ToolbarContent, EmptyState, EmptyStateIcon, EmptyStateBody, EmptyStatePrimary, Divider, ModalVariant, WizardNavItem, List, Alert, Radio, DrawerPanelContent, DrawerHead, DrawerActions, DrawerCloseButton, DrawerPanelBody, Drawer, DrawerContent, DrawerContentBody } from '@patternfly/react-core';
3
+ import { Card, CardHeader, CardActions, CardTitle, CardBody, CardFooter, Modal as Modal$1, Tooltip, Popover, PopoverPosition, Button, Text, TextVariants, TextList, TextListItem, Flex, FlexItem, Title, Label, Gallery, GalleryItem, ToolbarItem, SearchInput, Select, SelectVariant, SelectOption, Toolbar, ToolbarContent, EmptyState, EmptyStateIcon, EmptyStateBody, EmptyStatePrimary, Divider, ModalVariant, WizardNavItem, List, ExpandableSection, ListItem, Alert, Radio, DrawerPanelContent, DrawerHead, DrawerActions, DrawerCloseButton, DrawerPanelBody, Drawer, DrawerContent, DrawerContentBody } from '@patternfly/react-core';
4
4
  import SearchIcon from '@patternfly/react-icons/dist/js/icons/search-icon';
5
5
  import { css } from '@patternfly/react-styles';
6
6
  import RocketIcon from '@patternfly/react-icons/dist/js/icons/rocket-icon';
@@ -139,6 +139,7 @@ var en = {
139
139
  "{{count, number}} item": "{{count, number}} item",
140
140
  "{{count, number}} item_plural": "{{count, number}} items",
141
141
  "Prerequisites ({{totalPrereqs}})": "Prerequisites ({{totalPrereqs}})",
142
+ "View Prerequisites ({{totalPrereqs}})": "View Prerequisites ({{totalPrereqs}})",
142
143
  Prerequisites: Prerequisites,
143
144
  "Show prerequisites": "Show prerequisites",
144
145
  Complete: Complete,
@@ -578,6 +579,7 @@ const QuickStartContextDefaults = {
578
579
  footer: null,
579
580
  markdown: null,
580
581
  loading: false,
582
+ alwaysShowTaskReview: false,
581
583
  };
582
584
  const QuickStartContext = createContext(QuickStartContextDefaults);
583
585
  const getResource = (resource, options, resourceBundle, lng) => {
@@ -605,6 +607,7 @@ const useValuesForQuickStartContext = (value = {}) => {
605
607
  return getResource(resource, count !== undefined ? { count } : null, resourceBundle, language);
606
608
  }, [resourceBundle, language]);
607
609
  const [loading, setLoading] = React__default.useState(combinedValue.loading);
610
+ const [alwaysShowTaskReview, setAlwaysShowTaskReview] = React__default.useState(combinedValue.alwaysShowTaskReview);
608
611
  const initialSearchParams = new URLSearchParams(window.location.search);
609
612
  const initialSearchQuery = initialSearchParams.get(QUICKSTART_SEARCH_FILTER_KEY) || '';
610
613
  const initialStatusFilters = ((_a = initialSearchParams.get(QUICKSTART_STATUS_FILTER_KEY)) === null || _a === void 0 ? void 0 : _a.split(',')) || [];
@@ -675,6 +678,10 @@ const useValuesForQuickStartContext = (value = {}) => {
675
678
  });
676
679
  setAllQuickStartStates((qs) => (Object.assign(Object.assign({}, qs), { [quickStartId]: getDefaultQuickStartState(totalTasks, QuickStartStatus.IN_PROGRESS) })));
677
680
  }, [setActiveQuickStartID, setAllQuickStartStates, useQueryParams]);
681
+ // When alwaysShowTaskReview preference is enabled, skip visited step and go directly to review
682
+ const stepAfterInitial = alwaysShowTaskReview
683
+ ? QuickStartTaskStatus.REVIEW
684
+ : QuickStartTaskStatus.VISITED;
678
685
  const nextStep = useCallback((totalTasks) => {
679
686
  if (!activeQuickStartID) {
680
687
  return;
@@ -701,19 +708,19 @@ const useValuesForQuickStartContext = (value = {}) => {
701
708
  if (taskNumber < totalTasks && !updatedTaskStatus) {
702
709
  updatedTaskNumber = taskNumber + 1;
703
710
  }
704
- const markInitialStepVisited = updatedTaskNumber > -1 &&
711
+ const markInitialStepVisitedOrReview = updatedTaskNumber > -1 &&
705
712
  quickStart[getTaskStatusKey(updatedTaskNumber)] === QuickStartTaskStatus.INIT
706
- ? QuickStartTaskStatus.VISITED
713
+ ? stepAfterInitial
707
714
  : quickStart[getTaskStatusKey(updatedTaskNumber)];
708
715
  const newState = Object.assign(Object.assign({}, qs), { [activeQuickStartID]: Object.assign(Object.assign(Object.assign(Object.assign({}, quickStart), (updatedStatus ? { status: updatedStatus } : {})), (updatedTaskNumber > -1
709
716
  ? {
710
717
  taskNumber: updatedTaskNumber,
711
- [getTaskStatusKey(updatedTaskNumber)]: markInitialStepVisited,
718
+ [getTaskStatusKey(updatedTaskNumber)]: markInitialStepVisitedOrReview,
712
719
  }
713
720
  : {})), (updatedTaskStatus ? { [getTaskStatusKey(taskNumber)]: updatedTaskStatus } : {})) });
714
721
  return newState;
715
722
  });
716
- }, [activeQuickStartID, setAllQuickStartStates]);
723
+ }, [activeQuickStartID, setAllQuickStartStates, stepAfterInitial]);
717
724
  const previousStep = useCallback(() => {
718
725
  setAllQuickStartStates((qs) => {
719
726
  const quickStart = qs[activeQuickStartID];
@@ -735,7 +742,7 @@ const useValuesForQuickStartContext = (value = {}) => {
735
742
  let updatedTaskStatus = {};
736
743
  for (let taskIndex = 0; taskIndex <= taskNumber; taskIndex++) {
737
744
  const taskStatus = quickStart[getTaskStatusKey(taskIndex)];
738
- const newTaskStatus = taskStatus === QuickStartTaskStatus.INIT ? QuickStartTaskStatus.VISITED : undefined;
745
+ const newTaskStatus = taskStatus === QuickStartTaskStatus.INIT ? stepAfterInitial : undefined;
739
746
  if (newTaskStatus) {
740
747
  updatedTaskStatus = Object.assign(Object.assign({}, updatedTaskStatus), { [getTaskStatusKey(taskIndex)]: newTaskStatus });
741
748
  }
@@ -743,7 +750,7 @@ const useValuesForQuickStartContext = (value = {}) => {
743
750
  const updatedQuickStart = Object.assign(Object.assign(Object.assign(Object.assign({}, quickStart), (updatedStatus ? { status: updatedStatus } : {})), { taskNumber }), updatedTaskStatus);
744
751
  return Object.assign(Object.assign({}, qs), { [quickStartId]: updatedQuickStart });
745
752
  });
746
- }, [setAllQuickStartStates]);
753
+ }, [setAllQuickStartStates, stepAfterInitial]);
747
754
  const setQuickStartTaskStatus = useCallback((taskStatus) => {
748
755
  const quickStart = allQuickStartStates[activeQuickStartID];
749
756
  const { taskNumber } = quickStart;
@@ -789,6 +796,8 @@ const useValuesForQuickStartContext = (value = {}) => {
789
796
  setFilter,
790
797
  loading,
791
798
  setLoading,
799
+ alwaysShowTaskReview,
800
+ setAlwaysShowTaskReview,
792
801
  };
793
802
  };
794
803
  const QuickStartContextProvider = ({ children, value }) => {
@@ -954,7 +963,7 @@ const SimplePopper = ({ children }) => {
954
963
  }
955
964
  }, [destroy, isOpen]);
956
965
  return isOpen ? (React.createElement(Portal, null,
957
- React.createElement("div", { ref: nodeRefCallback, style: { zIndex: 9999, position: 'absolute', top: 0, left: 0 } }, children))) : null;
966
+ React.createElement("div", { ref: nodeRefCallback, style: { zIndex: 9999, position: 'absolute', top: 0, left: 0 }, className: "pfext-quick-start__base" }, children))) : null;
958
967
  };
959
968
 
960
969
  const isInViewport = (elementToCheck) => {
@@ -1197,7 +1206,7 @@ const CopyClipboard = ({ element, rootSelector, docContext, }) => {
1197
1206
  useEventListener(element, 'mouseleave', React.useCallback(() => {
1198
1207
  setShowSuccessContent(false);
1199
1208
  }, []));
1200
- return showSuccessContent ? (React.createElement(Tooltip, { key: "after-copy", isVisible: true, reference: () => element, content: getResource('Successfully copied to clipboard!') })) : (React.createElement(Tooltip, { key: "before-copy", reference: () => element, content: getResource('Copy to clipboard') }));
1209
+ return showSuccessContent ? (React.createElement(Tooltip, { key: "after-copy", isVisible: true, reference: () => element, content: getResource('Successfully copied to clipboard!'), className: "pfext-quick-start__base" })) : (React.createElement(Tooltip, { key: "before-copy", reference: () => element, content: getResource('Copy to clipboard'), className: "pfext-quick-start__base" }));
1201
1210
  };
1202
1211
  const MarkdownCopyClipboard = ({ docContext, rootSelector, }) => {
1203
1212
  const elements = docContext.querySelectorAll(`${rootSelector} [${MARKDOWN_COPY_BUTTON_ID}]`);
@@ -1522,10 +1531,11 @@ const QuickStartTileDescription = ({ description, prerequisites, }) => {
1522
1531
  React.createElement(Text, { component: TextVariants.h5, className: "pfext-quick-start-tile-prerequisites__text" },
1523
1532
  getResource('Prerequisites ({{totalPrereqs}})').replace('{{totalPrereqs}}', prereqs.length),
1524
1533
  ' '),
1525
- React.createElement(Popover, { "aria-label": getResource('Prerequisites'), headerContent: getResource('Prerequisites'), className: "pfext-page-layout__base", bodyContent: React.createElement(TextList, { "aria-label": getResource('Prerequisites'), className: "pfext-quick-start-tile-prerequisites-list" }, prereqs.map((prerequisite, index) => (
1526
- // eslint-disable-next-line react/no-array-index-key
1527
- React.createElement(TextListItem, { key: index },
1528
- React.createElement(QuickStartMarkdownView, { content: prerequisite }))))) },
1534
+ React.createElement(Popover, { "aria-label": getResource('Prerequisites'), headerContent: getResource('Prerequisites'), className: "pfext-quick-start__base", bodyContent: React.createElement("div", { className: "pfext-popover__base" },
1535
+ React.createElement(TextList, { "aria-label": getResource('Prerequisites'), className: "pfext-quick-start-tile-prerequisites-list" }, prereqs.map((prerequisite, index) => (
1536
+ // eslint-disable-next-line react/no-array-index-key
1537
+ React.createElement(TextListItem, { key: index },
1538
+ React.createElement(QuickStartMarkdownView, { content: prerequisite })))))) },
1529
1539
  React.createElement(Button, { variant: "link", isInline: true, className: "pfext-quick-start-tile-prerequisites__icon", "data-testid": "qs-card-prereqs", onClick: (e) => {
1530
1540
  e.preventDefault();
1531
1541
  e.stopPropagation();
@@ -1548,20 +1558,20 @@ const QuickStartTileFooter = ({ quickStartId, status, totalTasks, }) => {
1548
1558
  }, [quickStartId, restartQuickStart, totalTasks]);
1549
1559
  return (React.createElement(Flex, { justifyContent: { default: 'justifyContentSpaceBetween' } },
1550
1560
  status === QuickStartStatus.NOT_STARTED && (React.createElement(FlexItem, null,
1551
- React.createElement(Button, { onClick: start, variant: "link", isInline: true, "data-testid": "qs-card-notStarted-start" }, getResource('Start')))),
1561
+ React.createElement(Button, { onClick: start, variant: "link", isInline: true, "data-testid": "qs-card-notStarted-start", id: `${quickStartId}-start`, "aria-labelledby": `${quickStartId}-start ${quickStartId}` }, getResource('Start')))),
1552
1562
  status === QuickStartStatus.IN_PROGRESS && activeQuickStartID !== quickStartId && (React.createElement(FlexItem, null,
1553
- React.createElement(Button, { variant: "link", isInline: true, "data-testid": "qs-card-inProgress-resume" }, getResource('Continue')))),
1563
+ React.createElement(Button, { variant: "link", isInline: true, "data-testid": "qs-card-inProgress-resume", id: `${quickStartId}-continue`, "aria-labelledby": `${quickStartId}-continue ${quickStartId}` }, getResource('Continue')))),
1554
1564
  status === QuickStartStatus.COMPLETE && (React.createElement(FlexItem, null,
1555
- React.createElement(Button, { onClick: restart, variant: "link", isInline: true, "data-testid": "qs-card-complete-restart" }, getResource('Start')))),
1565
+ React.createElement(Button, { onClick: restart, variant: "link", isInline: true, "data-testid": "qs-card-complete-restart", id: `${quickStartId}-restart`, "aria-labelledby": `${quickStartId}-restart ${quickStartId}` }, getResource('Restart')))),
1556
1566
  status === QuickStartStatus.IN_PROGRESS && (React.createElement(FlexItem, null,
1557
- React.createElement(Button, { onClick: restart, variant: "link", isInline: true, "data-testid": "qs-card-inProgress-restart" }, getResource('Restart'))))));
1567
+ React.createElement(Button, { onClick: restart, variant: "link", isInline: true, "data-testid": "qs-card-inProgress-restart", id: `${quickStartId}-restart`, "aria-labelledby": `${quickStartId}-restart ${quickStartId}` }, getResource('Restart'))))));
1558
1568
  };
1559
1569
 
1560
- const QuickStartTileFooterExternal = ({ link }) => {
1570
+ const QuickStartTileFooterExternal = ({ link, quickStartId, }) => {
1561
1571
  const { href, text } = link;
1562
1572
  return (React.createElement(Flex, { justifyContent: { default: 'justifyContentSpaceBetween' } },
1563
1573
  React.createElement(FlexItem, null,
1564
- React.createElement(Button, { component: "a", href: href, target: "_blank", rel: "noopener noreferrer", variant: "link", "aria-label": `Open documentation in new window`, isInline: true, icon: React.createElement(ExternalLinkAltIcon, null), iconPosition: "right" }, text || href))));
1574
+ React.createElement(Button, { component: "a", href: href, target: "_blank", rel: "noopener noreferrer", variant: "link", "aria-label": `Open documentation in new window`, isInline: true, icon: React.createElement(ExternalLinkAltIcon, null), iconPosition: "right", id: quickStartId, "aria-labelledby": `${quickStartId}-external ${quickStartId}` }, text || href))));
1565
1575
  };
1566
1576
 
1567
1577
  const statusColorMap = {
@@ -1569,7 +1579,7 @@ const statusColorMap = {
1569
1579
  [QuickStartStatus.IN_PROGRESS]: 'purple',
1570
1580
  [QuickStartStatus.NOT_STARTED]: 'grey',
1571
1581
  };
1572
- const QuickStartTileHeader = ({ status, duration, name, type, }) => {
1582
+ const QuickStartTileHeader = ({ status, duration, name, type, quickStartId, }) => {
1573
1583
  const { getResource } = React.useContext(QuickStartContext);
1574
1584
  const statusLocaleMap = {
1575
1585
  [QuickStartStatus.COMPLETE]: getResource('Complete'),
@@ -1577,7 +1587,7 @@ const QuickStartTileHeader = ({ status, duration, name, type, }) => {
1577
1587
  [QuickStartStatus.NOT_STARTED]: getResource('Not started'),
1578
1588
  };
1579
1589
  return (React.createElement("div", { className: "pfext-quick-start-tile-header" },
1580
- React.createElement(Title, { headingLevel: "h3", "data-test": "title" }, name),
1590
+ React.createElement(Title, { headingLevel: "h3", "data-test": "title", id: quickStartId }, name),
1581
1591
  React.createElement("div", { className: "pfext-quick-start-tile-header__status" },
1582
1592
  type && (React.createElement(Label, { className: "pfext-quick-start-tile-header--margin", color: type.color }, type.text)),
1583
1593
  duration && (React.createElement(Label, { variant: "outline", "data-test": "duration", icon: React.createElement(OutlinedClockIcon, null), className: "pfext-quick-start-tile-header--margin" }, getResource('{{duration, number}} minutes', duration).replace('{{duration, number}}', duration))),
@@ -1588,8 +1598,14 @@ const QuickStartTile = ({ quickStart, status, isActive, onClick = () => { }, })
1588
1598
  const { metadata: { name: id }, spec: { icon, tasks, displayName, description, durationMinutes, prerequisites, link, type }, } = quickStart;
1589
1599
  const { setActiveQuickStart, footer } = React.useContext(QuickStartContext);
1590
1600
  const ref = React.useRef(null);
1591
- const quickStartIcon = (React.createElement(FallbackImg, { className: "pfext-catalog-item-icon__img--large", src: icon, alt: "", fallback: React.createElement(RocketIcon, null) }));
1592
- const footerComponent = footer && footer.show === false ? null : link ? (React.createElement(QuickStartTileFooterExternal, { link: link })) : (React.createElement(QuickStartTileFooter, { quickStartId: id, status: status, totalTasks: tasks === null || tasks === void 0 ? void 0 : tasks.length }));
1601
+ let quickStartIcon;
1602
+ if (typeof icon === 'object') {
1603
+ quickStartIcon = icon;
1604
+ }
1605
+ else {
1606
+ quickStartIcon = (React.createElement(FallbackImg, { className: "pfext-catalog-item-icon__img--large", src: icon, alt: "", fallback: React.createElement(RocketIcon, null) }));
1607
+ }
1608
+ const footerComponent = footer && footer.show === false ? null : link ? (React.createElement(QuickStartTileFooterExternal, { link: link, quickStartId: id })) : (React.createElement(QuickStartTileFooter, { quickStartId: id, status: status, totalTasks: tasks === null || tasks === void 0 ? void 0 : tasks.length }));
1593
1609
  const handleClick = (e) => {
1594
1610
  var _a;
1595
1611
  if ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.contains(e.target)) {
@@ -1609,7 +1625,7 @@ const QuickStartTile = ({ quickStart, status, isActive, onClick = () => { }, })
1609
1625
  // @ts-ignore
1610
1626
  component: "div", style: {
1611
1627
  cursor: 'pointer',
1612
- }, icon: quickStartIcon, className: "pfext-quick-start-tile", "data-testid": `qs-card-${camelize(displayName)}`, featured: isActive, title: React.createElement(QuickStartTileHeader, { name: displayName, status: status, duration: durationMinutes, type: type }), onClick: handleClick, "data-test": `tile ${id}`, description: React.createElement(QuickStartTileDescription, { description: description, prerequisites: prerequisites }), footer: footerComponent })));
1628
+ }, icon: quickStartIcon, className: "pfext-quick-start-tile", "data-testid": `qs-card-${camelize(displayName)}`, featured: isActive, title: React.createElement(QuickStartTileHeader, { name: displayName, status: status, duration: durationMinutes, type: type, quickStartId: id }), onClick: handleClick, "data-test": `tile ${id}`, description: React.createElement(QuickStartTileDescription, { description: description, prerequisites: prerequisites }), footer: footerComponent })));
1613
1629
  };
1614
1630
 
1615
1631
  const QuickStartCatalog = ({ quickStarts }) => {
@@ -1802,7 +1818,7 @@ const QuickStartCatalogPage = ({ quickStarts, showFilter, sortFnc = (q1, q2) =>
1802
1818
  if (!allQuickStarts || allQuickStarts.length === 0) {
1803
1819
  return React.createElement(EmptyBox, { label: getResource('Quick Starts') });
1804
1820
  }
1805
- return (React.createElement(React.Fragment, null,
1821
+ return (React.createElement("div", { className: "pfext-quick-start__base" },
1806
1822
  showTitle && (React.createElement("div", { className: "pfext-page-layout__header" },
1807
1823
  React.createElement(Text, { component: "h1", className: "pfext-page-layout__title", "data-test": "page-title" }, title || getResource('Quick Starts')),
1808
1824
  hint && React.createElement("div", { className: "pfext-page-layout__hint" }, hint))),
@@ -1823,65 +1839,89 @@ const QuickStartCatalogToolbar = ({ children }) => (React.createElement(Toolbar,
1823
1839
 
1824
1840
  const QuickStartCloseModal = ({ isOpen, onConfirm, onCancel, }) => {
1825
1841
  const { getResource } = React.useContext(QuickStartContext);
1826
- return (React.createElement(Modal, { className: "pfext-quick-start-drawer__modal", isOpen: isOpen, variant: ModalVariant.small, showClose: false, "data-test": "leave-quickstart", title: getResource('Leave quick start?'), footer: React.createElement(Flex, null,
1842
+ return (React.createElement(Modal, { className: "pfext-quick-start-drawer__modal pfext-quick-start__base", isOpen: isOpen, variant: ModalVariant.small, showClose: false, "data-test": "leave-quickstart", title: getResource('Leave quick start?'), footer: React.createElement(Flex, null,
1827
1843
  React.createElement(FlexItem, { align: { default: 'alignRight' } },
1828
1844
  React.createElement(Button, { variant: "secondary", "data-test": "cancel button", onClick: onCancel }, getResource('Cancel'))),
1829
1845
  React.createElement(FlexItem, null,
1830
1846
  React.createElement(Button, { variant: "primary", "data-test": "leave button", onClick: onConfirm }, getResource('Leave')))), isFullScreen: true }, getResource('Your progress will be saved.')));
1831
1847
  };
1832
1848
 
1833
- const TaskIcon = ({ taskIndex, taskStatus, }) => {
1849
+ const TaskIcon = ({ taskIndex, taskStatus }) => {
1834
1850
  const { getResource } = React.useContext(QuickStartContext);
1835
- switch (taskStatus) {
1836
- case QuickStartTaskStatus.SUCCESS:
1837
- return (React.createElement("span", { className: "pfext-icon-and-text__icon" },
1838
- React.createElement(CheckCircleIcon, { size: "md", className: "pfext-quick-start-task-header__task-icon-success" })));
1839
- case QuickStartTaskStatus.FAILED:
1840
- return (React.createElement("span", { className: "pfext-icon-and-text__icon" },
1841
- React.createElement(ExclamationCircleIcon, { size: "md", className: "pfext-quick-start-task-header__task-icon-failed" })));
1842
- default:
1843
- return (React.createElement("span", { className: "pfext-icon-and-text__icon pfext-quick-start-task-header__task-icon-init" }, getResource('{{taskIndex, number}}', taskIndex).replace('{{taskIndex, number}}', taskIndex)));
1851
+ const success = taskStatus === QuickStartTaskStatus.SUCCESS;
1852
+ const failed = taskStatus === QuickStartTaskStatus.FAILED;
1853
+ const classNames = css('pfext-icon-and-text__icon', {
1854
+ 'pfext-quick-start-task-header__task-icon-init': !failed && !success,
1855
+ });
1856
+ let content;
1857
+ if (success) {
1858
+ content = (React.createElement(CheckCircleIcon, { size: "md", className: "pfext-quick-start-task-header__task-icon-success" }));
1844
1859
  }
1860
+ else if (failed) {
1861
+ content = (React.createElement(ExclamationCircleIcon, { size: "md", className: "pfext-quick-start-task-header__task-icon-failed" }));
1862
+ }
1863
+ else {
1864
+ content = getResource('{{taskIndex, number}}', taskIndex).replace('{{taskIndex, number}}', taskIndex);
1865
+ }
1866
+ return React.createElement("span", { className: classNames }, content);
1845
1867
  };
1846
1868
  const QuickStartTaskHeader = ({ title, taskIndex, subtitle, taskStatus, size, isActiveTask, onTaskSelect, }) => {
1847
1869
  const classNames = css('pfext-quick-start-task-header__title', {
1848
1870
  'pfext-quick-start-task-header__title-success': taskStatus === QuickStartTaskStatus.SUCCESS,
1849
- 'pfext-quick-start-task-header__title-failed': taskStatus === QuickStartTaskStatus.FAILED,
1871
+ 'pfext-quick-start-task-header__title-failed': taskStatus === (QuickStartTaskStatus.FAILED || QuickStartTaskStatus.VISITED),
1850
1872
  });
1851
- const content = (React.createElement("span", { className: "pfext-quick-start-task-header" },
1852
- React.createElement(Title, { headingLevel: "h3", size: size, className: classNames },
1853
- React.createElement(TaskIcon, { taskIndex: taskIndex, taskStatus: taskStatus }),
1854
- React.createElement("span", { dangerouslySetInnerHTML: { __html: removeParagraphWrap(markdownConvert(title)) } }),
1855
- isActiveTask && subtitle && (React.createElement(React.Fragment, null,
1856
- ' ',
1857
- React.createElement("span", { className: "pfext-quick-start-task-header__subtitle text-secondary", "data-test-id": "quick-start-task-subtitle" }, subtitle))))));
1858
- return (React.createElement(WizardNavItem, { content: content, step: taskIndex, onNavItemClick: () => onTaskSelect(taskIndex - 1), navItemComponent: "button" }));
1873
+ const notCompleted = taskStatus === QuickStartTaskStatus.VISITED;
1874
+ const skippedReviewOrFailed = taskStatus === QuickStartTaskStatus.REVIEW || taskStatus === QuickStartTaskStatus.FAILED;
1875
+ const tryAgain = !isActiveTask && (skippedReviewOrFailed || notCompleted) && (React.createElement(FlexItem, null,
1876
+ React.createElement(Title, { headingLevel: "h4", className: "pfext-quick-start-task-header__tryagain" }, "Try the steps again.")));
1877
+ const content = (React.createElement(Flex, { className: "pfext-quick-start-task-header", direction: { default: 'column' }, spaceItems: { default: 'spaceItemsXs' } },
1878
+ React.createElement(FlexItem, null,
1879
+ React.createElement(Title, { headingLevel: "h3", size: size, className: classNames },
1880
+ React.createElement(TaskIcon, { taskIndex: taskIndex, taskStatus: taskStatus }),
1881
+ React.createElement("span", { dangerouslySetInnerHTML: { __html: removeParagraphWrap(markdownConvert(title)) } }),
1882
+ isActiveTask && subtitle && (React.createElement(React.Fragment, null,
1883
+ ' ',
1884
+ React.createElement("span", { className: "pfext-quick-start-task-header__subtitle", "data-test-id": "quick-start-task-subtitle" }, subtitle))))),
1885
+ tryAgain));
1886
+ return (React.createElement(WizardNavItem, { content: content, step: taskIndex, onNavItemClick: () => onTaskSelect(taskIndex - 1), navItemComponent: "button", isCurrent: isActiveTask }));
1859
1887
  };
1860
1888
 
1861
1889
  const QuickStartTaskHeaderList = ({ tasks, allTaskStatuses, onTaskSelect, }) => {
1862
1890
  return tasks.length > 0 ? (React.createElement(List, { className: "pfext-quick-start-task-header__list" }, tasks.map((task, index) => (React.createElement(QuickStartTaskHeader, { key: task.title, title: task.title, taskIndex: index + 1, size: "md", taskStatus: allTaskStatuses[index], onTaskSelect: onTaskSelect }))))) : null;
1863
1891
  };
1864
1892
 
1865
- const QuickStartConclusion = ({ tasks, conclusion, allTaskStatuses, nextQuickStart, onQuickStartChange, onTaskSelect, }) => {
1866
- var _a;
1893
+ const QuickStartConclusion = ({ tasks, conclusion, allTaskStatuses, nextQuickStarts, onQuickStartChange, onTaskSelect, }) => {
1867
1894
  const hasFailedTask = allTaskStatuses.includes(QuickStartTaskStatus.FAILED);
1868
- const nextQSDisplayName = (_a = nextQuickStart === null || nextQuickStart === void 0 ? void 0 : nextQuickStart.spec) === null || _a === void 0 ? void 0 : _a.displayName;
1869
1895
  const { getResource } = React.useContext(QuickStartContext);
1870
1896
  return (React.createElement(React.Fragment, null,
1871
1897
  React.createElement(QuickStartTaskHeaderList, { tasks: tasks, allTaskStatuses: allTaskStatuses, onTaskSelect: onTaskSelect }),
1872
1898
  React.createElement(QuickStartMarkdownView, { content: hasFailedTask
1873
1899
  ? getResource('One or more verifications did not pass during this quick start. Revisit the tasks or the help links, and then try again.')
1874
1900
  : conclusion }),
1875
- nextQuickStart && !hasFailedTask && (React.createElement(Button, { variant: "link", onClick: () => onQuickStartChange(nextQuickStart.metadata.name), isInline: true },
1876
- getResource('Start {{nextQSDisplayName}} quick start').replace('{{nextQSDisplayName}}', nextQSDisplayName),
1877
- ' ',
1878
- React.createElement(ArrowRightIcon, { style: { marginLeft: 'var(--pf-global--spacer--xs)', verticalAlign: 'middle' } })))));
1901
+ !hasFailedTask &&
1902
+ nextQuickStarts &&
1903
+ nextQuickStarts.length > 0 &&
1904
+ nextQuickStarts.map((nextQuickStart, index) => {
1905
+ var _a;
1906
+ return (React.createElement(Button, { variant: "link", onClick: () => onQuickStartChange(nextQuickStart.metadata.name), isInline: true, isBlock: true, key: index },
1907
+ getResource('Start {{nextQSDisplayName}} quick start').replace('{{nextQSDisplayName}}', (_a = nextQuickStart === null || nextQuickStart === void 0 ? void 0 : nextQuickStart.spec) === null || _a === void 0 ? void 0 : _a.displayName),
1908
+ ' ',
1909
+ React.createElement(ArrowRightIcon, { style: { marginLeft: 'var(--pf-global--spacer--xs)', verticalAlign: 'middle' } })));
1910
+ })));
1879
1911
  };
1880
1912
 
1881
- const QuickStartIntroduction = ({ tasks, introduction, allTaskStatuses, onTaskSelect, }) => {
1913
+ const QuickStartIntroduction = ({ tasks, introduction, allTaskStatuses, prerequisites, onTaskSelect, }) => {
1882
1914
  const { getResource } = React.useContext(QuickStartContext);
1915
+ const prereqs = prerequisites === null || prerequisites === void 0 ? void 0 : prerequisites.filter((p) => p);
1916
+ const [isPrereqsExpanded, setIsPrereqsExpanded] = React.useState(false);
1917
+ const prereqList = (prereqs === null || prereqs === void 0 ? void 0 : prereqs.length) > 0 && (React.createElement(ExpandableSection, { toggleText: getResource('View Prerequisites ({{totalPrereqs}})').replace('{{totalPrereqs}}', prereqs.length), onToggle: () => setIsPrereqsExpanded(!isPrereqsExpanded), className: "pfext-quick-start-intro__prereq" },
1918
+ React.createElement(List, { className: "pfext-quick-start-intro__prereq-list" }, prereqs.map((pr) => {
1919
+ return (React.createElement(ListItem, { key: pr, className: "pfext-quick-start-intro__prereq-list__item" },
1920
+ React.createElement("span", { className: "pfext-quick-start-intro__prereq-list__item-content" }, pr)));
1921
+ }))));
1883
1922
  return (React.createElement(React.Fragment, null,
1884
1923
  React.createElement(QuickStartMarkdownView, { content: introduction }),
1924
+ prereqList,
1885
1925
  React.createElement("p", { style: { marginBottom: 'var(--pf-global--spacer--md)' } },
1886
1926
  getResource('In this quick start, you will complete {{count, number}} task', tasks.length).replace('{{count, number}}', tasks.length),
1887
1927
  ":"),
@@ -1906,7 +1946,7 @@ const QuickStartTaskReview = ({ review, taskStatus, onTaskReview, }) => {
1906
1946
  'pfext-quick-start-task-review--failed': taskStatus === QuickStartTaskStatus.FAILED,
1907
1947
  });
1908
1948
  const title = React.createElement("span", { className: alertClassNames }, getResource('Check your work'));
1909
- return (React.createElement(Alert, { variant: getAlertVariant(taskStatus), title: title, isInline: true },
1949
+ return (React.createElement(Alert, { className: "pfext-quick-start-task-review-alert", variant: getAlertVariant(taskStatus), title: title, isInline: true },
1910
1950
  React.createElement(QuickStartMarkdownView, { content: instructions }),
1911
1951
  React.createElement("span", { className: "pfext-quick-start-task-review__actions" },
1912
1952
  React.createElement(Radio, { id: "review-success", name: "review-success", "data-testid": "qs-drawer-check-yes", label: getResource('Yes'), className: "pfext-quick-start-task-review__radio", isChecked: taskStatus === QuickStartTaskStatus.SUCCESS, onChange: () => onTaskReview(QuickStartTaskStatus.SUCCESS) }),
@@ -1915,31 +1955,32 @@ const QuickStartTaskReview = ({ review, taskStatus, onTaskReview, }) => {
1915
1955
  };
1916
1956
 
1917
1957
  const QuickStartTasks = ({ tasks, taskNumber, allTaskStatuses, onTaskReview, onTaskSelect, }) => {
1918
- const { getResource } = React.useContext(QuickStartContext);
1958
+ const { getResource, alwaysShowTaskReview } = React.useContext(QuickStartContext);
1919
1959
  return (React.createElement("div", { className: "pfext-quick-start-tasks__list" }, tasks
1920
1960
  .filter((_, index) => allTaskStatuses[index] !== QuickStartTaskStatus.INIT)
1921
1961
  .map((task, index) => {
1922
1962
  const { title, description, review } = task;
1923
1963
  const isActiveTask = index === taskNumber;
1924
1964
  const taskStatus = allTaskStatuses[index];
1965
+ const shouldShowTaskReview = (!QUICKSTART_TASKS_INITIAL_STATES.includes(taskStatus) || alwaysShowTaskReview) &&
1966
+ review;
1925
1967
  return (React.createElement(React.Fragment, { key: title },
1926
1968
  React.createElement(QuickStartTaskHeader, { taskIndex: index + 1, title: title, size: "md", subtitle: getResource('{{index, number}} of {{tasks, number}}')
1927
1969
  .replace('{{index, number}}', index + 1)
1928
1970
  .replace('{{tasks, number}}', tasks.length), taskStatus: taskStatus, isActiveTask: isActiveTask, onTaskSelect: onTaskSelect }),
1929
1971
  isActiveTask && (React.createElement("div", { style: { marginBottom: 'var(--pf-global--spacer--md)' } },
1930
1972
  React.createElement(QuickStartMarkdownView, { content: description }),
1931
- !QUICKSTART_TASKS_INITIAL_STATES.includes(taskStatus) && review && (React.createElement(QuickStartTaskReview, { review: review, taskStatus: taskStatus, onTaskReview: onTaskReview }))))));
1973
+ shouldShowTaskReview && (React.createElement(QuickStartTaskReview, { review: review, taskStatus: taskStatus, onTaskReview: onTaskReview }))))));
1932
1974
  })));
1933
1975
  };
1934
1976
 
1935
1977
  const QuickStartContent = React.forwardRef(({ quickStart, nextQuickStarts = [], taskNumber, allTaskStatuses, onTaskSelect, onTaskReview, onQuickStartChange, }, ref) => {
1936
- const { spec: { introduction, tasks, conclusion }, } = quickStart;
1978
+ const { spec: { introduction, tasks, conclusion, prerequisites }, } = quickStart;
1937
1979
  const totalTasks = tasks.length;
1938
- const nextQS = nextQuickStarts.length > 0 && nextQuickStarts[0];
1939
1980
  return (React.createElement("div", { className: "pfext-quick-start-content", ref: ref },
1940
- taskNumber === -1 && (React.createElement(QuickStartIntroduction, { tasks: tasks, allTaskStatuses: allTaskStatuses, introduction: introduction, onTaskSelect: onTaskSelect })),
1981
+ taskNumber === -1 && (React.createElement(QuickStartIntroduction, { tasks: tasks, allTaskStatuses: allTaskStatuses, introduction: introduction, prerequisites: prerequisites, onTaskSelect: onTaskSelect })),
1941
1982
  taskNumber > -1 && taskNumber < totalTasks && (React.createElement(QuickStartTasks, { tasks: tasks, taskNumber: taskNumber, allTaskStatuses: allTaskStatuses, onTaskReview: onTaskReview, onTaskSelect: onTaskSelect })),
1942
- taskNumber === totalTasks && (React.createElement(QuickStartConclusion, { tasks: tasks, conclusion: conclusion, allTaskStatuses: allTaskStatuses, nextQuickStart: nextQS, onQuickStartChange: onQuickStartChange, onTaskSelect: onTaskSelect }))));
1983
+ taskNumber === totalTasks && (React.createElement(QuickStartConclusion, { tasks: tasks, conclusion: conclusion, allTaskStatuses: allTaskStatuses, nextQuickStarts: nextQuickStarts, onQuickStartChange: onQuickStartChange, onTaskSelect: onTaskSelect }))));
1943
1984
  });
1944
1985
 
1945
1986
  const QuickStartFooter = ({ status, taskNumber, totalTasks, onNext, onBack, footerClass, quickStartId, }) => {
@@ -1977,8 +2018,7 @@ const QuickStartFooter = ({ status, taskNumber, totalTasks, onNext, onBack, foot
1977
2018
  }, [taskNumber, totalTasks, PrimaryButtonText, status]);
1978
2019
  const getPrimaryButton = React.useMemo(() => (React.createElement(Button, { variant: "primary", className: "pfext-quick-start-footer__actionbtn", onClick: onNext, "data-testid": `qs-drawer-${camelize(getPrimaryButtonText)}`, "data-test": `${getPrimaryButtonText} button` }, getPrimaryButtonText)), [getPrimaryButtonText, onNext]);
1979
2020
  const getSecondaryButton = React.useMemo(() => taskNumber === -1 && status !== QuickStartStatus.NOT_STARTED ? (React.createElement(Button, { variant: "secondary", onClick: onRestart, "data-testid": "qs-drawer-restart" }, SecondaryButtonText.RESTART)) : (taskNumber > -1 && (React.createElement(Button, { variant: "secondary", onClick: onBack, "data-testid": "qs-drawer-back" }, SecondaryButtonText.BACK))), [onRestart, onBack, SecondaryButtonText, status, taskNumber]);
1980
- const getSideNoteAction = React.useMemo(() => status === QuickStartStatus.COMPLETE &&
1981
- taskNumber === totalTasks && (React.createElement(Button, { variant: "link", className: "pfext-quick-start-footer__restartbtn", onClick: onRestart, "data-testid": "qs-drawer-side-note-action" }, SecondaryButtonText.RESTART)), [status, SecondaryButtonText, onRestart, taskNumber, totalTasks]);
2021
+ const getSideNoteAction = React.useMemo(() => taskNumber !== -1 && (React.createElement(Button, { variant: "link", className: "pfext-quick-start-footer__restartbtn", onClick: onRestart, "data-testid": "qs-drawer-side-note-action" }, SecondaryButtonText.RESTART)), [taskNumber, onRestart, SecondaryButtonText.RESTART]);
1982
2022
  return (React.createElement("div", { className: `pfext-quick-start-footer ${footerClass}` },
1983
2023
  getPrimaryButton,
1984
2024
  getSecondaryButton,
@@ -2032,6 +2072,13 @@ const getElement = (appendTo) => {
2032
2072
  }
2033
2073
  return appendTo;
2034
2074
  };
2075
+ const useScrollTopOnTaskNumberChange = (node, taskNumber) => {
2076
+ React.useEffect(() => {
2077
+ if (node) {
2078
+ node.scrollTo({ top: 0, behavior: 'smooth' });
2079
+ }
2080
+ }, [taskNumber, node]);
2081
+ };
2035
2082
  const QuickStartPanelContent = (_a) => {
2036
2083
  var { quickStarts = [], handleClose, activeQuickStartID, appendTo, isResizable = true, showClose = true } = _a, props = __rest(_a, ["quickStarts", "handleClose", "activeQuickStartID", "appendTo", "isResizable", "showClose"]);
2037
2084
  const { getResource } = React.useContext(QuickStartContext);
@@ -2040,6 +2087,7 @@ const QuickStartPanelContent = (_a) => {
2040
2087
  const quickStart = quickStarts.find((qs) => qs.metadata.name === activeQuickStartID);
2041
2088
  const { activeQuickStartState } = React.useContext(QuickStartContext);
2042
2089
  const taskNumber = activeQuickStartState === null || activeQuickStartState === void 0 ? void 0 : activeQuickStartState.taskNumber;
2090
+ useScrollTopOnTaskNumberChange(contentRef, taskNumber);
2043
2091
  const nextQuickStarts = quickStarts.filter((qs) => { var _a; return (_a = quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.nextQuickStart) === null || _a === void 0 ? void 0 : _a.includes(qs.metadata.name); });
2044
2092
  const headerClasses = css('pfext-quick-start-panel-content__header', {
2045
2093
  'pfext-quick-start-panel-content__header__shadow': shadows === Shadows.top || shadows === Shadows.both,
@@ -2057,7 +2105,7 @@ const QuickStartPanelContent = (_a) => {
2057
2105
  }
2058
2106
  return Number.parseInt(taskNumber, 10) + 1;
2059
2107
  };
2060
- const content = quickStart ? (React.createElement(DrawerPanelContent, Object.assign({ isResizable: isResizable, className: "pfext-quick-start-panel-content", "data-testid": `qs-drawer-${camelize(quickStart.spec.displayName)}`, "data-qs": `qs-step-${getStep()}`, "data-test": "quickstart drawer" }, props),
2108
+ const content = quickStart ? (React.createElement(DrawerPanelContent, Object.assign({ isResizable: isResizable, className: "pfext-quick-start__base", "data-testid": `qs-drawer-${camelize(quickStart.spec.displayName)}`, "data-qs": `qs-step-${getStep()}`, "data-test": "quickstart drawer" }, props),
2061
2109
  React.createElement("div", { className: headerClasses },
2062
2110
  React.createElement(DrawerHead, null,
2063
2111
  React.createElement("div", { className: "pfext-quick-start-panel-content__title" },
@@ -2076,7 +2124,7 @@ const QuickStartPanelContent = (_a) => {
2076
2124
  };
2077
2125
 
2078
2126
  const QuickStartContainer = (_a) => {
2079
- var { quickStarts, children, activeQuickStartID, allQuickStartStates, setActiveQuickStartID, setAllQuickStartStates, appendTo, fullWidth, onCloseInProgress, onCloseNotInProgress, resourceBundle, showCardFooters, language, loading = false, useQueryParams = true, markdown, contextProps } = _a, props = __rest(_a, ["quickStarts", "children", "activeQuickStartID", "allQuickStartStates", "setActiveQuickStartID", "setAllQuickStartStates", "appendTo", "fullWidth", "onCloseInProgress", "onCloseNotInProgress", "resourceBundle", "showCardFooters", "language", "loading", "useQueryParams", "markdown", "contextProps"]);
2127
+ var { quickStarts, children, activeQuickStartID, allQuickStartStates, setActiveQuickStartID, setAllQuickStartStates, appendTo, fullWidth, onCloseInProgress, onCloseNotInProgress, resourceBundle, showCardFooters, language, loading = false, useQueryParams = true, markdown, contextProps, alwaysShowTaskReview = false } = _a, props = __rest(_a, ["quickStarts", "children", "activeQuickStartID", "allQuickStartStates", "setActiveQuickStartID", "setAllQuickStartStates", "appendTo", "fullWidth", "onCloseInProgress", "onCloseNotInProgress", "resourceBundle", "showCardFooters", "language", "loading", "useQueryParams", "markdown", "contextProps", "alwaysShowTaskReview"]);
2080
2128
  const valuesForQuickstartContext = useValuesForQuickStartContext(Object.assign({ allQuickStarts: quickStarts, activeQuickStartID,
2081
2129
  setActiveQuickStartID,
2082
2130
  allQuickStartStates,
@@ -2084,7 +2132,8 @@ const QuickStartContainer = (_a) => {
2084
2132
  show: showCardFooters,
2085
2133
  }, language, resourceBundle: Object.assign({}, resourceBundle), loading,
2086
2134
  useQueryParams,
2087
- markdown }, contextProps));
2135
+ markdown,
2136
+ alwaysShowTaskReview }, contextProps));
2088
2137
  React.useEffect(() => {
2089
2138
  if (quickStarts &&
2090
2139
  JSON.stringify(quickStarts) !== JSON.stringify(valuesForQuickstartContext.allQuickStarts)) {