@patternfly/quickstarts 0.0.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 (304) hide show
  1. package/README.md +546 -0
  2. package/dist/ConsoleInternal/components/markdown-view.d.ts +19 -0
  3. package/dist/ConsoleInternal/components/utils/camel-case-wrap.d.ts +6 -0
  4. package/dist/ConsoleInternal/components/utils/index.d.ts +3 -0
  5. package/dist/ConsoleInternal/components/utils/router.d.ts +9 -0
  6. package/dist/ConsoleInternal/components/utils/status-box.d.ts +20 -0
  7. package/dist/ConsoleInternal/module/k8s/types.d.ts +42 -0
  8. package/dist/ConsoleShared/index.d.ts +1 -0
  9. package/dist/ConsoleShared/src/components/index.d.ts +7 -0
  10. package/dist/ConsoleShared/src/components/markdown-extensions/MarkdownCopyClipboard.d.ts +13 -0
  11. package/dist/ConsoleShared/src/components/markdown-extensions/accordion-extension.d.ts +7 -0
  12. package/dist/ConsoleShared/src/components/markdown-extensions/accordion-render-extension.d.ts +6 -0
  13. package/dist/ConsoleShared/src/components/markdown-extensions/admonition-extension.d.ts +7 -0
  14. package/dist/ConsoleShared/src/components/markdown-extensions/code-extension.d.ts +7 -0
  15. package/dist/ConsoleShared/src/components/markdown-extensions/const.d.ts +5 -0
  16. package/dist/ConsoleShared/src/components/markdown-extensions/index.d.ts +7 -0
  17. package/dist/ConsoleShared/src/components/markdown-extensions/inline-clipboard-extension.d.ts +7 -0
  18. package/dist/ConsoleShared/src/components/markdown-extensions/multiline-clipboard-extension.d.ts +7 -0
  19. package/dist/ConsoleShared/src/components/markdown-extensions/utils.d.ts +1 -0
  20. package/dist/ConsoleShared/src/components/markdown-highlight-extension/MarkdownHighlightExtension.d.ts +7 -0
  21. package/dist/ConsoleShared/src/components/markdown-highlight-extension/highlight-consts.d.ts +4 -0
  22. package/dist/ConsoleShared/src/components/markdown-highlight-extension/index.d.ts +1 -0
  23. package/dist/ConsoleShared/src/components/modal/Modal.d.ts +9 -0
  24. package/dist/ConsoleShared/src/components/modal/index.d.ts +1 -0
  25. package/dist/ConsoleShared/src/components/popper/Portal.d.ts +8 -0
  26. package/dist/ConsoleShared/src/components/popper/SimplePopper.d.ts +6 -0
  27. package/dist/ConsoleShared/src/components/popper/index.d.ts +2 -0
  28. package/dist/ConsoleShared/src/components/spotlight/InteractiveSpotlight.d.ts +7 -0
  29. package/dist/ConsoleShared/src/components/spotlight/Spotlight.d.ts +7 -0
  30. package/dist/ConsoleShared/src/components/spotlight/StaticSpotlight.d.ts +7 -0
  31. package/dist/ConsoleShared/src/components/spotlight/index.d.ts +1 -0
  32. package/dist/ConsoleShared/src/components/status/GenericStatus.d.ts +12 -0
  33. package/dist/ConsoleShared/src/components/status/NotStartedIcon.d.ts +3 -0
  34. package/dist/ConsoleShared/src/components/status/PopoverStatus.d.ts +13 -0
  35. package/dist/ConsoleShared/src/components/status/Status.d.ts +11 -0
  36. package/dist/ConsoleShared/src/components/status/StatusIconAndText.d.ts +8 -0
  37. package/dist/ConsoleShared/src/components/status/icons.d.ts +9 -0
  38. package/dist/ConsoleShared/src/components/status/index.d.ts +1 -0
  39. package/dist/ConsoleShared/src/components/status/statuses.d.ts +5 -0
  40. package/dist/ConsoleShared/src/components/status/types.d.ts +9 -0
  41. package/dist/ConsoleShared/src/components/utils/FallbackImg.d.ts +9 -0
  42. package/dist/ConsoleShared/src/components/utils/index.d.ts +1 -0
  43. package/dist/ConsoleShared/src/constants/index.d.ts +1 -0
  44. package/dist/ConsoleShared/src/constants/ui.d.ts +1 -0
  45. package/dist/ConsoleShared/src/hooks/index.d.ts +6 -0
  46. package/dist/ConsoleShared/src/hooks/scroll.d.ts +8 -0
  47. package/dist/ConsoleShared/src/hooks/useBoundingClientRect.d.ts +3 -0
  48. package/dist/ConsoleShared/src/hooks/useEventListener.d.ts +1 -0
  49. package/dist/ConsoleShared/src/hooks/useForceRender.d.ts +4 -0
  50. package/dist/ConsoleShared/src/hooks/useResizeObserver.d.ts +1 -0
  51. package/dist/ConsoleShared/src/hooks/useScrollShadows.d.ts +7 -0
  52. package/dist/ConsoleShared/src/index.d.ts +4 -0
  53. package/dist/ConsoleShared/src/utils/index.d.ts +1 -0
  54. package/dist/ConsoleShared/src/utils/useCombineRefs.d.ts +2 -0
  55. package/dist/HelpTopicDrawer.d.ts +33 -0
  56. package/dist/HelpTopicPanelContent.d.ts +11 -0
  57. package/dist/QuickStartCatalogPage.d.ts +14 -0
  58. package/dist/QuickStartCloseModal.d.ts +8 -0
  59. package/dist/QuickStartController.d.ts +10 -0
  60. package/dist/QuickStartDrawer.d.ts +62 -0
  61. package/dist/QuickStartMarkdownView.d.ts +9 -0
  62. package/dist/QuickStartPanelContent.d.ts +15 -0
  63. package/dist/catalog/Catalog/QuickStartCatalogHeader.d.ts +6 -0
  64. package/dist/catalog/Catalog/QuickStartCatalogSection.d.ts +5 -0
  65. package/dist/catalog/Catalog/QuickStartCatalogToolbar.d.ts +5 -0
  66. package/dist/catalog/Catalog/index.d.ts +3 -0
  67. package/dist/catalog/QuickStartCatalog.d.ts +8 -0
  68. package/dist/catalog/QuickStartTile.d.ts +14 -0
  69. package/dist/catalog/QuickStartTileDescription.d.ts +8 -0
  70. package/dist/catalog/QuickStartTileFooter.d.ts +8 -0
  71. package/dist/catalog/QuickStartTileFooterExternal.d.ts +8 -0
  72. package/dist/catalog/QuickStartTileHeader.d.ts +24 -0
  73. package/dist/catalog/Toolbar/QuickStartCatalogFilter.d.ts +10 -0
  74. package/dist/catalog/Toolbar/QuickStartCatalogFilterItems.d.ts +31 -0
  75. package/dist/catalog/index.d.ts +9 -0
  76. package/dist/controller/QuickStartConclusion.d.ts +12 -0
  77. package/dist/controller/QuickStartContent.d.ts +14 -0
  78. package/dist/controller/QuickStartFooter.d.ts +14 -0
  79. package/dist/controller/QuickStartIntroduction.d.ts +12 -0
  80. package/dist/controller/QuickStartTaskHeader.d.ts +15 -0
  81. package/dist/controller/QuickStartTaskHeaderList.d.ts +10 -0
  82. package/dist/controller/QuickStartTaskReview.d.ts +10 -0
  83. package/dist/controller/QuickStartTasks.d.ts +12 -0
  84. package/dist/data/mocks/json/explore-pipeline-quickstart.d.ts +2 -0
  85. package/dist/data/mocks/json/explore-serverless-quickstart.d.ts +2 -0
  86. package/dist/data/mocks/json/monitor-sampleapp-quickstart.d.ts +2 -0
  87. package/dist/data/mocks/json/tour-icons.d.ts +2 -0
  88. package/dist/data/quick-start-test-data.d.ts +2 -0
  89. package/dist/data/test-utils.d.ts +8 -0
  90. package/dist/index.d.ts +16 -0
  91. package/dist/index.es.js +2593 -0
  92. package/dist/index.es.js.map +1 -0
  93. package/dist/index.js +2695 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/patternfly-docs/quick-starts/design-guidelines/design-guidelines.md +105 -0
  96. package/dist/patternfly-docs/quick-starts/design-guidelines/img/card-elements copy.png +0 -0
  97. package/dist/patternfly-docs/quick-starts/design-guidelines/img/card-elements.png +0 -0
  98. package/dist/patternfly-docs/quick-starts/design-guidelines/img/catalog-elements.png +0 -0
  99. package/dist/patternfly-docs/quick-starts/design-guidelines/img/check-your-work.png +0 -0
  100. package/dist/patternfly-docs/quick-starts/design-guidelines/img/introduction-screen.png +0 -0
  101. package/dist/patternfly-docs/quick-starts/design-guidelines/img/mixed-catalog.png +0 -0
  102. package/dist/patternfly-docs/quick-starts/design-guidelines/img/prerequisites.png +0 -0
  103. package/dist/patternfly-docs/quick-starts/design-guidelines/img/qs-context.png +0 -0
  104. package/dist/patternfly-docs/quick-starts/design-guidelines/img/side-panel-elements.png +0 -0
  105. package/dist/patternfly-docs/quick-starts/design-guidelines/img/side-panel-resized.png +0 -0
  106. package/dist/patternfly-docs/quick-starts/design-guidelines/img/side-panel.png +0 -0
  107. package/dist/patternfly-docs/quick-starts/design-guidelines/img/task-no.png +0 -0
  108. package/dist/patternfly-docs/quick-starts/design-guidelines/img/task-yes.png +0 -0
  109. package/dist/patternfly-docs/quick-starts/design-guidelines/img/task.png +0 -0
  110. package/dist/patternfly-docs/quick-starts/examples/Basic.jsx +73 -0
  111. package/dist/patternfly-docs/quick-starts/examples/HelpTopic.jsx +51 -0
  112. package/dist/patternfly-docs/quick-starts/examples/about.md +84 -0
  113. package/dist/patternfly-docs/quick-starts/examples/basic.md +29 -0
  114. package/dist/patternfly-docs/quick-starts/examples/example-data/example-help-topics.js +173 -0
  115. package/dist/patternfly-docs/quick-starts/examples/example-data/example-quickstarts.js +215 -0
  116. package/dist/patternfly-docs/quick-starts/examples/example-data/index.js +15 -0
  117. package/dist/patternfly-docs/quick-starts/examples/help-topics.md +28 -0
  118. package/dist/patternfly-docs/quick-starts/examples/img/catalog.png +0 -0
  119. package/dist/patternfly-docs/quick-starts/examples/img/help-topic.png +0 -0
  120. package/dist/patternfly-docs/quick-starts/examples/img/side-panel.png +0 -0
  121. package/dist/patternfly-global.css +1302 -0
  122. package/dist/patternfly-nested.css +11812 -0
  123. package/dist/quickstarts-base.css +1219 -0
  124. package/dist/quickstarts-full.es.js +31861 -0
  125. package/dist/quickstarts-full.es.js.map +1 -0
  126. package/dist/quickstarts-standalone.css +868 -0
  127. package/dist/quickstarts-standalone.min.css +4 -0
  128. package/dist/quickstarts-vendor.css +165 -0
  129. package/dist/quickstarts.css +1383 -0
  130. package/dist/quickstarts.min.css +1 -0
  131. package/dist/styles/patternfly-global-entry.d.ts +1 -0
  132. package/dist/styles/patternfly-nested-entry.d.ts +1 -0
  133. package/dist/styles/quickstarts-standalone-entry.d.ts +1 -0
  134. package/dist/styles/vendor-entry.d.ts +1 -0
  135. package/dist/utils/PluralResolver.d.ts +16 -0
  136. package/dist/utils/asciidoc-procedure-parser.d.ts +12 -0
  137. package/dist/utils/const.d.ts +6 -0
  138. package/dist/utils/help-topic-context.d.ts +23 -0
  139. package/dist/utils/help-topic-types.d.ts +13 -0
  140. package/dist/utils/quick-start-context.d.ts +81 -0
  141. package/dist/utils/quick-start-types.d.ts +60 -0
  142. package/dist/utils/quick-start-utils.d.ts +10 -0
  143. package/dist/utils/useLocalStorage.d.ts +1 -0
  144. package/dist/vendor.js +2 -0
  145. package/dist/vendor.js.map +1 -0
  146. package/package.json +105 -0
  147. package/src/ConsoleInternal/components/_icon-and-text.scss +14 -0
  148. package/src/ConsoleInternal/components/_markdown-view.scss +19 -0
  149. package/src/ConsoleInternal/components/catalog/_catalog.scss +392 -0
  150. package/src/ConsoleInternal/components/markdown-view.tsx +276 -0
  151. package/src/ConsoleInternal/components/utils/_status-box.scss +58 -0
  152. package/src/ConsoleInternal/components/utils/camel-case-wrap.tsx +33 -0
  153. package/src/ConsoleInternal/components/utils/index.tsx +3 -0
  154. package/src/ConsoleInternal/components/utils/router.ts +45 -0
  155. package/src/ConsoleInternal/components/utils/status-box.tsx +56 -0
  156. package/src/ConsoleInternal/module/k8s/types.ts +53 -0
  157. package/src/ConsoleShared/index.ts +1 -0
  158. package/src/ConsoleShared/src/components/index.ts +7 -0
  159. package/src/ConsoleShared/src/components/layout/PageLayout.scss +29 -0
  160. package/src/ConsoleShared/src/components/markdown-extensions/MarkdownCopyClipboard.tsx +95 -0
  161. package/src/ConsoleShared/src/components/markdown-extensions/__tests__/MarkdownCopyClipboard.spec.tsx +25 -0
  162. package/src/ConsoleShared/src/components/markdown-extensions/__tests__/test-data.ts +5 -0
  163. package/src/ConsoleShared/src/components/markdown-extensions/accordion-extension.tsx +51 -0
  164. package/src/ConsoleShared/src/components/markdown-extensions/accordion-render-extension.tsx +60 -0
  165. package/src/ConsoleShared/src/components/markdown-extensions/admonition-extension.tsx +67 -0
  166. package/src/ConsoleShared/src/components/markdown-extensions/code-extension.tsx +23 -0
  167. package/src/ConsoleShared/src/components/markdown-extensions/const.ts +5 -0
  168. package/src/ConsoleShared/src/components/markdown-extensions/index.ts +7 -0
  169. package/src/ConsoleShared/src/components/markdown-extensions/inline-clipboard-extension.tsx +39 -0
  170. package/src/ConsoleShared/src/components/markdown-extensions/multiline-clipboard-extension.tsx +44 -0
  171. package/src/ConsoleShared/src/components/markdown-extensions/showdown-extension.scss +52 -0
  172. package/src/ConsoleShared/src/components/markdown-extensions/utils.ts +1 -0
  173. package/src/ConsoleShared/src/components/markdown-highlight-extension/MarkdownHighlightExtension.tsx +65 -0
  174. package/src/ConsoleShared/src/components/markdown-highlight-extension/highlight-consts.ts +9 -0
  175. package/src/ConsoleShared/src/components/markdown-highlight-extension/index.ts +1 -0
  176. package/src/ConsoleShared/src/components/modal/Modal.scss +3 -0
  177. package/src/ConsoleShared/src/components/modal/Modal.tsx +19 -0
  178. package/src/ConsoleShared/src/components/modal/index.ts +1 -0
  179. package/src/ConsoleShared/src/components/popper/Portal.tsx +25 -0
  180. package/src/ConsoleShared/src/components/popper/SimplePopper.tsx +92 -0
  181. package/src/ConsoleShared/src/components/popper/index.ts +2 -0
  182. package/src/ConsoleShared/src/components/spotlight/InteractiveSpotlight.tsx +58 -0
  183. package/src/ConsoleShared/src/components/spotlight/Spotlight.tsx +35 -0
  184. package/src/ConsoleShared/src/components/spotlight/StaticSpotlight.tsx +32 -0
  185. package/src/ConsoleShared/src/components/spotlight/index.ts +1 -0
  186. package/src/ConsoleShared/src/components/spotlight/spotlight.scss +63 -0
  187. package/src/ConsoleShared/src/components/status/GenericStatus.tsx +34 -0
  188. package/src/ConsoleShared/src/components/status/NotStartedIcon.tsx +27 -0
  189. package/src/ConsoleShared/src/components/status/PopoverStatus.tsx +39 -0
  190. package/src/ConsoleShared/src/components/status/Status.tsx +38 -0
  191. package/src/ConsoleShared/src/components/status/StatusIconAndText.tsx +42 -0
  192. package/src/ConsoleShared/src/components/status/icons.tsx +39 -0
  193. package/src/ConsoleShared/src/components/status/index.tsx +1 -0
  194. package/src/ConsoleShared/src/components/status/statuses.tsx +20 -0
  195. package/src/ConsoleShared/src/components/status/types.ts +8 -0
  196. package/src/ConsoleShared/src/components/utils/FallbackImg.tsx +20 -0
  197. package/src/ConsoleShared/src/components/utils/index.ts +1 -0
  198. package/src/ConsoleShared/src/constants/index.ts +1 -0
  199. package/src/ConsoleShared/src/constants/ui.ts +1 -0
  200. package/src/ConsoleShared/src/hooks/index.ts +6 -0
  201. package/src/ConsoleShared/src/hooks/scroll.ts +52 -0
  202. package/src/ConsoleShared/src/hooks/useBoundingClientRect.ts +18 -0
  203. package/src/ConsoleShared/src/hooks/useEventListener.ts +14 -0
  204. package/src/ConsoleShared/src/hooks/useForceRender.ts +6 -0
  205. package/src/ConsoleShared/src/hooks/useResizeObserver.ts +19 -0
  206. package/src/ConsoleShared/src/hooks/useScrollShadows.ts +45 -0
  207. package/src/ConsoleShared/src/index.ts +4 -0
  208. package/src/ConsoleShared/src/utils/index.ts +1 -0
  209. package/src/ConsoleShared/src/utils/useCombineRefs.ts +16 -0
  210. package/src/HelpTopicDrawer.tsx +116 -0
  211. package/src/HelpTopicPanelContent.tsx +160 -0
  212. package/src/QuickStartCatalogPage.tsx +195 -0
  213. package/src/QuickStartCloseModal.tsx +47 -0
  214. package/src/QuickStartController.tsx +111 -0
  215. package/src/QuickStartDrawer.scss +11 -0
  216. package/src/QuickStartDrawer.tsx +265 -0
  217. package/src/QuickStartMarkdownView.tsx +80 -0
  218. package/src/QuickStartPanelContent.scss +46 -0
  219. package/src/QuickStartPanelContent.tsx +165 -0
  220. package/src/__tests__/quick-start-utils.spec.tsx +16 -0
  221. package/src/catalog/Catalog/QuickStartCatalogHeader.tsx +18 -0
  222. package/src/catalog/Catalog/QuickStartCatalogSection.tsx +9 -0
  223. package/src/catalog/Catalog/QuickStartCatalogToolbar.tsx +12 -0
  224. package/src/catalog/Catalog/index.ts +3 -0
  225. package/src/catalog/QuickStartCatalog.scss +8 -0
  226. package/src/catalog/QuickStartCatalog.tsx +42 -0
  227. package/src/catalog/QuickStartTile.scss +11 -0
  228. package/src/catalog/QuickStartTile.tsx +129 -0
  229. package/src/catalog/QuickStartTileDescription.scss +29 -0
  230. package/src/catalog/QuickStartTileDescription.tsx +79 -0
  231. package/src/catalog/QuickStartTileFooter.tsx +101 -0
  232. package/src/catalog/QuickStartTileFooterExternal.tsx +40 -0
  233. package/src/catalog/QuickStartTileHeader.scss +16 -0
  234. package/src/catalog/QuickStartTileHeader.tsx +105 -0
  235. package/src/catalog/Toolbar/QuickStartCatalogFilter.scss +25 -0
  236. package/src/catalog/Toolbar/QuickStartCatalogFilter.tsx +32 -0
  237. package/src/catalog/Toolbar/QuickStartCatalogFilterItems.tsx +218 -0
  238. package/src/catalog/__tests__/QuickStartCatalog.spec.tsx +35 -0
  239. package/src/catalog/__tests__/QuickStartTile.spec.tsx +38 -0
  240. package/src/catalog/__tests__/QuickStartTileDescription.spec.tsx +44 -0
  241. package/src/catalog/index.ts +9 -0
  242. package/src/controller/QuickStartConclusion.tsx +63 -0
  243. package/src/controller/QuickStartContent.scss +12 -0
  244. package/src/controller/QuickStartContent.tsx +72 -0
  245. package/src/controller/QuickStartFooter.scss +13 -0
  246. package/src/controller/QuickStartFooter.tsx +124 -0
  247. package/src/controller/QuickStartIntroduction.scss +35 -0
  248. package/src/controller/QuickStartIntroduction.tsx +64 -0
  249. package/src/controller/QuickStartTaskHeader.scss +58 -0
  250. package/src/controller/QuickStartTaskHeader.tsx +125 -0
  251. package/src/controller/QuickStartTaskHeaderList.scss +17 -0
  252. package/src/controller/QuickStartTaskHeaderList.tsx +33 -0
  253. package/src/controller/QuickStartTaskReview.scss +30 -0
  254. package/src/controller/QuickStartTaskReview.tsx +81 -0
  255. package/src/controller/QuickStartTasks.scss +89 -0
  256. package/src/controller/QuickStartTasks.tsx +75 -0
  257. package/src/controller/__tests__/QuickStartConclusion.spec.tsx +95 -0
  258. package/src/controller/__tests__/QuickStartContent.spec.tsx +52 -0
  259. package/src/controller/__tests__/QuickStartFooter.spec.tsx +148 -0
  260. package/src/controller/__tests__/QuickStartTaskHeader.spec.tsx +43 -0
  261. package/src/controller/__tests__/QuickStartTaskReview.spec.tsx +45 -0
  262. package/src/controller/__tests__/QuickStartTasks.spec.tsx +81 -0
  263. package/src/data/mocks/json/explore-pipeline-quickstart.ts +66 -0
  264. package/src/data/mocks/json/explore-serverless-quickstart.ts +90 -0
  265. package/src/data/mocks/json/monitor-sampleapp-quickstart.ts +77 -0
  266. package/src/data/mocks/json/tour-icons.ts +3 -0
  267. package/src/data/mocks/yamls/add-healthchecks-quickstart.yaml +67 -0
  268. package/src/data/mocks/yamls/explore-pipeline-quickstart.yaml +57 -0
  269. package/src/data/mocks/yamls/explore-serverless-quickstart.yaml +83 -0
  270. package/src/data/mocks/yamls/install-associate-pipeline-quickstart.yaml +74 -0
  271. package/src/data/mocks/yamls/monitor-sampleapp-quickstart.yaml +66 -0
  272. package/src/data/mocks/yamls/sample-application-quickstart.yaml +97 -0
  273. package/src/data/mocks/yamls/serverless-application-quickstart.yaml +141 -0
  274. package/src/data/quick-start-test-data.ts +10 -0
  275. package/src/data/test-utils.ts +11 -0
  276. package/src/declaration.d.ts +2 -0
  277. package/src/index.ts +17 -0
  278. package/src/locales/en/quickstart.json +46 -0
  279. package/src/styles/_base.scss +54 -0
  280. package/src/styles/_dark-custom-override.scss +62 -0
  281. package/src/styles/legacy-bootstrap/README.md +21 -0
  282. package/src/styles/legacy-bootstrap/_code.scss +46 -0
  283. package/src/styles/legacy-bootstrap/_tables.scss +38 -0
  284. package/src/styles/legacy-bootstrap/_type.scss +92 -0
  285. package/src/styles/legacy-bootstrap/_variables.scss +48 -0
  286. package/src/styles/legacy-bootstrap.scss +5 -0
  287. package/src/styles/patternfly-global-entry.ts +1 -0
  288. package/src/styles/patternfly-global.scss +28 -0
  289. package/src/styles/patternfly-nested-entry.ts +1 -0
  290. package/src/styles/patternfly-nested.scss +18 -0
  291. package/src/styles/quickstarts-standalone-entry.ts +1 -0
  292. package/src/styles/quickstarts-standalone.scss +7 -0
  293. package/src/styles/style.scss +12 -0
  294. package/src/styles/vendor-entry.ts +1 -0
  295. package/src/styles/vendor.scss +7 -0
  296. package/src/utils/PluralResolver.ts +362 -0
  297. package/src/utils/asciidoc-procedure-parser.ts +130 -0
  298. package/src/utils/const.ts +10 -0
  299. package/src/utils/help-topic-context.tsx +72 -0
  300. package/src/utils/help-topic-types.ts +16 -0
  301. package/src/utils/quick-start-context.tsx +473 -0
  302. package/src/utils/quick-start-types.ts +73 -0
  303. package/src/utils/quick-start-utils.ts +88 -0
  304. package/src/utils/useLocalStorage.ts +38 -0
@@ -0,0 +1,2593 @@
1
+ import * as React from 'react';
2
+ import React__default, { createContext, useCallback, useEffect, useState } from 'react';
3
+ import { getUniqueId, Card, CardHeader, CardTitle, CardBody, CardFooter, Modal as Modal$1, useIsomorphicLayoutEffect, Tooltip, Alert, CodeBlock, Accordion, AccordionItem, AccordionToggle, AccordionContent, Popover, PopoverPosition, Button, Icon, Text, TextVariants, TextList, TextListItem, Flex, FlexItem, Title, Label, Gallery, GalleryItem, ToolbarItem, SearchInput, Select, SelectList, SelectOption, MenuToggle, Badge, Toolbar, ToolbarContent, EmptyState, EmptyStateHeader, EmptyStateIcon, EmptyStateBody, EmptyStateFooter, EmptyStateActions, Divider, ModalVariant, WizardNavItem, List, ExpandableSection, ListItem, Radio, DrawerPanelContent, DrawerHead, DrawerActions, DrawerCloseButton, DrawerPanelBody, Drawer, DrawerContent, DrawerContentBody, Stack, StackItem } from '@patternfly/react-core';
4
+ import SearchIcon from '@patternfly/react-icons/dist/js/icons/search-icon';
5
+ import { css } from '@patternfly/react-styles';
6
+ import { __rest } from 'tslib';
7
+ import '@patternfly/react-styles/css/components/Form/form';
8
+ import RocketIcon from '@patternfly/react-icons/dist/js/icons/rocket-icon';
9
+ import * as ReactDOM from 'react-dom';
10
+ import { renderToStaticMarkup } from 'react-dom/server';
11
+ import CopyIcon from '@patternfly/react-icons/dist/js/icons/copy-icon';
12
+ import LightbulbIcon from '@patternfly/react-icons/dist/js/icons/lightbulb-icon';
13
+ import FireIcon from '@patternfly/react-icons/dist/js/icons/fire-icon';
14
+ import { Converter } from 'showdown';
15
+ import SyncAltIcon from '@patternfly/react-icons/dist/js/icons/sync-alt-icon';
16
+ import CheckCircleIcon from '@patternfly/react-icons/dist/js/icons/check-circle-icon';
17
+ import ExclamationCircleIcon from '@patternfly/react-icons/dist/js/icons/exclamation-circle-icon';
18
+ import InfoCircleIcon from '@patternfly/react-icons/dist/js/icons/info-circle-icon';
19
+ import '@patternfly/react-tokens/dist/esm/global_danger_color_100';
20
+ import '@patternfly/react-tokens/dist/esm/global_palette_blue_300';
21
+ import okColor from '@patternfly/react-tokens/dist/esm/global_palette_green_500';
22
+ import ExternalLinkAltIcon from '@patternfly/react-icons/dist/js/icons/external-link-alt-icon';
23
+ import OutlinedClockIcon from '@patternfly/react-icons/dist/js/icons/outlined-clock-icon';
24
+ import OutlinedBookmarkIcon from '@patternfly/react-icons/dist/js/icons/outlined-bookmark-icon';
25
+ import ArrowRightIcon from '@patternfly/react-icons/dist/js/icons/arrow-right-icon';
26
+ import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon';
27
+
28
+ function _extends() {
29
+ _extends = Object.assign || function (target) {
30
+ for (var i = 1; i < arguments.length; i++) {
31
+ var source = arguments[i];
32
+
33
+ for (var key in source) {
34
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
35
+ target[key] = source[key];
36
+ }
37
+ }
38
+ }
39
+
40
+ return target;
41
+ };
42
+
43
+ return _extends.apply(this, arguments);
44
+ }
45
+
46
+ var m,x=m||(m={});x.Pop="POP";x.Push="PUSH";x.Replace="REPLACE";var y="production"!==process.env.NODE_ENV?function(a){return Object.freeze(a)}:function(a){return a};function z(a,b){if(!a){"undefined"!==typeof console&&console.warn(b);try{throw Error(b);}catch(g){}}}function A(a){a.preventDefault();a.returnValue="";}
47
+ function B(){var a=[];return {get length(){return a.length},push:function(b){a.push(b);return function(){a=a.filter(function(a){return a!==b});}},call:function(b){a.forEach(function(a){return a&&a(b)});}}}function D(){return Math.random().toString(36).substr(2,8)}function E(a){var b=a.pathname,g=a.search;a=a.hash;return (void 0===b?"/":b)+(void 0===g?"":g)+(void 0===a?"":a)}
48
+ function F(a){var b={};if(a){var g=a.indexOf("#");0<=g&&(b.hash=a.substr(g),a=a.substr(0,g));g=a.indexOf("?");0<=g&&(b.search=a.substr(g),a=a.substr(0,g));a&&(b.pathname=a);}return b}
49
+ function createBrowserHistory(a){function b(){var a=h.location,d=f.state||{};return [d.idx,y({pathname:a.pathname,search:a.search,hash:a.hash,state:d.usr||null,key:d.key||"default"})]}function g(a){return "string"===typeof a?a:E(a)}function t(a,d){void 0===d&&(d=null);return y(_extends({},l,{},"string"===typeof a?F(a):a,{state:d,key:D()}))}function v(a){n=a;a=b();q=a[0];l=a[1];c.call({action:n,location:l});}function w(a,d){function c(){w(a,d);}var k=m.Push,C=t(a,d);if(!e.length||(e.call({action:k,
50
+ location:C,retry:c}),!1)){var b=[{usr:C.state,key:C.key,idx:q+1},g(C)];C=b[0];b=b[1];try{f.pushState(C,"",b);}catch(G){h.location.assign(b);}v(k);}}function u(a,d){function c(){u(a,d);}var b=m.Replace,k=t(a,d);e.length&&(e.call({action:b,location:k,retry:c}),1)||(k=[{usr:k.state,key:k.key,idx:q},g(k)],f.replaceState(k[0],"",k[1]),v(b));}function r(a){f.go(a);}void 0===a&&(a={});a=a.window;var h=void 0===a?document.defaultView:a,f=h.history,p=null;h.addEventListener("popstate",function(){if(p)e.call(p),
51
+ p=null;else {var a=m.Pop,d=b(),c=d[0];d=d[1];if(e.length)if(null!=c){var f=q-c;f&&(p={action:a,location:d,retry:function(){r(-1*f);}},r(f));}else "production"!==process.env.NODE_ENV?z(!1,"You are trying to block a POP navigation to a location that was not created by the history library. The block will fail silently in production, but in general you should do all navigation with the history library (instead of using window.history.pushState directly) to avoid this situation."):void 0;else v(a);}});var n=
52
+ m.Pop;a=b();var q=a[0],l=a[1],c=B(),e=B();null==q&&(q=0,f.replaceState(_extends({},f.state,{idx:q}),""));return {get action(){return n},get location(){return l},createHref:g,push:w,replace:u,go:r,back:function(){r(-1);},forward:function(){r(1);},listen:function(a){return c.push(a)},block:function(a){var d=e.push(a);1===e.length&&h.addEventListener("beforeunload",A);return function(){d();e.length||h.removeEventListener("beforeunload",A);}}}}function createMemoryHistory(a){function b(a,b){void 0===b&&(b=null);return y(_extends({},n,{},"string"===typeof a?F(a):a,{state:b,key:D()}))}function g(a,b,f){return !l.length||(l.call({action:a,location:b,retry:f}),!1)}function t(a,b){p=a;n=b;q.call({action:p,location:n});}function v(a,e){var c=m.Push,d=b(a,e);"production"!==process.env.NODE_ENV?z("/"===n.pathname.charAt(0),"Relative pathnames are not supported in memory history.push("+JSON.stringify(a)+")"):void 0;g(c,d,function(){v(a,e);})&&
53
+ (f+=1,h.splice(f,h.length,d),t(c,d));}function w(a,e){var c=m.Replace,d=b(a,e);"production"!==process.env.NODE_ENV?z("/"===n.pathname.charAt(0),"Relative pathnames are not supported in memory history.replace("+JSON.stringify(a)+")"):void 0;g(c,d,function(){w(a,e);})&&(h[f]=d,t(c,d));}function u(a){var b=Math.min(Math.max(f+a,0),h.length-1),c=m.Pop,d=h[b];g(c,d,function(){u(a);})&&(f=b,t(c,d));}void 0===a&&(a={});var r=a;a=r.initialEntries;r=r.initialIndex;var h=(void 0===a?["/"]:a).map(function(a){var b=
54
+ y(_extends({pathname:"/",search:"",hash:"",state:null,key:D()},"string"===typeof a?F(a):a));"production"!==process.env.NODE_ENV?z("/"===b.pathname.charAt(0),"Relative pathnames are not supported in createMemoryHistory({ initialEntries }) (invalid entry: "+JSON.stringify(a)+")"):void 0;return b}),f=Math.min(Math.max(null==r?h.length-1:r,0),h.length-1),p=m.Pop,n=h[f],q=B(),l=B();return {get index(){return f},get action(){return p},get location(){return n},createHref:function(a){return "string"===typeof a?
55
+ a:E(a)},push:v,replace:w,go:u,back:function(){u(-1);},forward:function(){u(1);},listen:function(a){return q.push(a)},block:function(a){return l.push(a)}}}
56
+
57
+ var QuickStartStatus;
58
+ (function (QuickStartStatus) {
59
+ QuickStartStatus["COMPLETE"] = "Complete";
60
+ QuickStartStatus["IN_PROGRESS"] = "In Progress";
61
+ QuickStartStatus["NOT_STARTED"] = "Not started";
62
+ })(QuickStartStatus || (QuickStartStatus = {}));
63
+ var QuickStartTaskStatus;
64
+ (function (QuickStartTaskStatus) {
65
+ QuickStartTaskStatus["INIT"] = "Initial";
66
+ QuickStartTaskStatus["VISITED"] = "Visited";
67
+ QuickStartTaskStatus["REVIEW"] = "Review";
68
+ QuickStartTaskStatus["SUCCESS"] = "Success";
69
+ QuickStartTaskStatus["FAILED"] = "Failed";
70
+ })(QuickStartTaskStatus || (QuickStartTaskStatus = {}));
71
+
72
+ const QUICKSTART_SEARCH_FILTER_KEY = 'keyword';
73
+ const QUICKSTART_STATUS_FILTER_KEY = 'status';
74
+ const QUICKSTART_ID_FILTER_KEY = 'quickstart';
75
+ const QUICKSTART_TASKS_INITIAL_STATES = [
76
+ QuickStartTaskStatus.INIT,
77
+ QuickStartTaskStatus.VISITED,
78
+ ];
79
+ const HELP_TOPIC_NAME_KEY = 'topic';
80
+
81
+ let createHistory;
82
+ try {
83
+ if (process.env.NODE_ENV === 'test') {
84
+ // Running in node. Can't use browser history
85
+ createHistory = createMemoryHistory;
86
+ }
87
+ else {
88
+ createHistory = createBrowserHistory;
89
+ }
90
+ }
91
+ catch (unused) {
92
+ createHistory = createBrowserHistory;
93
+ }
94
+ const history = createHistory();
95
+ const removeQueryArgument = (k) => {
96
+ const params = new URLSearchParams(window.location.search);
97
+ if (params.has(k)) {
98
+ params.delete(k);
99
+ const url = new URL(window.location.href);
100
+ history.replace(`${url.pathname}?${params.toString()}${url.hash}`);
101
+ }
102
+ };
103
+ const setQueryArgument = (k, v) => {
104
+ if (!v) {
105
+ return removeQueryArgument(k);
106
+ }
107
+ const params = new URLSearchParams(window.location.search);
108
+ if (params.get(k) !== v) {
109
+ params.set(k, v);
110
+ const url = new URL(window.location.href);
111
+ history.replace(`${url.pathname}?${params.toString()}${url.hash}`);
112
+ }
113
+ };
114
+ const clearFilterParams = () => {
115
+ removeQueryArgument(QUICKSTART_SEARCH_FILTER_KEY);
116
+ removeQueryArgument(QUICKSTART_STATUS_FILTER_KEY);
117
+ };
118
+
119
+ var Status$1 = "Status";
120
+ var Prerequisites = "Prerequisites";
121
+ var Complete = "Complete";
122
+ var Start = "Start";
123
+ var Continue = "Continue";
124
+ var Next = "Next";
125
+ var Close = "Close";
126
+ var Back = "Back";
127
+ var Restart = "Restart";
128
+ var Yes = "Yes";
129
+ var No = "No";
130
+ var Cancel = "Cancel";
131
+ var Leave = "Leave";
132
+ var Type = "Quick start";
133
+ var en = {
134
+ "No results found": "No results found",
135
+ "No results match the filter criteria. Remove filters or clear all filters to show results.": "No results match the filter criteria. Remove filters or clear all filters to show results.",
136
+ "Clear all filters": "Clear all filters",
137
+ "Quick Starts": "Quick Starts",
138
+ "Complete ({{statusCount, number}})": "Complete ({{statusCount, number}})",
139
+ "In progress ({{statusCount, number}})": "In progress ({{statusCount, number}})",
140
+ "Not started ({{statusCount, number}})": "Not started ({{statusCount, number}})",
141
+ "Filter by keyword...": "Filter by keyword...",
142
+ "Select filter": "Select filter",
143
+ Status: Status$1,
144
+ "{{count, number}} item": "{{count, number}} item",
145
+ "{{count, number}} item_plural": "{{count, number}} items",
146
+ "Prerequisites ({{totalPrereqs}})": "Prerequisites ({{totalPrereqs}})",
147
+ "View Prerequisites ({{totalPrereqs}})": "View Prerequisites ({{totalPrereqs}})",
148
+ Prerequisites: Prerequisites,
149
+ "Show prerequisites": "Show prerequisites",
150
+ Complete: Complete,
151
+ "In progress": "In progress",
152
+ "Not started": "Not started",
153
+ "{{duration, number}} minutes": "{{duration, number}} minutes",
154
+ "One or more verifications did not pass during this quick start. Revisit the tasks or the help links, and then try again.": "One or more verifications did not pass during this quick start. Revisit the tasks or the help links, and then try again.",
155
+ "Start {{nextQSDisplayName}} quick start": "Start {{nextQSDisplayName}} quick start",
156
+ Start: Start,
157
+ Continue: Continue,
158
+ Next: Next,
159
+ Close: Close,
160
+ Back: Back,
161
+ Restart: Restart,
162
+ "In this quick start, you will complete {{count, number}} task": "In this quick start, you will complete {{count, number}} task",
163
+ "In this quick start, you will complete {{count, number}} task_plural": "In this quick start, you will complete {{count, number}} tasks",
164
+ "{{taskIndex, number}}": "{{taskIndex, number}}",
165
+ "Check your work": "Check your work",
166
+ Yes: Yes,
167
+ No: No,
168
+ "{{index, number}} of {{tasks, number}}": "{{index, number}} of {{tasks, number}}",
169
+ "Leave quick start?": "Leave quick start?",
170
+ Cancel: Cancel,
171
+ Leave: Leave,
172
+ "Your progress will be saved.": "Your progress will be saved.",
173
+ "Not available": "Not available",
174
+ "Copy to clipboard": "Copy to clipboard",
175
+ "Successfully copied to clipboard!": "Successfully copied to clipboard!",
176
+ Type: Type,
177
+ "{{type}} • {{duration, number}} minutes": "{{type}} • {{duration, number}} minutes"
178
+ };
179
+
180
+ /* eslint-disable */
181
+ // https://github.com/i18next/i18next/blob/master/src/PluralResolver.js
182
+ const sets = [
183
+ {
184
+ lngs: [
185
+ 'ach',
186
+ 'ak',
187
+ 'am',
188
+ 'arn',
189
+ 'br',
190
+ 'fil',
191
+ 'gun',
192
+ 'ln',
193
+ 'mfe',
194
+ 'mg',
195
+ 'mi',
196
+ 'oc',
197
+ 'pt',
198
+ 'pt-BR',
199
+ 'tg',
200
+ 'tl',
201
+ 'ti',
202
+ 'tr',
203
+ 'uz',
204
+ 'wa',
205
+ ],
206
+ nr: [1, 2],
207
+ fc: 1,
208
+ },
209
+ {
210
+ lngs: [
211
+ 'af',
212
+ 'an',
213
+ 'ast',
214
+ 'az',
215
+ 'bg',
216
+ 'bn',
217
+ 'ca',
218
+ 'da',
219
+ 'de',
220
+ 'dev',
221
+ 'el',
222
+ 'en',
223
+ 'eo',
224
+ 'es',
225
+ 'et',
226
+ 'eu',
227
+ 'fi',
228
+ 'fo',
229
+ 'fur',
230
+ 'fy',
231
+ 'gl',
232
+ 'gu',
233
+ 'ha',
234
+ 'hi',
235
+ 'hu',
236
+ 'hy',
237
+ 'ia',
238
+ 'it',
239
+ 'kk',
240
+ 'kn',
241
+ 'ku',
242
+ 'lb',
243
+ 'mai',
244
+ 'ml',
245
+ 'mn',
246
+ 'mr',
247
+ 'nah',
248
+ 'nap',
249
+ 'nb',
250
+ 'ne',
251
+ 'nl',
252
+ 'nn',
253
+ 'no',
254
+ 'nso',
255
+ 'pa',
256
+ 'pap',
257
+ 'pms',
258
+ 'ps',
259
+ 'pt-PT',
260
+ 'rm',
261
+ 'sco',
262
+ 'se',
263
+ 'si',
264
+ 'so',
265
+ 'son',
266
+ 'sq',
267
+ 'sv',
268
+ 'sw',
269
+ 'ta',
270
+ 'te',
271
+ 'tk',
272
+ 'ur',
273
+ 'yo',
274
+ ],
275
+ nr: [1, 2],
276
+ fc: 2,
277
+ },
278
+ {
279
+ lngs: [
280
+ 'ay',
281
+ 'bo',
282
+ 'cgg',
283
+ 'fa',
284
+ 'ht',
285
+ 'id',
286
+ 'ja',
287
+ 'jbo',
288
+ 'ka',
289
+ 'km',
290
+ 'ko',
291
+ 'ky',
292
+ 'lo',
293
+ 'ms',
294
+ 'sah',
295
+ 'su',
296
+ 'th',
297
+ 'tt',
298
+ 'ug',
299
+ 'vi',
300
+ 'wo',
301
+ 'zh',
302
+ ],
303
+ nr: [1],
304
+ fc: 3,
305
+ },
306
+ { lngs: ['be', 'bs', 'cnr', 'dz', 'hr', 'ru', 'sr', 'uk'], nr: [1, 2, 5], fc: 4 },
307
+ { lngs: ['ar'], nr: [0, 1, 2, 3, 11, 100], fc: 5 },
308
+ { lngs: ['cs', 'sk'], nr: [1, 2, 5], fc: 6 },
309
+ { lngs: ['csb', 'pl'], nr: [1, 2, 5], fc: 7 },
310
+ { lngs: ['cy'], nr: [1, 2, 3, 8], fc: 8 },
311
+ { lngs: ['fr'], nr: [1, 2], fc: 9 },
312
+ { lngs: ['ga'], nr: [1, 2, 3, 7, 11], fc: 10 },
313
+ { lngs: ['gd'], nr: [1, 2, 3, 20], fc: 11 },
314
+ { lngs: ['is'], nr: [1, 2], fc: 12 },
315
+ { lngs: ['jv'], nr: [0, 1], fc: 13 },
316
+ { lngs: ['kw'], nr: [1, 2, 3, 4], fc: 14 },
317
+ { lngs: ['lt'], nr: [1, 2, 10], fc: 15 },
318
+ { lngs: ['lv'], nr: [1, 2, 0], fc: 16 },
319
+ { lngs: ['mk'], nr: [1, 2], fc: 17 },
320
+ { lngs: ['mnk'], nr: [0, 1, 2], fc: 18 },
321
+ { lngs: ['mt'], nr: [1, 2, 11, 20], fc: 19 },
322
+ { lngs: ['or'], nr: [2, 1], fc: 2 },
323
+ { lngs: ['ro'], nr: [1, 2, 20], fc: 20 },
324
+ { lngs: ['sl'], nr: [5, 1, 2, 3], fc: 21 },
325
+ { lngs: ['he', 'iw'], nr: [1, 2, 20, 21], fc: 22 },
326
+ ];
327
+ const _rulesPluralsTypes = {
328
+ 1: function (n) {
329
+ return Number(n > 1);
330
+ },
331
+ 2: function (n) {
332
+ return Number(n != 1);
333
+ },
334
+ 3: function (n) {
335
+ return 0;
336
+ },
337
+ 4: function (n) {
338
+ return Number(n % 10 == 1 && n % 100 != 11
339
+ ? 0
340
+ : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20)
341
+ ? 1
342
+ : 2);
343
+ },
344
+ 5: function (n) {
345
+ return Number(n == 0
346
+ ? 0
347
+ : n == 1
348
+ ? 1
349
+ : n == 2
350
+ ? 2
351
+ : n % 100 >= 3 && n % 100 <= 10
352
+ ? 3
353
+ : n % 100 >= 11
354
+ ? 4
355
+ : 5);
356
+ },
357
+ 6: function (n) {
358
+ return Number(n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2);
359
+ },
360
+ 7: function (n) {
361
+ return Number(n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
362
+ },
363
+ 8: function (n) {
364
+ return Number(n == 1 ? 0 : n == 2 ? 1 : n != 8 && n != 11 ? 2 : 3);
365
+ },
366
+ 9: function (n) {
367
+ return Number(n >= 2);
368
+ },
369
+ 10: function (n) {
370
+ return Number(n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4);
371
+ },
372
+ 11: function (n) {
373
+ return Number(n == 1 || n == 11 ? 0 : n == 2 || n == 12 ? 1 : n > 2 && n < 20 ? 2 : 3);
374
+ },
375
+ 12: function (n) {
376
+ return Number(n % 10 != 1 || n % 100 == 11);
377
+ },
378
+ 13: function (n) {
379
+ return Number(n !== 0);
380
+ },
381
+ 14: function (n) {
382
+ return Number(n == 1 ? 0 : n == 2 ? 1 : n == 3 ? 2 : 3);
383
+ },
384
+ 15: function (n) {
385
+ return Number(n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
386
+ },
387
+ 16: function (n) {
388
+ return Number(n % 10 == 1 && n % 100 != 11 ? 0 : n !== 0 ? 1 : 2);
389
+ },
390
+ 17: function (n) {
391
+ return Number(n == 1 || (n % 10 == 1 && n % 100 != 11) ? 0 : 1);
392
+ },
393
+ 18: function (n) {
394
+ return Number(n == 0 ? 0 : n == 1 ? 1 : 2);
395
+ },
396
+ 19: function (n) {
397
+ return Number(n == 1
398
+ ? 0
399
+ : n == 0 || (n % 100 > 1 && n % 100 < 11)
400
+ ? 1
401
+ : n % 100 > 10 && n % 100 < 20
402
+ ? 2
403
+ : 3);
404
+ },
405
+ 20: function (n) {
406
+ return Number(n == 1 ? 0 : n == 0 || (n % 100 > 0 && n % 100 < 20) ? 1 : 2);
407
+ },
408
+ 21: function (n) {
409
+ return Number(n % 100 == 1 ? 1 : n % 100 == 2 ? 2 : n % 100 == 3 || n % 100 == 4 ? 3 : 0);
410
+ },
411
+ 22: function (n) {
412
+ return Number(n == 1 ? 0 : n == 2 ? 1 : (n < 0 || n > 10) && n % 10 == 0 ? 2 : 3);
413
+ },
414
+ };
415
+ function createRules() {
416
+ const rules = {};
417
+ sets.forEach((set) => {
418
+ set.lngs.forEach((l) => {
419
+ rules[l] = {
420
+ numbers: set.nr,
421
+ plurals: _rulesPluralsTypes[set.fc],
422
+ };
423
+ });
424
+ });
425
+ return rules;
426
+ }
427
+ class PluralResolver {
428
+ constructor(options = {}) {
429
+ this.options = options;
430
+ this.rules = createRules();
431
+ }
432
+ addRule(lng, obj) {
433
+ this.rules[lng] = obj;
434
+ }
435
+ getRule(code) {
436
+ return this.rules[code];
437
+ }
438
+ needsPlural(code) {
439
+ const rule = this.getRule(code);
440
+ return rule && rule.numbers.length > 1;
441
+ }
442
+ getPluralFormsOfKey(code, key) {
443
+ return this.getSuffixes(code).map((suffix) => key + suffix);
444
+ }
445
+ getSuffixes(code) {
446
+ const rule = this.getRule(code);
447
+ if (!rule) {
448
+ return [];
449
+ }
450
+ return rule.numbers.map((number) => this.getSuffix(code, number));
451
+ }
452
+ getSuffix(code, count) {
453
+ const rule = this.getRule(code);
454
+ if (rule) {
455
+ // if (rule.numbers.length === 1) return ''; // only singular
456
+ const idx = rule.noAbs ? rule.plurals(count) : rule.plurals(Math.abs(count));
457
+ let suffix = rule.numbers[idx];
458
+ // special treatment for lngs only having singular and plural
459
+ if (this.options.simplifyPluralSuffix && rule.numbers.length === 2 && rule.numbers[0] === 1) {
460
+ if (suffix === 2) {
461
+ suffix = 'plural';
462
+ }
463
+ else if (suffix === 1) {
464
+ suffix = '';
465
+ }
466
+ }
467
+ const returnSuffix = () => this.options.prepend && suffix.toString()
468
+ ? this.options.prepend + suffix.toString()
469
+ : suffix.toString();
470
+ // COMPATIBILITY JSON
471
+ // v1
472
+ if (this.options.compatibilityJSON === 'v1') {
473
+ if (suffix === 1) {
474
+ return '';
475
+ }
476
+ if (typeof suffix === 'number') {
477
+ return `_plural_${suffix.toString()}`;
478
+ }
479
+ return returnSuffix();
480
+ }
481
+ if ( /* v2 */this.options.compatibilityJSON === 'v2') {
482
+ return returnSuffix();
483
+ }
484
+ if (
485
+ /* v3 - gettext index */ this.options.simplifyPluralSuffix &&
486
+ rule.numbers.length === 2 &&
487
+ rule.numbers[0] === 1) {
488
+ return returnSuffix();
489
+ }
490
+ return this.options.prepend && idx.toString()
491
+ ? this.options.prepend + idx.toString()
492
+ : idx.toString();
493
+ }
494
+ // this.logger.warn(`no plural rule found for: ${code}`);
495
+ return '';
496
+ }
497
+ }
498
+
499
+ const QUICK_START_NAME = 'console.openshift.io/name';
500
+ const getQuickStartByName = (name, quickStarts) => quickStarts.find((quickStart) => quickStart.metadata.name === name);
501
+ const getQuickStartStatus = (allQuickStartStates, quickStartID) => { var _a, _b; return (_b = (_a = allQuickStartStates === null || allQuickStartStates === void 0 ? void 0 : allQuickStartStates[quickStartID]) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : QuickStartStatus.NOT_STARTED; };
502
+ const getTaskStatusKey = (taskNumber) => `taskStatus${taskNumber}`;
503
+ const getQuickStartStatusCount = (allQuickStartStates, quickStarts) => quickStarts.reduce((totals, item) => {
504
+ totals[getQuickStartStatus(allQuickStartStates, item.metadata.name)]++;
505
+ return totals;
506
+ }, {
507
+ [QuickStartStatus.IN_PROGRESS]: 0,
508
+ [QuickStartStatus.COMPLETE]: 0,
509
+ [QuickStartStatus.NOT_STARTED]: 0,
510
+ });
511
+ const getDisabledQuickStarts = () => {
512
+ var _a, _b;
513
+ let disabledQuickStarts = [];
514
+ const quickStartServerData = (_a = window.SERVER_FLAGS) === null || _a === void 0 ? void 0 : _a.quickStarts;
515
+ try {
516
+ if (quickStartServerData) {
517
+ disabledQuickStarts = (_b = JSON.parse(quickStartServerData).disabled) !== null && _b !== void 0 ? _b : [];
518
+ }
519
+ }
520
+ catch (e) {
521
+ // eslint-disable-next-line no-console
522
+ console.error('error while parsing SERVER_FLAG.quickStarts', e);
523
+ }
524
+ return disabledQuickStarts;
525
+ };
526
+ const isDisabledQuickStart = (quickstart, disabledQuickStarts) => {
527
+ var _a, _b;
528
+ const quickStartName = (_b = (_a = quickstart.metadata.annotations) === null || _a === void 0 ? void 0 : _a[QUICK_START_NAME]) !== null && _b !== void 0 ? _b : quickstart.metadata.name;
529
+ return disabledQuickStarts.includes(quickStartName);
530
+ };
531
+ const filterQuickStarts = (quickStarts, filterText, statusFilters, allQuickStartStates) => {
532
+ const searchText = filterText.toLowerCase();
533
+ return quickStarts.filter(({ metadata: { name }, spec: { displayName, prerequisites = [], description } }) => {
534
+ const matchesFilter = statusFilters.length > 0
535
+ ? statusFilters.includes(getQuickStartStatus(allQuickStartStates, name))
536
+ : true;
537
+ const matchesText = displayName.toLowerCase().includes(searchText) ||
538
+ description.toLowerCase().includes(searchText) ||
539
+ prerequisites.some((text) => text.toLowerCase().includes(searchText));
540
+ return matchesFilter && matchesText;
541
+ });
542
+ };
543
+ const camelize = (str) => str.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function (match, index) {
544
+ if (+match === 0) {
545
+ return '';
546
+ } // or if (/\s+/.test(match)) for white spaces
547
+ return index === 0 ? match.toLowerCase() : match.toUpperCase();
548
+ });
549
+
550
+ const pluralResolver = new PluralResolver({ simplifyPluralSuffix: true });
551
+ const getDefaultQuickStartState = (totalTasks, initialStatus) => {
552
+ const defaultQuickStartState = {
553
+ status: initialStatus || QuickStartStatus.NOT_STARTED,
554
+ taskNumber: -1,
555
+ };
556
+ if (totalTasks) {
557
+ for (let i = 0; i < totalTasks; i++) {
558
+ defaultQuickStartState[getTaskStatusKey(i)] = QuickStartTaskStatus.INIT;
559
+ }
560
+ }
561
+ return defaultQuickStartState;
562
+ };
563
+ const QuickStartContextDefaults = {
564
+ allQuickStarts: [],
565
+ activeQuickStartID: '',
566
+ allQuickStartStates: {},
567
+ activeQuickStartState: {},
568
+ setAllQuickStarts: () => { },
569
+ resourceBundle: en,
570
+ getResource: (resource) => resource,
571
+ language: 'en',
572
+ useQueryParams: true,
573
+ filter: {
574
+ keyword: '',
575
+ status: {
576
+ statusTypes: {},
577
+ statusFilters: [],
578
+ },
579
+ },
580
+ setFilter: () => { },
581
+ footer: null,
582
+ useLegacyHeaderColors: false,
583
+ markdown: null,
584
+ loading: false,
585
+ alwaysShowTaskReview: true,
586
+ };
587
+ const QuickStartContext = createContext(QuickStartContextDefaults);
588
+ const getResource = (resource, options, resourceBundle, lng) => {
589
+ if (options && !isNaN(options.count)) {
590
+ const suffix = pluralResolver.getSuffix(lng, options.count);
591
+ if (suffix && resourceBundle[`${resource}_${suffix}`]) {
592
+ // needs plural
593
+ return resourceBundle[`${resource}_${suffix}`];
594
+ }
595
+ }
596
+ return (resourceBundle && resourceBundle[resource]) || resource;
597
+ };
598
+ const useValuesForQuickStartContext = (value = {}) => {
599
+ var _a, _b;
600
+ const combinedValue = Object.assign(Object.assign({}, QuickStartContextDefaults), value);
601
+ const { activeQuickStartID, setActiveQuickStartID, setAllQuickStartStates, useQueryParams, allQuickStartStates, allQuickStarts = [], footer, useLegacyHeaderColors, markdown, } = combinedValue;
602
+ const [quickStarts, setQuickStarts] = React__default.useState(combinedValue.allQuickStarts || []);
603
+ const [resourceBundle, setResourceBundle] = React__default.useState(Object.assign(Object.assign({}, en), combinedValue.resourceBundle));
604
+ const [language, setLanguage] = React__default.useState(combinedValue.language);
605
+ const changeResourceBundle = (bundle, lng) => {
606
+ lng && setLanguage(lng);
607
+ setResourceBundle(Object.assign(Object.assign({}, en), bundle));
608
+ };
609
+ const findResource = useCallback((resource, count) => getResource(resource, count !== undefined ? { count } : null, resourceBundle, language), [resourceBundle, language]);
610
+ const [loading, setLoading] = React__default.useState(combinedValue.loading);
611
+ const [alwaysShowTaskReview, setAlwaysShowTaskReview] = React__default.useState(combinedValue.alwaysShowTaskReview);
612
+ const initialSearchParams = new URLSearchParams(window.location.search);
613
+ const initialSearchQuery = initialSearchParams.get(QUICKSTART_SEARCH_FILTER_KEY) || '';
614
+ const initialStatusFilters = ((_a = initialSearchParams.get(QUICKSTART_STATUS_FILTER_KEY)) === null || _a === void 0 ? void 0 : _a.split(',')) || [];
615
+ const quickStartStatusCount = getQuickStartStatusCount(allQuickStartStates, allQuickStarts);
616
+ const [statusTypes, setStatusTypes] = React__default.useState({
617
+ [QuickStartStatus.COMPLETE]: findResource('Complete ({{statusCount, number}})').replace('{{statusCount, number}}', quickStartStatusCount[QuickStartStatus.COMPLETE]),
618
+ [QuickStartStatus.IN_PROGRESS]: findResource('In progress ({{statusCount, number}})').replace('{{statusCount, number}}', quickStartStatusCount[QuickStartStatus.IN_PROGRESS]),
619
+ [QuickStartStatus.NOT_STARTED]: findResource('Not started ({{statusCount, number}})').replace('{{statusCount, number}}', quickStartStatusCount[QuickStartStatus.NOT_STARTED]),
620
+ });
621
+ const [statusFilters, setStatusFilters] = React__default.useState(initialStatusFilters);
622
+ const [filterKeyword, setFilterKeyword] = React__default.useState(initialSearchQuery);
623
+ const setFilter = (type, val) => {
624
+ if (type === 'keyword') {
625
+ setFilterKeyword(val);
626
+ }
627
+ else if (type === 'status') {
628
+ setStatusFilters(val);
629
+ }
630
+ };
631
+ React__default.useEffect(() => {
632
+ const updatedQuickStartStatusCount = getQuickStartStatusCount(allQuickStartStates, quickStarts);
633
+ setStatusTypes({
634
+ [QuickStartStatus.COMPLETE]: findResource('Complete ({{statusCount, number}})').replace('{{statusCount, number}}', updatedQuickStartStatusCount[QuickStartStatus.COMPLETE]),
635
+ [QuickStartStatus.IN_PROGRESS]: findResource('In progress ({{statusCount, number}})').replace('{{statusCount, number}}', updatedQuickStartStatusCount[QuickStartStatus.IN_PROGRESS]),
636
+ [QuickStartStatus.NOT_STARTED]: findResource('Not started ({{statusCount, number}})').replace('{{statusCount, number}}', updatedQuickStartStatusCount[QuickStartStatus.NOT_STARTED]),
637
+ });
638
+ }, [allQuickStartStates, findResource, quickStarts]);
639
+ const updateAllQuickStarts = (qs) => {
640
+ setQuickStarts(qs);
641
+ };
642
+ const setActiveQuickStart = useCallback((quickStartId, totalTasks) => {
643
+ setActiveQuickStartID((id) => {
644
+ if (!quickStartId || id === quickStartId) {
645
+ useQueryParams && removeQueryArgument(QUICKSTART_ID_FILTER_KEY);
646
+ return '';
647
+ }
648
+ useQueryParams && setQueryArgument(QUICKSTART_ID_FILTER_KEY, quickStartId);
649
+ return quickStartId;
650
+ });
651
+ setAllQuickStartStates((qs) => !quickStartId || qs[quickStartId]
652
+ ? qs
653
+ : Object.assign(Object.assign({}, qs), { [quickStartId]: getDefaultQuickStartState(totalTasks) }));
654
+ }, [setActiveQuickStartID, setAllQuickStartStates, useQueryParams]);
655
+ const startQuickStart = useCallback((quickStartId, totalTasks) => {
656
+ setActiveQuickStartID((id) => {
657
+ if (!id || id !== quickStartId) {
658
+ useQueryParams && setQueryArgument(QUICKSTART_ID_FILTER_KEY, quickStartId);
659
+ return quickStartId;
660
+ }
661
+ useQueryParams && setQueryArgument(QUICKSTART_ID_FILTER_KEY, id);
662
+ return id;
663
+ });
664
+ setAllQuickStartStates((qs) => {
665
+ if (qs.hasOwnProperty(quickStartId)) {
666
+ return Object.assign(Object.assign({}, qs), { [quickStartId]: Object.assign(Object.assign({}, qs[quickStartId]), { status: QuickStartStatus.IN_PROGRESS }) });
667
+ }
668
+ return Object.assign(Object.assign({}, qs), { [quickStartId]: getDefaultQuickStartState(totalTasks, QuickStartStatus.IN_PROGRESS) });
669
+ });
670
+ }, [setActiveQuickStartID, setAllQuickStartStates, useQueryParams]);
671
+ const restartQuickStart = useCallback((quickStartId, totalTasks) => {
672
+ setActiveQuickStartID((id) => {
673
+ if (!id || id !== quickStartId) {
674
+ useQueryParams && setQueryArgument(QUICKSTART_ID_FILTER_KEY, quickStartId);
675
+ return quickStartId;
676
+ }
677
+ useQueryParams && setQueryArgument(QUICKSTART_ID_FILTER_KEY, id);
678
+ return id;
679
+ });
680
+ setAllQuickStartStates((qs) => (Object.assign(Object.assign({}, qs), { [quickStartId]: getDefaultQuickStartState(totalTasks, QuickStartStatus.NOT_STARTED) })));
681
+ }, [setActiveQuickStartID, setAllQuickStartStates, useQueryParams]);
682
+ // When alwaysShowTaskReview preference is enabled, skip visited step and go directly to review
683
+ const stepAfterInitial = alwaysShowTaskReview
684
+ ? QuickStartTaskStatus.REVIEW
685
+ : QuickStartTaskStatus.VISITED;
686
+ const nextStep = useCallback((totalTasks) => {
687
+ if (!activeQuickStartID) {
688
+ return;
689
+ }
690
+ setAllQuickStartStates((qs) => {
691
+ const quickStart = qs[activeQuickStartID];
692
+ const status = quickStart === null || quickStart === void 0 ? void 0 : quickStart.status;
693
+ const taskNumber = quickStart === null || quickStart === void 0 ? void 0 : quickStart.taskNumber;
694
+ const taskStatus = quickStart[getTaskStatusKey(taskNumber)];
695
+ let updatedStatus;
696
+ let updatedTaskNumber;
697
+ let updatedTaskStatus;
698
+ if (status === QuickStartStatus.NOT_STARTED) {
699
+ updatedStatus = QuickStartStatus.IN_PROGRESS;
700
+ }
701
+ else if (status === QuickStartStatus.IN_PROGRESS &&
702
+ !QUICKSTART_TASKS_INITIAL_STATES.includes(taskStatus) &&
703
+ taskNumber === totalTasks - 1) {
704
+ updatedStatus = QuickStartStatus.COMPLETE;
705
+ }
706
+ if (taskStatus === QuickStartTaskStatus.VISITED) {
707
+ updatedTaskStatus = QuickStartTaskStatus.REVIEW;
708
+ }
709
+ if (taskNumber < totalTasks && !updatedTaskStatus) {
710
+ updatedTaskNumber = taskNumber + 1;
711
+ }
712
+ const markInitialStepVisitedOrReview = updatedTaskNumber > -1 &&
713
+ quickStart[getTaskStatusKey(updatedTaskNumber)] === QuickStartTaskStatus.INIT
714
+ ? stepAfterInitial
715
+ : quickStart[getTaskStatusKey(updatedTaskNumber)];
716
+ const newState = Object.assign(Object.assign({}, qs), { [activeQuickStartID]: Object.assign(Object.assign(Object.assign(Object.assign({}, quickStart), (updatedStatus ? { status: updatedStatus } : {})), (updatedTaskNumber > -1
717
+ ? {
718
+ taskNumber: updatedTaskNumber,
719
+ [getTaskStatusKey(updatedTaskNumber)]: markInitialStepVisitedOrReview,
720
+ }
721
+ : {})), (updatedTaskStatus ? { [getTaskStatusKey(taskNumber)]: updatedTaskStatus } : {})) });
722
+ return newState;
723
+ });
724
+ }, [activeQuickStartID, setAllQuickStartStates, stepAfterInitial]);
725
+ const previousStep = useCallback(() => {
726
+ setAllQuickStartStates((qs) => {
727
+ const quickStart = qs[activeQuickStartID];
728
+ const taskNumber = quickStart === null || quickStart === void 0 ? void 0 : quickStart.taskNumber;
729
+ if (taskNumber < 0) {
730
+ return qs;
731
+ }
732
+ return Object.assign(Object.assign({}, qs), { [activeQuickStartID]: Object.assign(Object.assign({}, quickStart), { taskNumber: taskNumber - 1 }) });
733
+ });
734
+ }, [activeQuickStartID, setAllQuickStartStates]);
735
+ const setQuickStartTaskNumber = useCallback((quickStartId, taskNumber) => {
736
+ setAllQuickStartStates((qs) => {
737
+ const quickStart = qs[quickStartId];
738
+ const status = quickStart === null || quickStart === void 0 ? void 0 : quickStart.status;
739
+ let updatedStatus;
740
+ if (taskNumber > -1 && status === QuickStartStatus.NOT_STARTED) {
741
+ updatedStatus = QuickStartStatus.IN_PROGRESS;
742
+ }
743
+ let updatedTaskStatus = {};
744
+ for (let taskIndex = 0; taskIndex <= taskNumber; taskIndex++) {
745
+ const taskStatus = quickStart[getTaskStatusKey(taskIndex)];
746
+ const newTaskStatus = taskStatus === QuickStartTaskStatus.INIT ? stepAfterInitial : undefined;
747
+ if (newTaskStatus) {
748
+ updatedTaskStatus = Object.assign(Object.assign({}, updatedTaskStatus), { [getTaskStatusKey(taskIndex)]: newTaskStatus });
749
+ }
750
+ }
751
+ const updatedQuickStart = Object.assign(Object.assign(Object.assign(Object.assign({}, quickStart), (updatedStatus ? { status: updatedStatus } : {})), { taskNumber }), updatedTaskStatus);
752
+ return Object.assign(Object.assign({}, qs), { [quickStartId]: updatedQuickStart });
753
+ });
754
+ }, [setAllQuickStartStates, stepAfterInitial]);
755
+ const setQuickStartTaskStatus = useCallback((taskStatus) => {
756
+ const quickStart = allQuickStartStates[activeQuickStartID];
757
+ const { taskNumber } = quickStart;
758
+ const updatedQuickStart = Object.assign(Object.assign({}, quickStart), { [getTaskStatusKey(taskNumber)]: taskStatus });
759
+ setAllQuickStartStates((qs) => (Object.assign(Object.assign({}, qs), { [activeQuickStartID]: updatedQuickStart })));
760
+ }, [allQuickStartStates, activeQuickStartID, setAllQuickStartStates]);
761
+ const activeQuickStartState = (_b = allQuickStartStates === null || allQuickStartStates === void 0 ? void 0 : allQuickStartStates[activeQuickStartID]) !== null && _b !== void 0 ? _b : {};
762
+ const getQuickStartForId = useCallback((id) => allQuickStartStates[id], [
763
+ allQuickStartStates,
764
+ ]);
765
+ return {
766
+ allQuickStarts: quickStarts,
767
+ setAllQuickStarts: updateAllQuickStarts,
768
+ activeQuickStartID,
769
+ setActiveQuickStartID,
770
+ allQuickStartStates,
771
+ setAllQuickStartStates,
772
+ activeQuickStartState,
773
+ setActiveQuickStart: value.setActiveQuickStart || setActiveQuickStart,
774
+ startQuickStart: value.startQuickStart || startQuickStart,
775
+ restartQuickStart: value.restartQuickStart || restartQuickStart,
776
+ nextStep: value.nextStep || nextStep,
777
+ previousStep: value.previousStep || previousStep,
778
+ setQuickStartTaskNumber,
779
+ setQuickStartTaskStatus,
780
+ getQuickStartForId,
781
+ footer,
782
+ useLegacyHeaderColors,
783
+ useQueryParams,
784
+ markdown,
785
+ resourceBundle,
786
+ getResource: findResource,
787
+ setResourceBundle: changeResourceBundle,
788
+ language,
789
+ setLanguage,
790
+ // revisit if this should be in public context API
791
+ filter: {
792
+ keyword: filterKeyword,
793
+ status: {
794
+ statusTypes,
795
+ statusFilters,
796
+ },
797
+ },
798
+ setFilter,
799
+ loading,
800
+ setLoading,
801
+ alwaysShowTaskReview,
802
+ setAlwaysShowTaskReview,
803
+ };
804
+ };
805
+ const QuickStartContextProvider = ({ children, value }) => (React__default.createElement(QuickStartContext.Provider, { value: useValuesForQuickStartContext(value) }, children));
806
+
807
+ const Box = ({ children, className }) => (React.createElement("div", { className: css('pfext-status-box', className) }, children));
808
+ const Loading = ({ className }) => (React.createElement("div", { className: css('pfext-m-loader', className) },
809
+ React.createElement("div", { className: "pfext-m-loader-dot__one" }),
810
+ React.createElement("div", { className: "pfext-m-loader-dot__two" }),
811
+ React.createElement("div", { className: "pfext-m-loader-dot__three" })));
812
+ Loading.displayName = 'Loading';
813
+ const LoadingBox = ({ className, message }) => (React.createElement(Box, { className: css('pfext-status-box--loading', className) },
814
+ React.createElement(Loading, null),
815
+ message && React.createElement("div", { className: "pfext-status-box__loading-message" }, message)));
816
+ LoadingBox.displayName = 'LoadingBox';
817
+ const EmptyBox = ({ label }) => {
818
+ const { getResource } = React.useContext(QuickStartContext);
819
+ return (React.createElement(Box, null,
820
+ React.createElement("div", { "data-test": "empty-message", className: "text-center" }, label
821
+ ? getResource('No {{label}} found').replace('{{label}}', label)
822
+ : getResource('Not found'))));
823
+ };
824
+ EmptyBox.displayName = 'EmptyBox';
825
+
826
+ const MEMO = {};
827
+ const CamelCaseWrap = ({ value, dataTest }) => {
828
+ if (!value) {
829
+ return '-';
830
+ }
831
+ if (MEMO[value]) {
832
+ return MEMO[value];
833
+ }
834
+ // Add word break points before capital letters (but keep consecutive capital letters together).
835
+ const words = value.match(/[A-Z]+[^A-Z]*|[^A-Z]+/g);
836
+ const rendered = (React.createElement("span", { "data-test": dataTest }, words.map((word, i) => (React.createElement(React.Fragment, { key: i },
837
+ word,
838
+ i !== words.length - 1 && React.createElement("wbr", null))))));
839
+ MEMO[value] = rendered;
840
+ return rendered;
841
+ };
842
+
843
+ class CatalogTile extends React.Component {
844
+ constructor(props) {
845
+ super(props);
846
+ this.handleClick = (e) => {
847
+ const { onClick, href } = this.props;
848
+ if (!href) {
849
+ e.preventDefault();
850
+ }
851
+ if (onClick) {
852
+ onClick(e);
853
+ }
854
+ };
855
+ this.renderBadges = (badges) => {
856
+ if (!badges || !badges.length) {
857
+ return null;
858
+ }
859
+ return (React.createElement("div", { className: "catalog-tile-pf-badge-container" }, badges.map((badge, index) => (React.createElement("span", { key: `badge-${index}` }, badge)))));
860
+ };
861
+ this.generatedId = getUniqueId('pf-catalog-tile');
862
+ }
863
+ render() {
864
+ const _a = this.props, { id, className, featured, onClick, href, icon, iconImg, iconAlt, iconClass, badges, title, vendor, description, footer,
865
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
866
+ ref, children } = _a, props = __rest(_a, ["id", "className", "featured", "onClick", "href", "icon", "iconImg", "iconAlt", "iconClass", "badges", "title", "vendor", "description", "footer", "ref", "children"]);
867
+ return (React.createElement(Card, Object.assign({ component: href ? 'a' : 'div', id: id || this.generatedId, href: href || '#', className: css('catalog-tile-pf', { featured }, className), isClickable: !!onClick }, props),
868
+ (badges.length > 0 || iconImg || iconClass || icon || onClick) && (React.createElement(CardHeader, { actions: { actions: badges.length > 0 && this.renderBadges(badges) }, selectableActions: onClick && {
869
+ selectableActionId: id + '-input',
870
+ onClickAction: (e) => this.handleClick(e),
871
+ selectableActionAriaLabelledby: id
872
+ } },
873
+ iconImg && React.createElement("img", { className: "catalog-tile-pf-icon", src: iconImg, alt: iconAlt }),
874
+ !iconImg && (iconClass || icon) && React.createElement("span", { className: `catalog-tile-pf-icon ${iconClass}` }, icon))),
875
+ React.createElement(CardTitle, { className: "catalog-tile-pf-header" },
876
+ React.createElement("div", { className: "catalog-tile-pf-title" }, title),
877
+ vendor && React.createElement("div", { className: "catalog-tile-pf-subtitle" }, vendor)),
878
+ (description || children) && (React.createElement(CardBody, { className: "catalog-tile-pf-body" },
879
+ description && (React.createElement("div", { className: "catalog-tile-pf-description" },
880
+ React.createElement("span", { className: css({ 'has-footer': footer }) }, description))),
881
+ children)),
882
+ footer && React.createElement(CardFooter, { className: "catalog-tile-pf-footer" }, footer)));
883
+ }
884
+ }
885
+ CatalogTile.displayName = 'CatalogTile';
886
+ CatalogTile.defaultProps = {
887
+ id: null,
888
+ className: '',
889
+ featured: false,
890
+ onClick: null,
891
+ href: null,
892
+ iconImg: null,
893
+ iconAlt: '',
894
+ iconClass: '',
895
+ icon: null,
896
+ badges: [],
897
+ vendor: null,
898
+ description: null,
899
+ footer: null,
900
+ children: null
901
+ };
902
+
903
+ const Modal = (_a) => {
904
+ var { isFullScreen = false, className } = _a, props = __rest(_a, ["isFullScreen", "className"]);
905
+ return (React.createElement(Modal$1, Object.assign({}, props, { className: css('pfext-modal', className), appendTo: () => (isFullScreen ? document.body : document.querySelector('#modal-container')) })));
906
+ };
907
+
908
+ const getContainer = (container) => typeof container === 'function' ? container() : container;
909
+ const Portal = ({ children, container }) => {
910
+ const [containerNode, setContainerNode] = React.useState();
911
+ useIsomorphicLayoutEffect(() => {
912
+ setContainerNode(getContainer(container) || document.body);
913
+ }, [container]);
914
+ return containerNode ? ReactDOM.createPortal(children, containerNode) : null;
915
+ };
916
+
917
+ const SimplePopper = ({ children }) => {
918
+ const openProp = true;
919
+ const nodeRef = React.useRef();
920
+ const popperRef = React.useRef(null);
921
+ const [isOpen, setOpenState] = React.useState(openProp);
922
+ const setOpen = React.useCallback((newOpen) => {
923
+ setOpenState(newOpen);
924
+ }, []);
925
+ React.useEffect(() => {
926
+ setOpen(openProp);
927
+ }, [openProp, setOpen]);
928
+ const onKeyDown = React.useCallback((e) => {
929
+ if (e.keyCode === 27) {
930
+ setOpen(false);
931
+ }
932
+ }, [setOpen]);
933
+ const onClickOutside = React.useCallback((e) => {
934
+ if (!nodeRef.current || (e.target instanceof Node && !nodeRef.current.contains(e.target))) {
935
+ setOpen(false);
936
+ }
937
+ }, [setOpen]);
938
+ const destroy = React.useCallback(() => {
939
+ if (popperRef.current) {
940
+ popperRef.current.destroy();
941
+ document.removeEventListener('keydown', onKeyDown, true);
942
+ document.removeEventListener('mousedown', onClickOutside, true);
943
+ document.removeEventListener('touchstart', onClickOutside, true);
944
+ }
945
+ }, [onClickOutside, onKeyDown]);
946
+ const initialize = React.useCallback(() => {
947
+ if (!nodeRef.current || !isOpen) {
948
+ return;
949
+ }
950
+ destroy();
951
+ }, [isOpen, destroy]);
952
+ const nodeRefCallback = React.useCallback((node) => {
953
+ nodeRef.current = node;
954
+ initialize();
955
+ }, [initialize]);
956
+ React.useEffect(() => {
957
+ initialize();
958
+ }, [initialize]);
959
+ React.useEffect(() => () => {
960
+ destroy();
961
+ }, [destroy]);
962
+ React.useEffect(() => {
963
+ if (!isOpen) {
964
+ destroy();
965
+ }
966
+ }, [destroy, isOpen]);
967
+ return isOpen ? (React.createElement(Portal, null,
968
+ React.createElement("div", { ref: nodeRefCallback, style: { zIndex: 9999, position: 'absolute', top: 0, left: 0 }, className: "pfext-quick-start__base" }, children))) : null;
969
+ };
970
+
971
+ const isInViewport = (elementToCheck) => {
972
+ const rect = elementToCheck.getBoundingClientRect();
973
+ return (rect.top >= 0 &&
974
+ rect.left >= 0 &&
975
+ rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
976
+ rect.right <= (window.innerWidth || document.documentElement.clientWidth));
977
+ };
978
+ const InteractiveSpotlight = ({ element }) => {
979
+ const { top, bottom, left, right, height, width } = element.getBoundingClientRect();
980
+ const style = {
981
+ height,
982
+ width,
983
+ top,
984
+ left,
985
+ bottom,
986
+ right,
987
+ };
988
+ const [clicked, setClicked] = React.useState(false);
989
+ React.useEffect(() => {
990
+ if (!clicked) {
991
+ if (!isInViewport(element)) {
992
+ element.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
993
+ }
994
+ const handleClick = () => setClicked(true);
995
+ document.addEventListener('click', handleClick);
996
+ return () => {
997
+ document.removeEventListener('click', handleClick);
998
+ };
999
+ }
1000
+ return () => { };
1001
+ }, [element, clicked]);
1002
+ if (clicked) {
1003
+ return null;
1004
+ }
1005
+ return (React.createElement(Portal, null,
1006
+ React.createElement(SimplePopper, null,
1007
+ React.createElement("div", { className: "pfext-spotlight pfext-spotlight__element-highlight-animate", style: style }))));
1008
+ };
1009
+
1010
+ var ScrollDirection;
1011
+ (function (ScrollDirection) {
1012
+ ScrollDirection["scrollingUp"] = "scrolling-up";
1013
+ ScrollDirection["scrollingDown"] = "scrolling-down";
1014
+ ScrollDirection["scrolledToBottom"] = "scrolled-to-bottom";
1015
+ ScrollDirection["scrolledToTop"] = "scrolled-to-top";
1016
+ })(ScrollDirection || (ScrollDirection = {}));
1017
+
1018
+ const useResizeObserver = (callback, targetElement, observerOptions = undefined) => {
1019
+ const element = React.useMemo(() => targetElement !== null && targetElement !== void 0 ? targetElement : document.querySelector('body'), [targetElement]);
1020
+ React.useEffect(() => {
1021
+ const observer = new ResizeObserver(callback);
1022
+ observer.observe(element, observerOptions);
1023
+ return () => {
1024
+ observer.disconnect();
1025
+ };
1026
+ }, [callback, observerOptions, element]);
1027
+ };
1028
+
1029
+ var Shadows;
1030
+ (function (Shadows) {
1031
+ Shadows["none"] = "none";
1032
+ Shadows["both"] = "both";
1033
+ Shadows["top"] = "top";
1034
+ Shadows["bottom"] = "bottom";
1035
+ })(Shadows || (Shadows = {}));
1036
+ const useScrollShadows = (node) => {
1037
+ const [shadows, setShadows] = React.useState(Shadows.none);
1038
+ const computeShadows = React.useCallback(() => {
1039
+ if (node) {
1040
+ const { scrollTop, clientHeight, scrollHeight } = node;
1041
+ const top = scrollTop !== 0;
1042
+ const bottom = scrollTop + clientHeight < scrollHeight;
1043
+ if (top && bottom) {
1044
+ setShadows(Shadows.both);
1045
+ }
1046
+ else if (top) {
1047
+ setShadows(Shadows.top);
1048
+ }
1049
+ else if (bottom) {
1050
+ setShadows(Shadows.bottom);
1051
+ }
1052
+ else {
1053
+ setShadows(Shadows.none);
1054
+ }
1055
+ }
1056
+ }, [node]);
1057
+ // recompute when the scroll container changes in size
1058
+ useResizeObserver(computeShadows, node);
1059
+ React.useEffect(() => {
1060
+ if (node) {
1061
+ // compute initial shadows
1062
+ computeShadows();
1063
+ // listen for scroll events
1064
+ node.addEventListener('scroll', computeShadows);
1065
+ }
1066
+ return () => {
1067
+ if (node) {
1068
+ node.removeEventListener('scroll', computeShadows);
1069
+ }
1070
+ };
1071
+ }, [node, computeShadows]);
1072
+ return shadows;
1073
+ };
1074
+
1075
+ const useBoundingClientRect = (targetElement) => {
1076
+ const [clientRect, setClientRect] = React.useState(() => targetElement ? targetElement.getBoundingClientRect() : null);
1077
+ const observerCallback = React.useCallback(() => {
1078
+ setClientRect(targetElement ? targetElement.getBoundingClientRect() : null);
1079
+ }, [targetElement]);
1080
+ useResizeObserver(observerCallback);
1081
+ return clientRect;
1082
+ };
1083
+
1084
+ /**
1085
+ * React hook that forces component render.
1086
+ */
1087
+ const useForceRender = () => React.useReducer((s) => !s, false)[1];
1088
+
1089
+ const useEventListener = (target, event, callback) => {
1090
+ useEffect(() => {
1091
+ target.addEventListener(event, callback);
1092
+ return () => {
1093
+ target.removeEventListener(event, callback);
1094
+ };
1095
+ }, [target, event, callback]);
1096
+ };
1097
+
1098
+ const StaticSpotlight = ({ element }) => {
1099
+ const clientRect = useBoundingClientRect(element);
1100
+ const style = clientRect
1101
+ ? {
1102
+ top: clientRect.top,
1103
+ left: clientRect.left,
1104
+ height: clientRect.height,
1105
+ width: clientRect.width,
1106
+ }
1107
+ : {};
1108
+ return clientRect ? (React.createElement(Portal, null,
1109
+ React.createElement("div", { className: "pf-v5-c-backdrop pfext-spotlight__with-backdrop" },
1110
+ React.createElement("div", { className: "pfext-spotlight pfext-spotlight__element-highlight-noanimate", style: style })))) : null;
1111
+ };
1112
+
1113
+ const Spotlight = ({ selector, interactive }) => {
1114
+ // if target element is a hidden one return null
1115
+ const element = React.useMemo(() => {
1116
+ const highlightElement = document.querySelector(selector);
1117
+ let hiddenElement = highlightElement;
1118
+ while (hiddenElement) {
1119
+ const ariaHidden = hiddenElement.getAttribute('aria-hidden');
1120
+ if (ariaHidden === 'true') {
1121
+ return null;
1122
+ }
1123
+ hiddenElement = hiddenElement.parentElement;
1124
+ }
1125
+ return highlightElement;
1126
+ }, [selector]);
1127
+ if (!element) {
1128
+ return null;
1129
+ }
1130
+ return interactive ? (React.createElement(InteractiveSpotlight, { element: element })) : (React.createElement(StaticSpotlight, { element: element }));
1131
+ };
1132
+
1133
+ const MarkdownHighlightExtension = ({ docContext, rootSelector, }) => {
1134
+ const [selector, setSelector] = React.useState(null);
1135
+ React.useEffect(() => {
1136
+ const elements = docContext.querySelectorAll(`${rootSelector} [data-highlight]`);
1137
+ let timeoutId;
1138
+ function startHighlight(e) {
1139
+ const highlightId = e.target.getAttribute('data-highlight');
1140
+ if (!highlightId) {
1141
+ return;
1142
+ }
1143
+ setSelector(null);
1144
+ timeoutId = setTimeout(() => {
1145
+ setSelector(`[data-quickstart-id="${highlightId}"]`);
1146
+ }, 0);
1147
+ }
1148
+ elements && elements.forEach((elm) => elm.addEventListener('click', startHighlight));
1149
+ return () => {
1150
+ clearTimeout(timeoutId);
1151
+ elements && elements.forEach((elm) => elm.removeEventListener('click', startHighlight));
1152
+ };
1153
+ }, [docContext, rootSelector]);
1154
+ React.useEffect(() => {
1155
+ const elements = docContext.querySelectorAll(`${rootSelector} [class^=data-highlight__]`);
1156
+ let timeoutId;
1157
+ function startHighlight(e) {
1158
+ e.preventDefault();
1159
+ const classes = e.target.getAttribute('class').split(' ');
1160
+ let highlightId;
1161
+ for (const className of classes) {
1162
+ if (className.startsWith('data-highlight__')) {
1163
+ highlightId = className.split('__')[1];
1164
+ break;
1165
+ }
1166
+ }
1167
+ if (!highlightId) {
1168
+ return;
1169
+ }
1170
+ setSelector(null);
1171
+ timeoutId = setTimeout(() => {
1172
+ setSelector(`[data-quickstart-id="${highlightId}"]`);
1173
+ }, 0);
1174
+ }
1175
+ elements && elements.forEach((elm) => elm.addEventListener('click', startHighlight));
1176
+ return () => {
1177
+ clearTimeout(timeoutId);
1178
+ elements && elements.forEach((elm) => elm.removeEventListener('click', startHighlight));
1179
+ };
1180
+ }, [docContext, rootSelector]);
1181
+ if (!selector) {
1182
+ return null;
1183
+ }
1184
+ return React.createElement(Spotlight, { selector: selector, interactive: true });
1185
+ };
1186
+
1187
+ const MARKDOWN_COPY_BUTTON_ID = 'data-copy-for';
1188
+ const MARKDOWN_SNIPPET_ID = 'data-snippet-id';
1189
+ const ACCORDION_MARKDOWN_BUTTON_ID = `accordion-markdown-button-id`;
1190
+ const ACCORDION_MARKDOWN_CONTENT_ID = `accordion-markdown-content-id`;
1191
+
1192
+ const CopyClipboard = ({ element, rootSelector, docContext, }) => {
1193
+ const { getResource } = React.useContext(QuickStartContext);
1194
+ const [showSuccessContent, setShowSuccessContent] = React.useState(false);
1195
+ const textToCopy = React.useMemo(() => {
1196
+ var _a;
1197
+ const copyTextId = element.getAttribute(MARKDOWN_COPY_BUTTON_ID);
1198
+ return (_a = docContext.querySelector(`${rootSelector} [${MARKDOWN_SNIPPET_ID}="${copyTextId}"]`)) === null || _a === void 0 ? void 0 : _a.innerText;
1199
+ }, [element, docContext, rootSelector]);
1200
+ useEventListener(element, 'click', React.useCallback(() => {
1201
+ navigator.clipboard
1202
+ .writeText(textToCopy.trim())
1203
+ .then(() => {
1204
+ setShowSuccessContent(true);
1205
+ })
1206
+ .catch(() => { });
1207
+ }, [textToCopy]));
1208
+ useEventListener(element, 'mouseleave', React.useCallback(() => {
1209
+ setShowSuccessContent(false);
1210
+ }, []));
1211
+ return showSuccessContent ? (React.createElement(Tooltip, { key: "after-copy", isVisible: true, triggerRef: () => element, content: getResource('Successfully copied to clipboard!'), className: "pfext-quick-start__base" })) : (React.createElement(Tooltip, { key: "before-copy", triggerRef: () => element, content: getResource('Copy to clipboard'), className: "pfext-quick-start__base" }));
1212
+ };
1213
+ const MarkdownCopyClipboard = ({ docContext, rootSelector, }) => {
1214
+ const elements = docContext.querySelectorAll(`${rootSelector} [${MARKDOWN_COPY_BUTTON_ID}]`);
1215
+ return elements.length > 0 ? (React.createElement(React.Fragment, null, Array.from(elements).map((elm) => {
1216
+ const attributeValue = elm.getAttribute(MARKDOWN_COPY_BUTTON_ID);
1217
+ return (React.createElement(CopyClipboard, { key: attributeValue, element: elm, rootSelector: rootSelector, docContext: docContext }));
1218
+ }))) : null;
1219
+ };
1220
+
1221
+ const removeTemplateWhitespace = (template) => template.replace(/>(?:\s|\n)+</g, '><');
1222
+
1223
+ const useInlineCopyClipboardShowdownExtension = () => {
1224
+ const { getResource } = React.useContext(QuickStartContext);
1225
+ return React.useMemo(() => ({
1226
+ type: 'lang',
1227
+ regex: /`([^`](.*?)[^`])`{{copy}}/g,
1228
+ replace: (text, group, _, groupId) => {
1229
+ if (!group || isNaN(groupId)) {
1230
+ return text;
1231
+ }
1232
+ return removeTemplateWhitespace(`<span class="pf-v5-c-clipboard-copy pf-m-inline">
1233
+ <span class="pf-v5-c-clipboard-copy__text" ${MARKDOWN_SNIPPET_ID}="${groupId}">${group}</span>
1234
+ <span class="pf-v5-c-clipboard-copy__actions">
1235
+ <span class="pf-v5-c-clipboard-copy__actions-item">
1236
+ <button class="pf-v5-c-button pf-m-plain" aria-label="${getResource('Copy to clipboard')}" ${MARKDOWN_COPY_BUTTON_ID}="${groupId}">
1237
+ ${renderToStaticMarkup(React.createElement(CopyIcon, null))}
1238
+ </button>
1239
+ </span>
1240
+ </span>
1241
+ </span>`);
1242
+ },
1243
+ }), [getResource]);
1244
+ };
1245
+
1246
+ const useMultilineCopyClipboardShowdownExtension = () => {
1247
+ const { getResource } = React.useContext(QuickStartContext);
1248
+ return React.useMemo(() => ({
1249
+ type: 'lang',
1250
+ regex: /```[\n]\s*((((?!```).)*?\n)+)\s*```{{copy}}/g,
1251
+ replace: (text, group, _1, _2, groupId) => {
1252
+ if (!group || isNaN(groupId)) {
1253
+ return text;
1254
+ }
1255
+ return `<div class="pf-v5-c-code-block">
1256
+ <div class="pf-v5-c-code-block__header">
1257
+ <div class="pf-v5-c-code-block__actions">
1258
+ <div class="pf-v5-c-code-block__actions-item">
1259
+ <button class="pf-v5-c-button pf-m-plain" type="button" aria-label="${getResource('Copy to clipboard')}" ${MARKDOWN_COPY_BUTTON_ID}="${groupId}">
1260
+ ${renderToStaticMarkup(React.createElement(CopyIcon, null))}
1261
+ </button>
1262
+ </div>
1263
+ </div>
1264
+ </div>
1265
+ <div class="pf-v5-c-code-block__content">
1266
+ <pre class="pf-v5-c-code-block__pre pfext-code-block__pre">
1267
+ <code class="pf-v5-c-code-block__code"
1268
+ ${MARKDOWN_SNIPPET_ID}="${groupId}">${group.trim()}</code>
1269
+ </pre>
1270
+ </div>
1271
+ </div>`;
1272
+ },
1273
+ }), [getResource]);
1274
+ };
1275
+
1276
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
1277
+ const DOMPurify = require('dompurify');
1278
+ const markdownConvert = (markdown, extensions) => {
1279
+ const converter = new Converter({
1280
+ tables: true,
1281
+ openLinksInNewWindow: true,
1282
+ strikethrough: true,
1283
+ emoji: false,
1284
+ });
1285
+ if (extensions) {
1286
+ converter.addExtension(extensions);
1287
+ }
1288
+ DOMPurify.addHook('beforeSanitizeElements', function (node) {
1289
+ // nodeType 1 = element type
1290
+ // transform anchor tags
1291
+ if (node.nodeType === 1 && node.nodeName.toLowerCase() === 'a') {
1292
+ node.setAttribute('rel', 'noopener noreferrer');
1293
+ return node;
1294
+ }
1295
+ // add PF class to ul and ol lists
1296
+ if (node.nodeType === 1 &&
1297
+ (node.nodeName.toLowerCase() === 'ul' || node.nodeName.toLowerCase() === 'ol')) {
1298
+ node.setAttribute('class', 'pf-v5-c-list');
1299
+ return node;
1300
+ }
1301
+ });
1302
+ // Add a hook to make all links open a new window
1303
+ DOMPurify.addHook('afterSanitizeAttributes', function (node) {
1304
+ // set all elements owning target to target=_blank
1305
+ if ('target' in node) {
1306
+ node.setAttribute('target', '_blank');
1307
+ }
1308
+ // set non-HTML/MathML links to xlink:show=new
1309
+ if (!node.hasAttribute('target') &&
1310
+ (node.hasAttribute('xlink:href') || node.hasAttribute('href'))) {
1311
+ node.setAttribute('xlink:show', 'new');
1312
+ }
1313
+ });
1314
+ return DOMPurify.sanitize(converter.makeHtml(markdown), {
1315
+ USE_PROFILES: {
1316
+ html: true,
1317
+ svg: true,
1318
+ },
1319
+ });
1320
+ };
1321
+ const SyncMarkdownView = ({ content, emptyMsg, extensions, renderExtension, exactHeight, inline, className, }) => {
1322
+ const { getResource } = React.useContext(QuickStartContext);
1323
+ const markup = React.useMemo(() => markdownConvert(content || emptyMsg || getResource('Not available'), extensions), [content, emptyMsg, extensions, getResource]);
1324
+ const innerProps = {
1325
+ renderExtension: (extensions === null || extensions === void 0 ? void 0 : extensions.length) > 0 ? renderExtension : undefined,
1326
+ exactHeight,
1327
+ markup,
1328
+ isEmpty: !content,
1329
+ className,
1330
+ };
1331
+ return inline ? React.createElement(InlineMarkdownView, Object.assign({}, innerProps)) : React.createElement(IFrameMarkdownView, Object.assign({}, innerProps));
1332
+ };
1333
+ const uniqueId = (function () {
1334
+ let num = 0;
1335
+ return function (prefix) {
1336
+ const prefixStr = String(prefix) || '';
1337
+ num += 1;
1338
+ return prefixStr + num;
1339
+ };
1340
+ })();
1341
+ const RenderExtension = ({ renderExtension, selector, markup, docContext, }) => {
1342
+ const forceRender = useForceRender();
1343
+ const markupRef = React.useRef(null);
1344
+ const shouldRenderExtension = React.useCallback(() => {
1345
+ if (markupRef.current === markup) {
1346
+ return true;
1347
+ }
1348
+ markupRef.current = markup;
1349
+ return false;
1350
+ }, [markup]);
1351
+ /**
1352
+ * During a render cycle in which markup changes, renderExtension receives an old copy of document
1353
+ * because react is still updating the dom using `dangerouslySetInnerHTML` with latest markdown markup
1354
+ * which causes the component rendered by renderExtension to receive old copy of document
1355
+ * use forceRender to delay the rendering of extension by one render cycle
1356
+ */
1357
+ React.useEffect(() => {
1358
+ if (renderExtension) {
1359
+ forceRender();
1360
+ }
1361
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1362
+ }, [markup]);
1363
+ return (React.createElement(React.Fragment, null, shouldRenderExtension() ? renderExtension === null || renderExtension === void 0 ? void 0 : renderExtension(docContext !== null && docContext !== void 0 ? docContext : document, selector) : null));
1364
+ };
1365
+ const InlineMarkdownView = ({ markup, isEmpty, renderExtension, className, }) => {
1366
+ const id = React.useMemo(() => uniqueId('markdown'), []);
1367
+ return (React.createElement("div", { className: css('pfext-markdown-view', { 'is-empty': isEmpty }, className), id: id },
1368
+ React.createElement("div", { dangerouslySetInnerHTML: { __html: markup } }),
1369
+ renderExtension && (React.createElement(RenderExtension, { renderExtension: renderExtension, selector: `#${id}`, markup: markup }))));
1370
+ };
1371
+ const IFrameMarkdownView = ({ exactHeight, markup, isEmpty, renderExtension, className, }) => {
1372
+ const [frame, setFrame] = React.useState();
1373
+ const [loaded, setLoaded] = React.useState(false);
1374
+ const updateTimeoutHandle = React.useRef();
1375
+ const updateDimensions = React.useCallback(() => {
1376
+ var _a;
1377
+ if (!((_a = frame === null || frame === void 0 ? void 0 : frame.contentWindow) === null || _a === void 0 ? void 0 : _a.document.body.firstChild)) {
1378
+ return;
1379
+ }
1380
+ frame.style.height = `${frame.contentWindow.document.body.firstElementChild.scrollHeight}px`;
1381
+ // Let the new height take effect, then reset again once we recompute
1382
+ updateTimeoutHandle.current = setTimeout(() => {
1383
+ if (exactHeight) {
1384
+ frame.style.height = `${frame.contentWindow.document.body.firstElementChild.scrollHeight}px`;
1385
+ }
1386
+ else {
1387
+ // Increase by 15px for the case where a horizontal scrollbar might appear
1388
+ frame.style.height = `${frame.contentWindow.document.body.firstElementChild.scrollHeight + 15}px`;
1389
+ }
1390
+ });
1391
+ }, [frame, exactHeight]);
1392
+ React.useEffect(() => () => {
1393
+ clearTimeout(updateTimeoutHandle.current);
1394
+ }, []);
1395
+ const onLoad = React.useCallback(() => {
1396
+ updateDimensions();
1397
+ setLoaded(true);
1398
+ }, [updateDimensions]);
1399
+ // Find the app's stylesheets and inject them into the frame to ensure consistent styling.
1400
+ const filteredLinks = Array.from(document.getElementsByTagName('link')).filter((l) => l.href.includes('app-bundle'));
1401
+ const linkRefs = filteredLinks.reduce((refs, link) => `${refs}
1402
+ <link rel="stylesheet" href="${link.href}">`, '');
1403
+ const contents = `
1404
+ ${linkRefs}
1405
+ <style type="text/css">
1406
+ body {
1407
+ background-color: transparent !important;
1408
+ color: ${isEmpty ? '#999' : '#333'};
1409
+ font-family: var(--pf-v5-global--FontFamily--sans-serif);
1410
+ min-width: auto !important;
1411
+ }
1412
+ table {
1413
+ display: block;
1414
+ margin-bottom: 11.5px;
1415
+ overflow-x: auto;
1416
+ }
1417
+ td,
1418
+ th {
1419
+ border-bottom: 1px solid #ededed;
1420
+ padding: 10px;
1421
+ vertical-align: top;
1422
+ }
1423
+ th {
1424
+ padding-top: 0;
1425
+ }
1426
+ </style>
1427
+ <body class="pf-m-redhat-font"><div style="overflow-y: auto;">${markup}</div></body>`;
1428
+ return (React.createElement(React.Fragment, null,
1429
+ React.createElement("iframe", { sandbox: "allow-popups allow-popups-to-escape-sandbox allow-same-origin", srcDoc: contents, style: { border: '0px', display: 'block', width: '100%', height: '0' }, ref: (r) => setFrame(r), onLoad: () => onLoad(), className: className }),
1430
+ loaded && frame && renderExtension && (React.createElement(RenderExtension, { markup: markup, selector: '', renderExtension: renderExtension, docContext: frame.contentDocument }))));
1431
+ };
1432
+
1433
+ const LINK_LABEL = '[\\d\\w\\s-()$!]+';
1434
+ const HIGHLIGHT_ACTIONS = ['highlight'];
1435
+ const SELECTOR_ID = `[\\w-]+`;
1436
+ // [linkLabel]{{action id}}
1437
+ const HIGHLIGHT_REGEXP = new RegExp(`\\[(${LINK_LABEL})]{{(${HIGHLIGHT_ACTIONS.join('|')}) (${SELECTOR_ID})}}`, 'g');
1438
+
1439
+ const removeParagraphWrap = (markdown) => markdown.replace(/^<p>|<\/p>$/g, '');
1440
+ const QuickStartMarkdownView = ({ content, exactHeight, className, }) => {
1441
+ const { markdown } = React.useContext(QuickStartContext);
1442
+ const inlineCopyClipboardShowdownExtension = useInlineCopyClipboardShowdownExtension();
1443
+ const multilineCopyClipboardShowdownExtension = useMultilineCopyClipboardShowdownExtension();
1444
+ const admonitionShowdownExtension = useAdmonitionShowdownExtension();
1445
+ const codeShowdownExtension = useCodeShowdownExtension();
1446
+ const accordionShowdownExtension = useAccordionShowdownExtension();
1447
+ return (React.createElement(SyncMarkdownView, { inline: true, content: content, exactHeight: exactHeight, extensions: [
1448
+ {
1449
+ type: 'lang',
1450
+ regex: HIGHLIGHT_REGEXP,
1451
+ replace: (text, linkLabel, linkType, linkId) => {
1452
+ if (!linkLabel || !linkType || !linkId) {
1453
+ return text;
1454
+ }
1455
+ return `<button class="pf-v5-c-button pf-m-inline pf-m-link" data-highlight="${linkId}">${linkLabel}</button>`;
1456
+ },
1457
+ },
1458
+ {
1459
+ type: 'output',
1460
+ filter(text) {
1461
+ // check HTML for patterns like: <em>Status: unknown</em>{#extension-requirement-status}
1462
+ // and replace with <em id="extension-requirement-status">Status: unknown</em>
1463
+ return text.replace(/<em>(.*)<\/em>{#(.*)}/g, '<em id="$2">$1</em>');
1464
+ },
1465
+ },
1466
+ inlineCopyClipboardShowdownExtension,
1467
+ multilineCopyClipboardShowdownExtension,
1468
+ admonitionShowdownExtension,
1469
+ codeShowdownExtension,
1470
+ accordionShowdownExtension,
1471
+ ...(markdown ? markdown.extensions : []),
1472
+ ], renderExtension: (docContext, rootSelector) => (React.createElement(React.Fragment, null,
1473
+ React.createElement(AccordionRenderExtension, { docContext: docContext }),
1474
+ React.createElement(MarkdownHighlightExtension, { docContext: docContext, rootSelector: rootSelector }),
1475
+ React.createElement(MarkdownCopyClipboard, { docContext: docContext, rootSelector: rootSelector }),
1476
+ markdown &&
1477
+ markdown.renderExtension &&
1478
+ markdown.renderExtension(docContext, rootSelector))), className: className }));
1479
+ };
1480
+
1481
+ var AdmonitionType;
1482
+ (function (AdmonitionType) {
1483
+ AdmonitionType["TIP"] = "TIP";
1484
+ AdmonitionType["NOTE"] = "NOTE";
1485
+ AdmonitionType["IMPORTANT"] = "IMPORTANT";
1486
+ AdmonitionType["WARNING"] = "WARNING";
1487
+ AdmonitionType["CAUTION"] = "CAUTION";
1488
+ })(AdmonitionType || (AdmonitionType = {}));
1489
+ const admonitionToAlertVariantMap = {
1490
+ [AdmonitionType.NOTE]: { variant: 'info' },
1491
+ [AdmonitionType.TIP]: { variant: 'default', customIcon: React.createElement(LightbulbIcon, null) },
1492
+ [AdmonitionType.IMPORTANT]: { variant: 'danger' },
1493
+ [AdmonitionType.CAUTION]: { variant: 'warning', customIcon: React.createElement(FireIcon, null) },
1494
+ [AdmonitionType.WARNING]: { variant: 'warning' },
1495
+ };
1496
+ const useAdmonitionShowdownExtension = () =>
1497
+ // const { getResource } = React.useContext<QuickStartContextValues>(QuickStartContext);
1498
+ React.useMemo(() => ({
1499
+ type: 'lang',
1500
+ regex: /\[(.+)]{{(admonition) ([\w-]+)}}/g,
1501
+ replace: (text, content, admonitionLabel, admonitionType, groupId) => {
1502
+ if (!content || !admonitionLabel || !admonitionType || !groupId) {
1503
+ return text;
1504
+ }
1505
+ admonitionType = admonitionType.toUpperCase();
1506
+ const { variant, customIcon } = admonitionToAlertVariantMap[admonitionType];
1507
+ const style = admonitionType === AdmonitionType.CAUTION ? { backgroundColor: '#ec7a0915' } : {};
1508
+ const mdContent = React.createElement(QuickStartMarkdownView, { content: content });
1509
+ const pfAlert = (React.createElement(Alert, { variant: variant, customIcon: customIcon && customIcon, isInline: true, title: admonitionType, className: "pfext-markdown-admonition", style: style }, mdContent));
1510
+ return removeTemplateWhitespace(renderToStaticMarkup(pfAlert));
1511
+ },
1512
+ }), []);
1513
+
1514
+ const useCodeShowdownExtension = () => React.useMemo(() => ({
1515
+ type: 'output',
1516
+ regex: /<pre><code>(.*?)\n?<\/code><\/pre>/g,
1517
+ replace: (text, content) => {
1518
+ if (!content) {
1519
+ return text;
1520
+ }
1521
+ const pfCodeBlock = React.createElement(CodeBlock, null, content);
1522
+ return removeTemplateWhitespace(renderToStaticMarkup(pfCodeBlock));
1523
+ },
1524
+ }), []);
1525
+
1526
+ const useAccordionShowdownExtension = () => React.useMemo(() => ({
1527
+ type: 'lang',
1528
+ regex: /\[(.+)]{{(accordion) ("(.*?)")}}/g,
1529
+ replace: (_text, accordionContent, _command, accordionHeading) => {
1530
+ const accordionId = String(accordionHeading).replace(/\s/g, '-');
1531
+ return removeTemplateWhitespace(renderToStaticMarkup(React.createElement(Accordion, { asDefinitionList: true },
1532
+ React.createElement(AccordionItem, null,
1533
+ React.createElement(AccordionToggle, { isExpanded: false, id: `${ACCORDION_MARKDOWN_BUTTON_ID}-${accordionId}` }, accordionHeading),
1534
+ React.createElement(AccordionContent, { id: `${ACCORDION_MARKDOWN_CONTENT_ID}-${accordionId}`, isHidden: !false }, accordionContent)))));
1535
+ },
1536
+ }), []);
1537
+
1538
+ const AccordionShowdownHandler = ({ buttonElement, contentElement, }) => {
1539
+ const [expanded, setExpanded] = React.useState(false);
1540
+ const handleClick = () => {
1541
+ const expandedModifier = 'pf-m-expanded';
1542
+ buttonElement.className = `pf-v5-c-accordion__toggle ${!expanded ? expandedModifier : ''}`;
1543
+ contentElement.hidden = expanded;
1544
+ contentElement.className = `pf-v5-c-accordion__expanded-content ${!expanded ? expandedModifier : ''}`;
1545
+ setExpanded(!expanded);
1546
+ };
1547
+ useEventListener(buttonElement, 'click', handleClick);
1548
+ return React.createElement(React.Fragment, null);
1549
+ };
1550
+ const AccordionRenderExtension = ({ docContext }) => {
1551
+ const buttonElements = docContext.querySelectorAll(`[id ^= ${ACCORDION_MARKDOWN_BUTTON_ID}]`);
1552
+ const contentElements = docContext.querySelectorAll(`[id ^= ${ACCORDION_MARKDOWN_CONTENT_ID}]`);
1553
+ return buttonElements.length > 0 ? (React.createElement(React.Fragment, null, Array.from(buttonElements).map((elm) => {
1554
+ const content = Array.from(contentElements).find((elm2) => {
1555
+ const elmId = elm.id.split(ACCORDION_MARKDOWN_BUTTON_ID)[1];
1556
+ const elm2Id = elm2.id.split(ACCORDION_MARKDOWN_CONTENT_ID)[1];
1557
+ return elmId === elm2Id;
1558
+ });
1559
+ return (React.createElement(AccordionShowdownHandler, { key: elm.id.split(ACCORDION_MARKDOWN_BUTTON_ID)[1], buttonElement: elm, contentElement: content }));
1560
+ }))) : null;
1561
+ };
1562
+
1563
+ const FallbackImg = ({ src, alt, className, fallback }) => {
1564
+ const [isSrcValid, setIsSrcValid] = React.useState(true);
1565
+ if (src && isSrcValid) {
1566
+ return React.createElement("img", { className: className, src: src, alt: alt, onError: () => setIsSrcValid(false) });
1567
+ }
1568
+ return React.createElement(React.Fragment, null, fallback);
1569
+ };
1570
+
1571
+ const DASH = '-';
1572
+
1573
+ const PopoverStatus = ({ hideHeader, children, isVisible = null, statusBody, title, onHide, onShow, }) => (React.createElement(Popover, { position: PopoverPosition.right, headerContent: hideHeader ? null : title, bodyContent: children, "aria-label": title, onHide: onHide, onShow: onShow, isVisible: isVisible },
1574
+ React.createElement(Button, { variant: "link", isInline: true }, statusBody)));
1575
+
1576
+ const StatusIconAndText = ({ icon, title, spin, iconOnly, noTooltip, className, }) => {
1577
+ if (!title) {
1578
+ return React.createElement(React.Fragment, null, DASH);
1579
+ }
1580
+ return (React.createElement("span", { className: css('pfext-icon-and-text', className), title: iconOnly && !noTooltip ? title : undefined },
1581
+ icon &&
1582
+ React.cloneElement(icon, {
1583
+ className: css(spin && 'fa-spin', icon.props.className, !iconOnly && 'pfext-icon-and-text__icon pfext-icon-flex-child'),
1584
+ }),
1585
+ !iconOnly && React.createElement(CamelCaseWrap, { value: title, dataTest: "status-text" })));
1586
+ };
1587
+
1588
+ const GenericStatus = (props) => {
1589
+ const { Icon, children, popoverTitle, title, noTooltip, iconOnly } = props, restProps = __rest(props, ["Icon", "children", "popoverTitle", "title", "noTooltip", "iconOnly"]);
1590
+ const renderIcon = iconOnly && !noTooltip ? React.createElement(Icon, { title: title }) : React.createElement(Icon, null);
1591
+ const statusBody = (React.createElement(StatusIconAndText, Object.assign({}, restProps, { noTooltip: noTooltip, title: title, iconOnly: iconOnly, icon: renderIcon })));
1592
+ return React.Children.toArray(children).length ? (React.createElement(PopoverStatus, Object.assign({ title: popoverTitle || title }, restProps, { statusBody: statusBody }), children)) : (statusBody);
1593
+ };
1594
+
1595
+ const GreenCheckCircleIcon = ({ className, title, size }) => (React.createElement(Icon, { size: size },
1596
+ React.createElement(CheckCircleIcon, { "data-test": "success-icon", color: okColor.value, className: className, title: title })));
1597
+
1598
+ const SuccessStatus = (props) => (React.createElement(GenericStatus, Object.assign({}, props, { Icon: GreenCheckCircleIcon, title: props.title || 'Healthy' })));
1599
+ SuccessStatus.displayName = 'SuccessStatus';
1600
+
1601
+ const Status = ({ status, title, iconOnly, noTooltip, className, }) => {
1602
+ const statusProps = { title: title || status, iconOnly, noTooltip, className };
1603
+ switch (status) {
1604
+ case 'In Progress':
1605
+ return React.createElement(StatusIconAndText, Object.assign({}, statusProps, { icon: React.createElement(SyncAltIcon, null) }));
1606
+ case 'Complete':
1607
+ return React.createElement(SuccessStatus, Object.assign({}, statusProps));
1608
+ default:
1609
+ return React.createElement(React.Fragment, null, status || DASH);
1610
+ }
1611
+ };
1612
+ const StatusIcon = ({ status }) => (React.createElement(Status, { status: status, iconOnly: true }));
1613
+
1614
+ const QuickStartTileDescription = ({ description, prerequisites, }) => {
1615
+ const { getResource } = React.useContext(QuickStartContext);
1616
+ const prereqs = prerequisites === null || prerequisites === void 0 ? void 0 : prerequisites.filter((p) => p);
1617
+ return (React.createElement(React.Fragment, null,
1618
+ React.createElement(QuickStartMarkdownView, { content: description, className: "pfext-quick-start-tile-description" }),
1619
+ (prereqs === null || prereqs === void 0 ? void 0 : prereqs.length) > 0 && (React.createElement("div", { className: "pfext-quick-start-tile-prerequisites" },
1620
+ React.createElement(Text, { component: TextVariants.h5, className: "pfext-quick-start-tile-prerequisites__text" },
1621
+ getResource('Prerequisites ({{totalPrereqs}})').replace('{{totalPrereqs}}', prereqs.length),
1622
+ ' '),
1623
+ React.createElement(Popover, { "aria-label": getResource('Prerequisites'), headerContent: getResource('Prerequisites'), className: "pfext-quick-start__base", bodyContent: React.createElement("div", { className: "pfext-popover__base" },
1624
+ React.createElement(TextList, { "aria-label": getResource('Prerequisites'), className: "pfext-quick-start-tile-prerequisites-list" }, prereqs.map((prerequisite, index) => (
1625
+ // eslint-disable-next-line react/no-array-index-key
1626
+ React.createElement(TextListItem, { key: index },
1627
+ React.createElement(QuickStartMarkdownView, { content: prerequisite })))))) },
1628
+ React.createElement(Button, { variant: "link", isInline: true, className: "pfext-quick-start-tile-prerequisites__icon", "data-testid": "qs-card-prereqs", onClick: (e) => {
1629
+ e.preventDefault();
1630
+ e.stopPropagation();
1631
+ }, "aria-label": getResource('Show prerequisites') },
1632
+ React.createElement(InfoCircleIcon, null)))))));
1633
+ };
1634
+
1635
+ const QuickStartTileFooter = ({ quickStartId, status, totalTasks, }) => {
1636
+ const { getResource } = React.useContext(QuickStartContext);
1637
+ const { activeQuickStartID, startQuickStart, restartQuickStart } = React.useContext(QuickStartContext);
1638
+ const start = React.useCallback((e) => {
1639
+ e.preventDefault();
1640
+ e.stopPropagation();
1641
+ startQuickStart(quickStartId, totalTasks);
1642
+ }, [quickStartId, startQuickStart, totalTasks]);
1643
+ const restart = React.useCallback((e) => {
1644
+ e.preventDefault();
1645
+ e.stopPropagation();
1646
+ restartQuickStart(quickStartId, totalTasks);
1647
+ }, [quickStartId, restartQuickStart, totalTasks]);
1648
+ return (React.createElement(Flex, { justifyContent: { default: 'justifyContentSpaceBetween' } },
1649
+ status === QuickStartStatus.NOT_STARTED && (React.createElement(FlexItem, null,
1650
+ 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')))),
1651
+ status === QuickStartStatus.IN_PROGRESS && activeQuickStartID !== quickStartId && (React.createElement(FlexItem, null,
1652
+ React.createElement(Button, { variant: "link", isInline: true, "data-testid": "qs-card-inProgress-resume", id: `${quickStartId}-continue`, "aria-labelledby": `${quickStartId}-continue ${quickStartId}` }, getResource('Continue')))),
1653
+ status === QuickStartStatus.COMPLETE && (React.createElement(FlexItem, null,
1654
+ 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')))),
1655
+ status === QuickStartStatus.IN_PROGRESS && (React.createElement(FlexItem, null,
1656
+ 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'))))));
1657
+ };
1658
+
1659
+ const QuickStartTileFooterExternal = ({ link, quickStartId, }) => {
1660
+ const { href, text } = link;
1661
+ return (React.createElement(Flex, { justifyContent: { default: 'justifyContentSpaceBetween' } },
1662
+ React.createElement(FlexItem, null,
1663
+ 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))));
1664
+ };
1665
+
1666
+ const statusColorMap = {
1667
+ [QuickStartStatus.COMPLETE]: 'green',
1668
+ [QuickStartStatus.IN_PROGRESS]: 'purple',
1669
+ [QuickStartStatus.NOT_STARTED]: 'grey',
1670
+ };
1671
+ const QuickStartTileHeader = ({ status, duration, name, type, quickStartId, action, }) => {
1672
+ const { getResource } = React.useContext(QuickStartContext);
1673
+ const statusLocaleMap = {
1674
+ [QuickStartStatus.COMPLETE]: getResource('Complete'),
1675
+ [QuickStartStatus.IN_PROGRESS]: getResource('In progress'),
1676
+ [QuickStartStatus.NOT_STARTED]: getResource('Not started'),
1677
+ };
1678
+ const ActionIcon = (action === null || action === void 0 ? void 0 : action.icon) || OutlinedBookmarkIcon;
1679
+ return (React.createElement("div", { className: "pfext-quick-start-tile-header" },
1680
+ React.createElement(Flex, { flexWrap: { default: 'nowrap' } },
1681
+ React.createElement(Title, { headingLevel: "h3", "data-test": "title", id: quickStartId },
1682
+ React.createElement(QuickStartMarkdownView, { content: name })),
1683
+ action && (React.createElement(Button, Object.assign({ "aria-label": action['aria-label'], icon: React.createElement(ActionIcon, null), variant: "plain", onClick: action.onClick }, action.buttonProps)))),
1684
+ React.createElement("div", { className: "pfext-quick-start-tile-header__status" },
1685
+ type && (React.createElement(Label, { className: "pfext-quick-start-tile-header--margin", color: type.color }, type.text)),
1686
+ 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))),
1687
+ status !== QuickStartStatus.NOT_STARTED && (React.createElement(Label, { variant: "outline", color: statusColorMap[status], icon: React.createElement(StatusIcon, { status: status }), "data-test": "status" }, statusLocaleMap[status])))));
1688
+ };
1689
+
1690
+ const QuickStartTile = ({ quickStart, status, isActive, onClick = () => { }, action, }) => {
1691
+ const { metadata: { name: id }, spec: { icon, tasks, displayName, description, durationMinutes, prerequisites, link, type }, } = quickStart;
1692
+ const { setActiveQuickStart, footer } = React.useContext(QuickStartContext);
1693
+ const ref = React.useRef(null);
1694
+ let quickStartIcon;
1695
+ if (typeof icon === 'object') {
1696
+ quickStartIcon = icon;
1697
+ }
1698
+ else {
1699
+ quickStartIcon = (React.createElement(FallbackImg, { className: "pfext-catalog-item-icon__img--large", src: icon, alt: "", fallback: React.createElement(RocketIcon, null) }));
1700
+ }
1701
+ const footerComponent = React.useMemo(() => {
1702
+ if (footer && footer.show === false) {
1703
+ return null;
1704
+ }
1705
+ if (link) {
1706
+ return React.createElement(QuickStartTileFooterExternal, { link: link, quickStartId: id });
1707
+ }
1708
+ return React.createElement(QuickStartTileFooter, { quickStartId: id, status: status, totalTasks: tasks === null || tasks === void 0 ? void 0 : tasks.length });
1709
+ }, [footer, id, link, status, tasks === null || tasks === void 0 ? void 0 : tasks.length]);
1710
+ const handleClick = (e) => {
1711
+ var _a;
1712
+ if ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.contains(e.target)) {
1713
+ if (!link) {
1714
+ setActiveQuickStart(id, tasks === null || tasks === void 0 ? void 0 : tasks.length);
1715
+ }
1716
+ onClick();
1717
+ }
1718
+ };
1719
+ const linkProps = link
1720
+ ? {
1721
+ href: link.href,
1722
+ target: '_blank',
1723
+ rel: 'noreferrer',
1724
+ }
1725
+ : {};
1726
+ return (React.createElement("div", { ref: ref, onClick: handleClick },
1727
+ React.createElement(CatalogTile, Object.assign({ id: id + '-catalog-tile', style: {
1728
+ cursor: 'pointer',
1729
+ }, 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, action: action }), onKeyDown: (event) => {
1730
+ if (event.key === 'Enter' || event.key === ' ') {
1731
+ setActiveQuickStart(id, tasks === null || tasks === void 0 ? void 0 : tasks.length);
1732
+ onClick();
1733
+ }
1734
+ } }, linkProps, { "data-test": `tile ${id}`, description: React.createElement(QuickStartTileDescription, { description: description, prerequisites: prerequisites }), footer: footerComponent, tabIndex: 0,
1735
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1736
+ // @ts-ignore-next-line
1737
+ isSelectableRaised: true }))));
1738
+ };
1739
+
1740
+ const QuickStartCatalog = ({ quickStarts }) => {
1741
+ const { activeQuickStartID, allQuickStartStates } = React.useContext(QuickStartContext);
1742
+ return (React.createElement("div", { className: "pfext-page-layout__content" },
1743
+ React.createElement(Gallery, { className: "pfext-quick-start-catalog__gallery", hasGutter: true }, quickStarts.map((quickStart) => {
1744
+ const { metadata: { name: id }, } = quickStart;
1745
+ return (React.createElement(GalleryItem, { key: id, className: "pfext-quick-start-catalog__gallery-item" },
1746
+ React.createElement(QuickStartTile, { quickStart: quickStart, isActive: id === activeQuickStartID, status: getQuickStartStatus(allQuickStartStates, id) })));
1747
+ }))));
1748
+ };
1749
+
1750
+ const QuickStartCatalogFilterSearch = (_a) => {
1751
+ var { searchInputText, handleTextChange } = _a, props = __rest(_a, ["searchInputText", "handleTextChange"]);
1752
+ const { getResource } = React.useContext(QuickStartContext);
1753
+ return (React.createElement(ToolbarItem, { className: "pfext-quick-start-catalog-filter__input" },
1754
+ React.createElement(SearchInput, Object.assign({ placeholder: getResource('Filter by keyword...'), value: searchInputText, onChange: (_ev, value) => handleTextChange(value), onClear: () => handleTextChange('') }, props))));
1755
+ };
1756
+ const QuickStartCatalogFilterSelect = (_a) => {
1757
+ var { isDropdownOpen, setIsDropdownOpen, onRowfilterSelect, selectedFilters, dropdownItems } = _a, props = __rest(_a, ["isDropdownOpen", "setIsDropdownOpen", "onRowfilterSelect", "selectedFilters", "dropdownItems"]);
1758
+ const { getResource } = React.useContext(QuickStartContext);
1759
+ const toggle = (toggleRef) => (React.createElement(MenuToggle, { isFullWidth: true, ref: toggleRef, onClick: () => setIsDropdownOpen(!isDropdownOpen), isExpanded: isDropdownOpen },
1760
+ getResource('Status'),
1761
+ selectedFilters.length > 0 && React.createElement(Badge, { isRead: true }, selectedFilters.length)));
1762
+ return (React.createElement(ToolbarItem, null,
1763
+ React.createElement(Select, Object.assign({ "aria-label": getResource('Select filter'), isOpen: isDropdownOpen, selected: selectedFilters, onSelect: onRowfilterSelect, onOpenChange: (isOpen) => setIsDropdownOpen(isOpen), toggle: toggle }, props),
1764
+ React.createElement(SelectList, null, dropdownItems))));
1765
+ };
1766
+ const QuickStartCatalogFilterCount = ({ quickStartsCount }) => {
1767
+ const { getResource } = React.useContext(QuickStartContext);
1768
+ return (React.createElement(ToolbarItem, { className: "pfext-quick-start-catalog-filter__count", align: { default: 'alignRight' } }, getResource('{{count, number}} item', quickStartsCount).replace('{{count, number}}', quickStartsCount)));
1769
+ };
1770
+ const QuickStartCatalogFilterSearchWrapper = ({ onSearchInputChange = () => { } }) => {
1771
+ const { useQueryParams, filter, setFilter } = React.useContext(QuickStartContext);
1772
+ React.useEffect(() => {
1773
+ // use this effect to clear the search when a `clear all` action is performed higher up
1774
+ const unlisten = history.listen(({ location }) => {
1775
+ const searchParams = new URLSearchParams(location.search);
1776
+ const searchQuery = searchParams.get(QUICKSTART_SEARCH_FILTER_KEY) || '';
1777
+ if (searchQuery === '') {
1778
+ setFilter('keyword', '');
1779
+ onSearchInputChange('');
1780
+ }
1781
+ });
1782
+ return () => {
1783
+ unlisten();
1784
+ };
1785
+ }, [onSearchInputChange, setFilter]);
1786
+ const handleTextChange = (val) => {
1787
+ if (val.length > 0) {
1788
+ useQueryParams && setQueryArgument(QUICKSTART_SEARCH_FILTER_KEY, val);
1789
+ }
1790
+ else {
1791
+ useQueryParams && removeQueryArgument(QUICKSTART_SEARCH_FILTER_KEY);
1792
+ }
1793
+ if ((filter === null || filter === void 0 ? void 0 : filter.keyword) !== val) {
1794
+ setFilter('keyword', val);
1795
+ }
1796
+ onSearchInputChange(val);
1797
+ };
1798
+ return (React.createElement(QuickStartCatalogFilterSearch, { searchInputText: filter === null || filter === void 0 ? void 0 : filter.keyword, handleTextChange: handleTextChange }));
1799
+ };
1800
+ // compare string/number arrays
1801
+ const equalsIgnoreOrder = (a, b) => {
1802
+ if (a.length !== b.length) {
1803
+ return false;
1804
+ }
1805
+ const uniqueValues = new Set([...a, ...b]);
1806
+ for (const v of uniqueValues) {
1807
+ const aCount = a.filter((e) => e === v).length;
1808
+ const bCount = b.filter((e) => e === v).length;
1809
+ if (aCount !== bCount) {
1810
+ return false;
1811
+ }
1812
+ }
1813
+ return true;
1814
+ };
1815
+ const QuickStartCatalogFilterStatusWrapper = ({ onStatusChange = () => { } }) => {
1816
+ const { useQueryParams, filter, setFilter } = React.useContext(QuickStartContext);
1817
+ React.useEffect(() => {
1818
+ // use this effect to clear the status when a `clear all` action is performed higher up
1819
+ const unlisten = history.listen(({ location }) => {
1820
+ var _a;
1821
+ const searchParams = new URLSearchParams(location.search);
1822
+ const updatedStatusFilters = ((_a = searchParams.get(QUICKSTART_STATUS_FILTER_KEY)) === null || _a === void 0 ? void 0 : _a.split(',')) || [];
1823
+ if (updatedStatusFilters.length === 0) {
1824
+ setFilter('status', []);
1825
+ onStatusChange([]);
1826
+ }
1827
+ });
1828
+ return () => {
1829
+ unlisten();
1830
+ };
1831
+ });
1832
+ const [isDropdownOpen, setIsDropdownOpen] = React.useState(false);
1833
+ const onRowfilterSelect = React.useCallback((_e, selectedValue) => {
1834
+ setIsDropdownOpen(false);
1835
+ const selection = Object.entries(filter.status.statusTypes).find(([_key, value]) => value === selectedValue)[0];
1836
+ const selectedFiltersList = filter.status.statusFilters.includes(selection)
1837
+ ? filter.status.statusFilters.filter((status) => status !== selection)
1838
+ : [...filter.status.statusFilters, selection];
1839
+ if (!equalsIgnoreOrder(filter.status.statusFilters, selectedFiltersList)) {
1840
+ setFilter('status', selectedFiltersList);
1841
+ }
1842
+ if (selectedFiltersList.length > 0) {
1843
+ useQueryParams && setQueryArgument('status', selectedFiltersList.join(','));
1844
+ }
1845
+ else {
1846
+ useQueryParams && removeQueryArgument(QUICKSTART_STATUS_FILTER_KEY);
1847
+ }
1848
+ onStatusChange(selectedFiltersList);
1849
+ }, [filter.status.statusFilters, onStatusChange, setFilter, useQueryParams]);
1850
+ const dropdownItems = Object.entries(filter.status.statusTypes).map(([key, value]) => (React.createElement(SelectOption, { key: key, "data-key": key, value: value, hasCheckbox: true, isSelected: filter.status.statusFilters.includes(key) },
1851
+ React.createElement(React.Fragment, null, value))));
1852
+ return (React.createElement(QuickStartCatalogFilterSelect, { isDropdownOpen: isDropdownOpen, setIsDropdownOpen: setIsDropdownOpen, onRowfilterSelect: onRowfilterSelect, selectedFilters: filter.status.statusFilters, dropdownItems: dropdownItems }));
1853
+ };
1854
+ const QuickStartCatalogFilterCountWrapper = ({ quickStartsCount }) => React.createElement(QuickStartCatalogFilterCount, { quickStartsCount: quickStartsCount });
1855
+
1856
+ const QuickStartCatalogFilter = (_a) => {
1857
+ var { quickStartsCount, onSearchInputChange = () => { }, onStatusChange = () => { } } = _a, props = __rest(_a, ["quickStartsCount", "onSearchInputChange", "onStatusChange"]);
1858
+ return (React.createElement(Toolbar, Object.assign({ usePageInsets: true, className: "pfext-quick-start-catalog-filter__flex" }, props),
1859
+ React.createElement(ToolbarContent, null,
1860
+ React.createElement(QuickStartCatalogFilterSearchWrapper, { onSearchInputChange: onSearchInputChange }),
1861
+ React.createElement(QuickStartCatalogFilterStatusWrapper, { onStatusChange: onStatusChange }),
1862
+ React.createElement(QuickStartCatalogFilterCountWrapper, { quickStartsCount: quickStartsCount }))));
1863
+ };
1864
+
1865
+ const QuickStartCatalogEmptyState = ({ clearFilters }) => {
1866
+ const { getResource } = React.useContext(QuickStartContext);
1867
+ return (React.createElement(EmptyState, null,
1868
+ React.createElement(EmptyStateHeader, { titleText: React.createElement(React.Fragment, null, getResource('No results found')), icon: React.createElement(EmptyStateIcon, { icon: SearchIcon }), headingLevel: "h4" }),
1869
+ React.createElement(EmptyStateBody, null, getResource('No results match the filter criteria. Remove filters or clear all filters to show results.')),
1870
+ React.createElement(EmptyStateFooter, null,
1871
+ React.createElement(EmptyStateActions, null,
1872
+ React.createElement(Button, { variant: "link", onClick: clearFilters, "data-test": "clear-filter button" }, getResource('Clear all filters'))))));
1873
+ };
1874
+ const QuickStartCatalogPage = ({ quickStarts, showFilter, sortFnc = (q1, q2) => q1.spec.displayName.localeCompare(q2.spec.displayName), title, hint, showTitle = true, }) => {
1875
+ const sortFncCallback = React.useCallback(sortFnc, [sortFnc]);
1876
+ const { allQuickStarts = [], setAllQuickStarts, allQuickStartStates, getResource, filter, setFilter, loading, } = React.useContext(QuickStartContext);
1877
+ React.useEffect(() => {
1878
+ // passed through prop, not context
1879
+ if (quickStarts && JSON.stringify(quickStarts) !== JSON.stringify(allQuickStarts)) {
1880
+ setAllQuickStarts(quickStarts);
1881
+ }
1882
+ }, [quickStarts, allQuickStarts, setAllQuickStarts]);
1883
+ const initialFilteredQuickStarts = showFilter
1884
+ ? filterQuickStarts(allQuickStarts, filter.keyword, filter.status.statusFilters, allQuickStartStates).sort(sortFncCallback)
1885
+ : allQuickStarts;
1886
+ const [filteredQuickStarts, setFilteredQuickStarts] = React.useState(initialFilteredQuickStarts);
1887
+ React.useEffect(() => {
1888
+ const filteredQs = showFilter
1889
+ ? filterQuickStarts(allQuickStarts, filter.keyword, filter.status.statusFilters, allQuickStartStates).sort(sortFncCallback)
1890
+ : allQuickStarts;
1891
+ // also needs a check whether the content of the QS changed
1892
+ if (filteredQs.length !== filteredQuickStarts.length ||
1893
+ JSON.stringify(filteredQs) !== JSON.stringify(filteredQuickStarts)) {
1894
+ setFilteredQuickStarts(filteredQs);
1895
+ }
1896
+ }, [
1897
+ allQuickStarts,
1898
+ allQuickStartStates,
1899
+ showFilter,
1900
+ filter.keyword,
1901
+ filter.status.statusFilters,
1902
+ sortFncCallback,
1903
+ filteredQuickStarts,
1904
+ ]);
1905
+ const clearFilters = () => {
1906
+ setFilter('keyword', '');
1907
+ setFilter('status', []);
1908
+ clearFilterParams();
1909
+ setFilteredQuickStarts(allQuickStarts.sort((q1, q2) => q1.spec.displayName.localeCompare(q2.spec.displayName)));
1910
+ };
1911
+ const onSearchInputChange = (searchValue) => {
1912
+ const result = filterQuickStarts(allQuickStarts, searchValue, filter.status.statusFilters, allQuickStartStates).sort((q1, q2) => q1.spec.displayName.localeCompare(q2.spec.displayName));
1913
+ if (searchValue !== filter.keyword) {
1914
+ setFilter('keyword', searchValue);
1915
+ }
1916
+ if (result.length !== filteredQuickStarts.length) {
1917
+ setFilteredQuickStarts(result);
1918
+ }
1919
+ };
1920
+ const onStatusChange = (statusList) => {
1921
+ const result = filterQuickStarts(allQuickStarts, filter.keyword, statusList, allQuickStartStates).sort((q1, q2) => q1.spec.displayName.localeCompare(q2.spec.displayName));
1922
+ if (JSON.stringify(statusList) !== JSON.stringify(filter.status)) {
1923
+ setFilter('status', statusList);
1924
+ }
1925
+ if (result.length !== filteredQuickStarts.length) {
1926
+ setFilteredQuickStarts(result);
1927
+ }
1928
+ };
1929
+ if (loading) {
1930
+ return React.createElement(LoadingBox, null);
1931
+ }
1932
+ if (!allQuickStarts || allQuickStarts.length === 0) {
1933
+ return React.createElement(EmptyBox, { label: getResource('Quick Starts') });
1934
+ }
1935
+ return (React.createElement("div", { className: "pfext-quick-start__base" },
1936
+ showTitle && (React.createElement("div", { className: "pfext-page-layout__header" },
1937
+ React.createElement(Text, { component: "h1", className: "pfext-page-layout__title", "data-test": "page-title" }, title || getResource('Quick Starts')),
1938
+ hint && React.createElement("div", { className: "pfext-page-layout__hint" }, hint))),
1939
+ showTitle && React.createElement(Divider, { component: "div" }),
1940
+ showFilter && (React.createElement(React.Fragment, null,
1941
+ React.createElement(QuickStartCatalogFilter, { quickStartsCount: filteredQuickStarts.length, onSearchInputChange: onSearchInputChange, onStatusChange: onStatusChange }),
1942
+ React.createElement(Divider, { component: "div" }))),
1943
+ React.createElement(React.Fragment, null, filteredQuickStarts.length === 0 ? (React.createElement(QuickStartCatalogEmptyState, { clearFilters: clearFilters })) : (React.createElement(QuickStartCatalog, { quickStarts: filteredQuickStarts })))));
1944
+ };
1945
+
1946
+ const QuickStartCatalogHeader = ({ title, hint, }) => (React.createElement("div", { className: "pfext-page-layout__header" },
1947
+ React.createElement("h1", { "data-pf-content": "true", className: "pfext-page-layout__title" }, title),
1948
+ hint && React.createElement("div", { className: "pfext-page-layout__hint" }, hint)));
1949
+
1950
+ const QuickStartCatalogSection = ({ children }) => (React.createElement("div", { className: "pfext-page-layout__content" }, children));
1951
+
1952
+ const QuickStartCatalogToolbar = ({ children }) => (React.createElement(Toolbar, { usePageInsets: true, className: "pfext-quick-start-catalog-filter__flex" }, children));
1953
+
1954
+ const QuickStartCloseModal = ({ isOpen, onConfirm, onCancel, }) => {
1955
+ const { getResource } = React.useContext(QuickStartContext);
1956
+ 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,
1957
+ React.createElement(FlexItem, { align: { default: 'alignRight' } },
1958
+ React.createElement(Button, { variant: "secondary", "data-test": "cancel button", onClick: onCancel }, getResource('Cancel'))),
1959
+ React.createElement(FlexItem, null,
1960
+ React.createElement(Button, { variant: "primary", "data-test": "leave button", onClick: onConfirm }, getResource('Leave')))), isFullScreen: true }, getResource('Your progress will be saved.')));
1961
+ };
1962
+
1963
+ const TaskIcon = ({ taskIndex, taskStatus }) => {
1964
+ const { getResource } = React.useContext(QuickStartContext);
1965
+ const success = taskStatus === QuickStartTaskStatus.SUCCESS;
1966
+ const failed = taskStatus === QuickStartTaskStatus.FAILED;
1967
+ const classNames = css('pfext-icon-and-text__icon', {
1968
+ 'pfext-quick-start-task-header__task-icon-init': !failed && !success,
1969
+ });
1970
+ let content;
1971
+ if (success) {
1972
+ content = (React.createElement(Icon, { size: "md" },
1973
+ React.createElement(CheckCircleIcon, { className: "pfext-quick-start-task-header__task-icon-success" }),
1974
+ ' '));
1975
+ }
1976
+ else if (failed) {
1977
+ content = (React.createElement(Icon, { size: "md" },
1978
+ React.createElement(ExclamationCircleIcon, { className: "pfext-quick-start-task-header__task-icon-failed" })));
1979
+ }
1980
+ else {
1981
+ content = getResource('{{taskIndex, number}}', taskIndex).replace('{{taskIndex, number}}', taskIndex);
1982
+ }
1983
+ return React.createElement("span", { className: classNames }, content);
1984
+ };
1985
+ const QuickStartTaskHeader = ({ title, taskIndex, subtitle, taskStatus, size, isActiveTask, onTaskSelect, children, }) => {
1986
+ const titleRef = React.useRef(null);
1987
+ React.useEffect(() => {
1988
+ if (isActiveTask) {
1989
+ // Focus the WizardNavItem button element that contains the title
1990
+ titleRef.current.parentNode.focus();
1991
+ }
1992
+ }, [isActiveTask]);
1993
+ const classNames = css('pfext-quick-start-task-header__title', {
1994
+ 'pfext-quick-start-task-header__title-success': taskStatus === QuickStartTaskStatus.SUCCESS,
1995
+ 'pfext-quick-start-task-header__title-failed': taskStatus === (QuickStartTaskStatus.FAILED || QuickStartTaskStatus.VISITED),
1996
+ });
1997
+ // const notCompleted = taskStatus === QuickStartTaskStatus.VISITED;
1998
+ // const skippedReview = taskStatus === QuickStartTaskStatus.REVIEW;
1999
+ const failedReview = taskStatus === QuickStartTaskStatus.FAILED;
2000
+ // TODO: toned down when this is shown, investigate further when we should display it
2001
+ // related: https://github.com/patternfly/patternfly-quickstarts/issues/104
2002
+ const tryAgain = failedReview && (React.createElement(React.Fragment, null,
2003
+ React.createElement("div", null),
2004
+ React.createElement("div", { className: "pfext-quick-start-task-header__tryagain" }, "Try the steps again.")));
2005
+ const content = (React.createElement("div", { className: "pfext-quick-start-task-header", ref: titleRef },
2006
+ React.createElement(TaskIcon, { taskIndex: taskIndex, taskStatus: taskStatus }),
2007
+ React.createElement(Title, { headingLevel: "h3", size: size, className: classNames },
2008
+ React.createElement("span", { dangerouslySetInnerHTML: { __html: removeParagraphWrap(markdownConvert(title)) } }),
2009
+ isActiveTask && subtitle && (React.createElement("span", { className: "pfext-quick-start-task-header__subtitle", "data-test-id": "quick-start-task-subtitle" },
2010
+ ' ',
2011
+ subtitle))),
2012
+ tryAgain));
2013
+ return (React.createElement(WizardNavItem, { content: content, stepIndex: taskIndex, onClick: () => onTaskSelect(taskIndex - 1), component: "button", isCurrent: isActiveTask }, children));
2014
+ };
2015
+
2016
+ const QuickStartTaskHeaderList = ({ tasks, allTaskStatuses, onTaskSelect, }) => 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;
2017
+
2018
+ const QuickStartConclusion = ({ tasks, conclusion, allTaskStatuses, nextQuickStarts, onQuickStartChange, onTaskSelect, }) => {
2019
+ const hasFailedTask = allTaskStatuses.includes(QuickStartTaskStatus.FAILED);
2020
+ const { getResource } = React.useContext(QuickStartContext);
2021
+ return (React.createElement(React.Fragment, null,
2022
+ React.createElement(QuickStartTaskHeaderList, { tasks: tasks, allTaskStatuses: allTaskStatuses, onTaskSelect: onTaskSelect }),
2023
+ React.createElement(QuickStartMarkdownView, { content: hasFailedTask
2024
+ ? getResource('One or more verifications did not pass during this quick start. Revisit the tasks or the help links, and then try again.')
2025
+ : conclusion }),
2026
+ !hasFailedTask &&
2027
+ nextQuickStarts &&
2028
+ nextQuickStarts.length > 0 &&
2029
+ nextQuickStarts.map((nextQuickStart, index) => {
2030
+ var _a;
2031
+ return (React.createElement(Button, { variant: "link", onClick: () => onQuickStartChange(nextQuickStart.metadata.name), isInline: true, isBlock: true, key: index },
2032
+ 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),
2033
+ ' ',
2034
+ React.createElement(ArrowRightIcon, { style: { marginLeft: 'var(--pf-v5-global--spacer--xs)', verticalAlign: 'middle' } })));
2035
+ })));
2036
+ };
2037
+
2038
+ const QuickStartIntroduction = ({ tasks, introduction, allTaskStatuses, prerequisites, onTaskSelect, }) => {
2039
+ const { getResource } = React.useContext(QuickStartContext);
2040
+ const prereqs = prerequisites === null || prerequisites === void 0 ? void 0 : prerequisites.filter((p) => p);
2041
+ const [isPrereqsExpanded, setIsPrereqsExpanded] = React.useState(false);
2042
+ 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" },
2043
+ React.createElement(List, { className: "pfext-quick-start-intro__prereq-list" }, prereqs.map((pr) => (React.createElement(ListItem, { key: pr, className: "pfext-quick-start-intro__prereq-list__item" },
2044
+ React.createElement("span", { className: "pfext-quick-start-intro__prereq-list__item-content" },
2045
+ React.createElement(QuickStartMarkdownView, { content: pr }))))))));
2046
+ return (React.createElement(React.Fragment, null,
2047
+ React.createElement(QuickStartMarkdownView, { content: introduction }),
2048
+ prereqList,
2049
+ React.createElement("p", { style: { marginBottom: 'var(--pf-v5-global--spacer--md)' } },
2050
+ getResource('In this quick start, you will complete {{count, number}} task', tasks.length).replace('{{count, number}}', tasks.length),
2051
+ ":"),
2052
+ React.createElement(QuickStartTaskHeaderList, { tasks: tasks, allTaskStatuses: allTaskStatuses, onTaskSelect: onTaskSelect })));
2053
+ };
2054
+
2055
+ const getAlertVariant = (status) => {
2056
+ switch (status) {
2057
+ case QuickStartTaskStatus.SUCCESS:
2058
+ return 'success';
2059
+ case QuickStartTaskStatus.FAILED:
2060
+ return 'danger';
2061
+ default:
2062
+ return 'info';
2063
+ }
2064
+ };
2065
+ const QuickStartTaskReview = ({ review, taskStatus, onTaskReview, }) => {
2066
+ const { instructions, failedTaskHelp: taskHelp } = review;
2067
+ const { getResource } = React.useContext(QuickStartContext);
2068
+ const alertClassNames = css('pfext-quick-start-task-review', {
2069
+ 'pfext-quick-start-task-review--success': taskStatus === QuickStartTaskStatus.SUCCESS,
2070
+ 'pfext-quick-start-task-review--failed': taskStatus === QuickStartTaskStatus.FAILED,
2071
+ });
2072
+ const title = React.createElement("span", { className: alertClassNames }, getResource('Check your work'));
2073
+ return (React.createElement(Alert, { className: "pfext-quick-start-task-review-alert", variant: getAlertVariant(taskStatus), title: title, isInline: true, role: "alert" },
2074
+ React.createElement(QuickStartMarkdownView, { content: instructions }),
2075
+ React.createElement("span", { className: "pfext-quick-start-task-review__actions" },
2076
+ 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) }),
2077
+ React.createElement(Radio, { id: "review-failed", name: "review-failed", "data-testid": "qs-drawer-check-no", label: getResource('No'), className: "pfext-quick-start-task-review__radio", isChecked: taskStatus === QuickStartTaskStatus.FAILED, onChange: () => onTaskReview(QuickStartTaskStatus.FAILED) })),
2078
+ taskStatus === QuickStartTaskStatus.FAILED && taskHelp && (React.createElement(QuickStartMarkdownView, { content: taskHelp, exactHeight: true }))));
2079
+ };
2080
+
2081
+ const QuickStartTasks = ({ tasks, taskNumber, allTaskStatuses, onTaskReview, onTaskSelect, }) => {
2082
+ const { getResource, alwaysShowTaskReview } = React.useContext(QuickStartContext);
2083
+ return (React.createElement("div", { className: "pfext-quick-start-tasks__list" },
2084
+ React.createElement("ul", null, tasks
2085
+ .filter((_, index) => allTaskStatuses[index] !== QuickStartTaskStatus.INIT)
2086
+ .map((task, index) => {
2087
+ const { title, description, review } = task;
2088
+ const isActiveTask = index === taskNumber;
2089
+ const taskStatus = allTaskStatuses[index];
2090
+ const shouldShowTaskReview = (!QUICKSTART_TASKS_INITIAL_STATES.includes(taskStatus) || alwaysShowTaskReview) &&
2091
+ review;
2092
+ return (React.createElement(React.Fragment, { key: title },
2093
+ React.createElement(QuickStartTaskHeader, { taskIndex: index + 1, title: title, size: "md", subtitle: getResource('{{index, number}} of {{tasks, number}}')
2094
+ .replace('{{index, number}}', index + 1)
2095
+ .replace('{{tasks, number}}', tasks.length), taskStatus: taskStatus, isActiveTask: isActiveTask, onTaskSelect: onTaskSelect }, isActiveTask && (React.createElement("div", { className: "pfext-quick-start-task__content" },
2096
+ React.createElement(QuickStartMarkdownView, { content: description }),
2097
+ shouldShowTaskReview && (React.createElement(QuickStartTaskReview, { review: review, taskStatus: taskStatus, onTaskReview: onTaskReview })))))));
2098
+ }))));
2099
+ };
2100
+
2101
+ const QuickStartContent = React.forwardRef(({ quickStart, nextQuickStarts = [], taskNumber, allTaskStatuses, onTaskSelect, onTaskReview, onQuickStartChange, }, ref) => {
2102
+ const { spec: { introduction, tasks, conclusion, prerequisites }, } = quickStart;
2103
+ const totalTasks = tasks.length;
2104
+ return (React.createElement("div", { className: "pfext-quick-start-content", ref: ref },
2105
+ taskNumber === -1 && (React.createElement(QuickStartIntroduction, { tasks: tasks, allTaskStatuses: allTaskStatuses, introduction: introduction, prerequisites: prerequisites, onTaskSelect: onTaskSelect })),
2106
+ taskNumber > -1 && taskNumber < totalTasks && (React.createElement(QuickStartTasks, { tasks: tasks, taskNumber: taskNumber, allTaskStatuses: allTaskStatuses, onTaskReview: onTaskReview, onTaskSelect: onTaskSelect })),
2107
+ taskNumber === totalTasks && (React.createElement(QuickStartConclusion, { tasks: tasks, conclusion: conclusion, allTaskStatuses: allTaskStatuses, nextQuickStarts: nextQuickStarts, onQuickStartChange: onQuickStartChange, onTaskSelect: onTaskSelect }))));
2108
+ });
2109
+
2110
+ const QuickStartFooter = ({ status, taskNumber, totalTasks, onNext, onBack, footerClass, quickStartId, }) => {
2111
+ const { restartQuickStart, getResource } = React.useContext(QuickStartContext);
2112
+ const PrimaryButtonText = React.useMemo(() => ({
2113
+ START: getResource('Start'),
2114
+ CONTINUE: getResource('Continue'),
2115
+ NEXT: getResource('Next'),
2116
+ CLOSE: getResource('Close'),
2117
+ }), [getResource]);
2118
+ const SecondaryButtonText = React.useMemo(() => ({
2119
+ BACK: getResource('Back'),
2120
+ RESTART: getResource('Restart'),
2121
+ }), [getResource]);
2122
+ const onRestart = React.useCallback((e) => {
2123
+ e.preventDefault();
2124
+ e.stopPropagation();
2125
+ restartQuickStart(quickStartId, totalTasks);
2126
+ }, [quickStartId, restartQuickStart, totalTasks]);
2127
+ const getPrimaryButtonText = React.useMemo(() => {
2128
+ if (status === QuickStartStatus.NOT_STARTED) {
2129
+ return PrimaryButtonText.START;
2130
+ }
2131
+ if (taskNumber === totalTasks) {
2132
+ return PrimaryButtonText.CLOSE;
2133
+ }
2134
+ if (taskNumber > -1 && taskNumber < totalTasks) {
2135
+ return PrimaryButtonText.NEXT;
2136
+ }
2137
+ return PrimaryButtonText.CONTINUE;
2138
+ }, [taskNumber, totalTasks, PrimaryButtonText, status]);
2139
+ 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]);
2140
+ 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]);
2141
+ 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]);
2142
+ return (React.createElement("div", { className: `pfext-quick-start-footer ${footerClass}` },
2143
+ getPrimaryButton,
2144
+ getSecondaryButton,
2145
+ getSideNoteAction));
2146
+ };
2147
+
2148
+ const QuickStartController = ({ quickStart, nextQuickStarts, contentRef, footerClass, }) => {
2149
+ const { metadata: { name }, spec: { tasks = [] }, } = quickStart;
2150
+ const totalTasks = tasks === null || tasks === void 0 ? void 0 : tasks.length;
2151
+ const { activeQuickStartState, setActiveQuickStart, setQuickStartTaskNumber, setQuickStartTaskStatus, nextStep, previousStep, } = React.useContext(QuickStartContext);
2152
+ const status = activeQuickStartState === null || activeQuickStartState === void 0 ? void 0 : activeQuickStartState.status;
2153
+ const taskNumber = activeQuickStartState === null || activeQuickStartState === void 0 ? void 0 : activeQuickStartState.taskNumber;
2154
+ const allTaskStatuses = tasks.map((task, index) => activeQuickStartState[`taskStatus${index}`]);
2155
+ const handleQuickStartChange = React.useCallback((quickStartId) => setActiveQuickStart(quickStartId), [setActiveQuickStart]);
2156
+ const handleTaskStatusChange = React.useCallback((newTaskStatus) => setQuickStartTaskStatus(newTaskStatus), [setQuickStartTaskStatus]);
2157
+ const getQuickStartActiveTask = React.useCallback(() => {
2158
+ let activeTaskNumber = 0;
2159
+ while (activeTaskNumber !== totalTasks &&
2160
+ activeQuickStartState[`taskStatus${activeTaskNumber}`] === QuickStartTaskStatus.SUCCESS) {
2161
+ activeTaskNumber++;
2162
+ }
2163
+ return activeTaskNumber;
2164
+ }, [totalTasks, activeQuickStartState]);
2165
+ const handleQuickStartContinue = React.useCallback(() => {
2166
+ const activeTaskNumber = getQuickStartActiveTask();
2167
+ setQuickStartTaskNumber(name, activeTaskNumber);
2168
+ }, [getQuickStartActiveTask, setQuickStartTaskNumber, name]);
2169
+ const handleNext = React.useCallback(() => {
2170
+ if (status === QuickStartStatus.COMPLETE && taskNumber === totalTasks) {
2171
+ return handleQuickStartChange('');
2172
+ }
2173
+ if (status !== QuickStartStatus.NOT_STARTED && taskNumber === -1) {
2174
+ return handleQuickStartContinue();
2175
+ }
2176
+ return nextStep(totalTasks);
2177
+ }, [handleQuickStartChange, nextStep, status, taskNumber, totalTasks, handleQuickStartContinue]);
2178
+ const handleBack = React.useCallback(() => previousStep(), [previousStep]);
2179
+ const handleTaskSelect = React.useCallback((selectedTaskNumber) => {
2180
+ setQuickStartTaskNumber(name, selectedTaskNumber);
2181
+ }, [name, setQuickStartTaskNumber]);
2182
+ return (React.createElement(React.Fragment, null,
2183
+ React.createElement(QuickStartContent, { quickStart: quickStart, nextQuickStarts: nextQuickStarts, taskNumber: taskNumber, allTaskStatuses: allTaskStatuses, onTaskSelect: handleTaskSelect, onTaskReview: handleTaskStatusChange, onQuickStartChange: handleQuickStartChange, ref: contentRef }),
2184
+ React.createElement(QuickStartFooter, { status: status, taskNumber: taskNumber, totalTasks: totalTasks, onNext: handleNext, onBack: handleBack, footerClass: footerClass, quickStartId: quickStart.metadata.name })));
2185
+ };
2186
+
2187
+ const getElement = (appendTo) => {
2188
+ if (typeof appendTo === 'function') {
2189
+ return appendTo();
2190
+ }
2191
+ return appendTo;
2192
+ };
2193
+ const useScrollTopOnTaskNumberChange = (node, taskNumber) => {
2194
+ React.useEffect(() => {
2195
+ if (node) {
2196
+ node.scrollTo({ top: 0, behavior: 'smooth' });
2197
+ }
2198
+ }, [taskNumber, node]);
2199
+ };
2200
+ const QuickStartPanelContent = (_a) => {
2201
+ var { quickStarts = [], handleClose, activeQuickStartID, appendTo, isResizable = true, showClose = true, headerVariant = '' } = _a, props = __rest(_a, ["quickStarts", "handleClose", "activeQuickStartID", "appendTo", "isResizable", "showClose", "headerVariant"]);
2202
+ const titleRef = React.useRef(null);
2203
+ const { getResource, activeQuickStartState } = React.useContext(QuickStartContext);
2204
+ const [contentRef, setContentRef] = React.useState();
2205
+ const shadows = useScrollShadows(contentRef);
2206
+ const quickStart = quickStarts.find((qs) => qs.metadata.name === activeQuickStartID);
2207
+ const taskNumber = activeQuickStartState === null || activeQuickStartState === void 0 ? void 0 : activeQuickStartState.taskNumber;
2208
+ useScrollTopOnTaskNumberChange(contentRef, taskNumber);
2209
+ 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); });
2210
+ const headerClasses = css('pfext-quick-start-panel-content__header', {
2211
+ 'pfext-quick-start-panel-content__header__shadow': shadows === Shadows.top || shadows === Shadows.both,
2212
+ 'pfext-quick-start-panel-content__header--blue-white': headerVariant === 'blue-white',
2213
+ });
2214
+ const footerClass = css({
2215
+ 'pfext-quick-start-panel-content__footer__shadow': shadows === Shadows.bottom || shadows === Shadows.both,
2216
+ });
2217
+ const getStep = () => {
2218
+ const tasks = quickStart.spec.tasks.length;
2219
+ if (Number.parseInt(taskNumber) === -1) {
2220
+ return 'intro';
2221
+ }
2222
+ if (Number.parseInt(taskNumber) === tasks) {
2223
+ return 'conclusion';
2224
+ }
2225
+ return Number.parseInt(taskNumber) + 1;
2226
+ };
2227
+ React.useEffect(() => {
2228
+ if (quickStart) {
2229
+ titleRef.current.focus();
2230
+ }
2231
+ }, [quickStart]);
2232
+ 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),
2233
+ React.createElement("div", { className: headerClasses },
2234
+ React.createElement(DrawerHead, null,
2235
+ React.createElement("div", { className: "pfext-quick-start-panel-content__title", tabIndex: -1, ref: titleRef },
2236
+ React.createElement(Title, { headingLevel: "h2", size: "xl", className: "pfext-quick-start-panel-content__name", style: { marginRight: 'var(--pf-v5-global--spacer--md)' } },
2237
+ React.createElement("span", { dangerouslySetInnerHTML: {
2238
+ __html: removeParagraphWrap(markdownConvert(quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.displayName)),
2239
+ } }),
2240
+ ' ',
2241
+ React.createElement("small", { className: "pfext-quick-start-panel-content__duration" }, (quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.durationMinutes)
2242
+ ? getResource('{{type}} • {{duration, number}} minutes', quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.durationMinutes)
2243
+ .replace('{{duration, number}}', quickStart === null || quickStart === void 0 ? void 0 : quickStart.spec.durationMinutes)
2244
+ .replace('{{type}}', getResource('Type'))
2245
+ : getResource('Type')))),
2246
+ showClose && (React.createElement(DrawerActions, null,
2247
+ React.createElement(DrawerCloseButton, { onClick: handleClose, className: "pfext-quick-start-panel-content__close-button", "data-testid": "qs-drawer-close" }))))),
2248
+ React.createElement(DrawerPanelBody, { hasNoPadding: true, className: "pfext-quick-start-panel-content__body", "data-test": "content" },
2249
+ React.createElement(QuickStartController, { quickStart: quickStart, nextQuickStarts: nextQuickStarts, footerClass: footerClass, contentRef: setContentRef })))) : null;
2250
+ if (appendTo) {
2251
+ return ReactDOM.createPortal(content, getElement(appendTo));
2252
+ }
2253
+ return content;
2254
+ };
2255
+
2256
+ const QuickStartContainer = (_a) => {
2257
+ var { quickStarts, children, activeQuickStartID, allQuickStartStates, setActiveQuickStartID, setAllQuickStartStates, appendTo, fullWidth, onCloseInProgress, onCloseNotInProgress, resourceBundle, showCardFooters, useLegacyHeaderColors, language, loading = false, useQueryParams = true, markdown, contextProps, alwaysShowTaskReview = true } = _a, props = __rest(_a, ["quickStarts", "children", "activeQuickStartID", "allQuickStartStates", "setActiveQuickStartID", "setAllQuickStartStates", "appendTo", "fullWidth", "onCloseInProgress", "onCloseNotInProgress", "resourceBundle", "showCardFooters", "useLegacyHeaderColors", "language", "loading", "useQueryParams", "markdown", "contextProps", "alwaysShowTaskReview"]);
2258
+ const valuesForQuickstartContext = useValuesForQuickStartContext(Object.assign({ allQuickStarts: quickStarts, activeQuickStartID,
2259
+ setActiveQuickStartID,
2260
+ allQuickStartStates,
2261
+ setAllQuickStartStates, footer: {
2262
+ show: showCardFooters,
2263
+ }, useLegacyHeaderColors,
2264
+ language, resourceBundle: Object.assign({}, resourceBundle), loading,
2265
+ useQueryParams,
2266
+ markdown,
2267
+ alwaysShowTaskReview }, contextProps));
2268
+ React.useEffect(() => {
2269
+ if (quickStarts &&
2270
+ JSON.stringify(quickStarts) !== JSON.stringify(valuesForQuickstartContext.allQuickStarts)) {
2271
+ valuesForQuickstartContext.setAllQuickStarts(quickStarts);
2272
+ }
2273
+ }, [quickStarts, valuesForQuickstartContext]);
2274
+ React.useEffect(() => {
2275
+ if (loading !== valuesForQuickstartContext.loading) {
2276
+ valuesForQuickstartContext.setLoading(loading);
2277
+ }
2278
+ }, [loading, valuesForQuickstartContext]);
2279
+ const drawerProps = Object.assign({ appendTo,
2280
+ fullWidth,
2281
+ onCloseInProgress,
2282
+ onCloseNotInProgress }, props);
2283
+ return (React.createElement(QuickStartContext.Provider, { value: valuesForQuickstartContext },
2284
+ React.createElement(QuickStartDrawer, Object.assign({}, drawerProps), children)));
2285
+ };
2286
+ const QuickStartDrawer = (_a) => {
2287
+ var { quickStarts = [], children, appendTo, fullWidth, onCloseInProgress, onCloseNotInProgress } = _a, props = __rest(_a, ["quickStarts", "children", "appendTo", "fullWidth", "onCloseInProgress", "onCloseNotInProgress"]);
2288
+ const { activeQuickStartID, setActiveQuickStart, allQuickStarts = [], activeQuickStartState, allQuickStartStates, setAllQuickStartStates, useLegacyHeaderColors, } = React.useContext(QuickStartContext);
2289
+ const combinedQuickStarts = allQuickStarts.concat(quickStarts);
2290
+ React.useEffect(() => {
2291
+ const params = new URLSearchParams(window.location.search);
2292
+ // if there is a quick start param, but the quick start is not active, set it
2293
+ // this can happen if a new browser session is opened or an incognito window for example
2294
+ const quickStartIdFromParam = params.get(QUICKSTART_ID_FILTER_KEY) || '';
2295
+ if (quickStartIdFromParam && activeQuickStartID !== quickStartIdFromParam) {
2296
+ const activeQuickStart = getQuickStartByName(quickStartIdFromParam, combinedQuickStarts);
2297
+ // don't try to load a quick start that is actually just an external resource (spec.link)
2298
+ if (combinedQuickStarts.length > 0 && activeQuickStart && !activeQuickStart.spec.link) {
2299
+ setActiveQuickStart(quickStartIdFromParam);
2300
+ }
2301
+ }
2302
+ }, [activeQuickStartID, combinedQuickStarts, setActiveQuickStart]);
2303
+ React.useEffect(() => {
2304
+ // If activeQuickStartID was changed through prop from QuickStartContainer, need to init the state if it does not exist yet
2305
+ if (activeQuickStartID && !allQuickStartStates[activeQuickStartID]) {
2306
+ setAllQuickStartStates(Object.assign(Object.assign({}, allQuickStartStates), { [activeQuickStartID]: getDefaultQuickStartState() }));
2307
+ }
2308
+ }, [activeQuickStartID, allQuickStartStates, setAllQuickStartStates]);
2309
+ const [modalOpen, setModalOpen] = React.useState(false);
2310
+ const activeQuickStartStatus = activeQuickStartState === null || activeQuickStartState === void 0 ? void 0 : activeQuickStartState.status;
2311
+ const onClose = () => setActiveQuickStart('');
2312
+ const handleClose = () => {
2313
+ if (activeQuickStartStatus === QuickStartStatus.IN_PROGRESS) {
2314
+ if (onCloseInProgress) {
2315
+ onCloseInProgress();
2316
+ }
2317
+ else {
2318
+ setModalOpen(true);
2319
+ }
2320
+ }
2321
+ else if (onCloseNotInProgress) {
2322
+ onCloseNotInProgress();
2323
+ }
2324
+ else {
2325
+ onClose();
2326
+ }
2327
+ };
2328
+ const onModalConfirm = () => {
2329
+ setModalOpen(false);
2330
+ onClose();
2331
+ };
2332
+ const onModalCancel = () => setModalOpen(false);
2333
+ const fullWidthPanelStyle = fullWidth
2334
+ ? {
2335
+ style: {
2336
+ flex: 1,
2337
+ },
2338
+ }
2339
+ : {};
2340
+ const fullWidthBodyStyle = fullWidth
2341
+ ? {
2342
+ style: {
2343
+ display: activeQuickStartID ? 'none' : 'flex',
2344
+ },
2345
+ }
2346
+ : {};
2347
+ const panelContent = (React.createElement(QuickStartPanelContent, Object.assign({ quickStarts: combinedQuickStarts, handleClose: handleClose, activeQuickStartID: activeQuickStartID, appendTo: appendTo, isResizable: !fullWidth, headerVariant: useLegacyHeaderColors ? '' : 'blue-white' }, fullWidthPanelStyle)));
2348
+ return (React.createElement(React.Fragment, null,
2349
+ React.createElement(Drawer, Object.assign({ isExpanded: !!activeQuickStartID, isInline: true }, props), children ? (React.createElement(DrawerContent, Object.assign({ panelContent: panelContent }, fullWidthBodyStyle),
2350
+ React.createElement(DrawerContentBody, { className: "pfext-quick-start-drawer__body" }, children))) : (React.createElement("div", { className: "pf-v5-c-drawer__main" }, panelContent))),
2351
+ React.createElement(QuickStartCloseModal, { isOpen: modalOpen, onConfirm: onModalConfirm, onCancel: onModalCancel })));
2352
+ };
2353
+
2354
+ const HelpTopicContextDefaults = {
2355
+ helpTopics: [],
2356
+ setHelpTopics: () => { },
2357
+ activeHelpTopic: null,
2358
+ setActiveHelpTopicByName: () => { },
2359
+ filteredHelpTopics: [],
2360
+ setFilteredHelpTopics: () => { },
2361
+ loading: false,
2362
+ };
2363
+ const HelpTopicContext = React__default.createContext(HelpTopicContextDefaults);
2364
+ const useValuesForHelpTopicContext = (value = {}) => {
2365
+ const combinedValue = Object.assign(Object.assign({}, HelpTopicContextDefaults), value);
2366
+ const [loading, setLoading] = React__default.useState(combinedValue.loading);
2367
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
2368
+ const [helpTopics, setHelpTopics] = React__default.useState(combinedValue.helpTopics || []);
2369
+ const [activeHelpTopic, setActiveHelpTopic] = React__default.useState(combinedValue.activeHelpTopic || null);
2370
+ const setActiveHelpTopicByName = React__default.useCallback((helpTopicName) => {
2371
+ const topic = helpTopics.find((t) => t.name === helpTopicName);
2372
+ if (!helpTopicName) {
2373
+ setActiveHelpTopic(null);
2374
+ return;
2375
+ }
2376
+ setActiveHelpTopic(topic);
2377
+ }, [helpTopics]);
2378
+ const [filteredHelpTopics, setFilteredHelpTopics] = React__default.useState(combinedValue.filteredHelpTopics || []);
2379
+ return {
2380
+ helpTopics,
2381
+ setHelpTopics,
2382
+ activeHelpTopic,
2383
+ setActiveHelpTopicByName,
2384
+ filteredHelpTopics,
2385
+ setFilteredHelpTopics,
2386
+ loading,
2387
+ setLoading,
2388
+ };
2389
+ };
2390
+
2391
+ const HelpTopicPanelContent = (_a) => {
2392
+ var _b, _c;
2393
+ var { activeHelpTopic = null, filteredHelpTopics = [], isResizable = true, onClose } = _a, props = __rest(_a, ["activeHelpTopic", "filteredHelpTopics", "isResizable", "onClose"]);
2394
+ const { setActiveHelpTopicByName } = React.useContext(HelpTopicContext);
2395
+ const [isHelpTopicMenuOpen, setIsHelpTopicMenuOpen] = React.useState(false);
2396
+ const toggleHelpTopicMenu = () => {
2397
+ setIsHelpTopicMenuOpen(!isHelpTopicMenuOpen);
2398
+ };
2399
+ const onSelectHelpTopic = (_event, value) => {
2400
+ const topicName = value;
2401
+ setActiveHelpTopicByName(topicName.toString());
2402
+ toggleHelpTopicMenu();
2403
+ };
2404
+ const helpTopicOptions = filteredHelpTopics.length > 1 &&
2405
+ filteredHelpTopics.map((topic) => (React.createElement(SelectOption, { key: topic.name, value: topic.name }, topic.title)));
2406
+ const paddingContainer = (children) => React.createElement("div", { style: { padding: '24px' } }, children);
2407
+ const panelBodyItems = (React.createElement(React.Fragment, null,
2408
+ paddingContainer(React.createElement(QuickStartMarkdownView, { content: activeHelpTopic === null || activeHelpTopic === void 0 ? void 0 : activeHelpTopic.content })),
2409
+ !!((_b = activeHelpTopic === null || activeHelpTopic === void 0 ? void 0 : activeHelpTopic.links) === null || _b === void 0 ? void 0 : _b.length) && React.createElement(Divider, null),
2410
+ paddingContainer(React.createElement(Stack, { hasGutter: true }, (_c = activeHelpTopic === null || activeHelpTopic === void 0 ? void 0 : activeHelpTopic.links) === null || _c === void 0 ? void 0 : _c.map(({ href, text, newTab, isExternal }, index) => (React.createElement(StackItem, { key: index },
2411
+ React.createElement(Button, { component: "a", href: href, target: newTab ? '_blank' : '', rel: "noopener noreferrer", variant: "link", "aria-label": `Open documentation in new window`, isInline: true, icon: isExternal ? React.createElement(ExternalLinkAltIcon, null) : null, iconPosition: "right", style: { fontSize: 'inherit' } }, text || href))))))));
2412
+ const content = (React.createElement(DrawerPanelContent, Object.assign({ isResizable: isResizable, className: "pfext-quick-start__base" }, props),
2413
+ React.createElement("div", null,
2414
+ React.createElement(DrawerHead, null,
2415
+ React.createElement("div", { className: "pfext-quick-start-panel-content__title" },
2416
+ helpTopicOptions && (React.createElement(Select, { isPlain: true, id: "help-topics-select", selected: activeHelpTopic, isOpen: isHelpTopicMenuOpen, onSelect: onSelectHelpTopic, onOpenChange: (isOpen) => setIsHelpTopicMenuOpen(isOpen), toggle: (toggleRef) => (React.createElement(MenuToggle, { isFullWidth: true, ref: toggleRef, icon: React.createElement(BarsIcon, null), onClick: toggleHelpTopicMenu, isExpanded: isHelpTopicMenuOpen }, activeHelpTopic === null || activeHelpTopic === void 0 ? void 0 : activeHelpTopic.title)) },
2417
+ React.createElement(SelectList, null, helpTopicOptions))),
2418
+ React.createElement(Title, { headingLevel: "h1", size: "xl", className: "pfext-quick-start-panel-content__name", style: { marginRight: 'var(--pf-v5-global--spacer--md)' } }, activeHelpTopic === null || activeHelpTopic === void 0 ? void 0 : activeHelpTopic.title)),
2419
+ React.createElement(DrawerActions, null,
2420
+ React.createElement(DrawerCloseButton, { onClick: onClose, className: "pfext-quick-start-panel-content__close-button", "data-testid": "qs-drawer-close" }))),
2421
+ React.createElement(Divider, null),
2422
+ React.createElement(DrawerPanelBody, { hasNoPadding: true, className: "pfext-quick-start-panel-content__body", "data-test": "content" }, panelBodyItems))));
2423
+ return content;
2424
+ };
2425
+
2426
+ const HelpTopicContainer = (_a) => {
2427
+ var { helpTopics, children, resourceBundle, language, loading = false, markdown, contextProps } = _a, props = __rest(_a, ["helpTopics", "children", "resourceBundle", "language", "loading", "markdown", "contextProps"]);
2428
+ const valuesForHelpTopicContext = useValuesForHelpTopicContext(Object.assign({ helpTopics,
2429
+ language, resourceBundle: Object.assign({}, resourceBundle), loading,
2430
+ markdown }, contextProps));
2431
+ React.useEffect(() => {
2432
+ if (loading !== valuesForHelpTopicContext.loading) {
2433
+ valuesForHelpTopicContext.setLoading(loading);
2434
+ }
2435
+ }, [loading, valuesForHelpTopicContext]);
2436
+ React.useEffect(() => {
2437
+ if (helpTopics &&
2438
+ JSON.stringify(helpTopics) !== JSON.stringify(valuesForHelpTopicContext.helpTopics)) {
2439
+ valuesForHelpTopicContext.setHelpTopics(helpTopics);
2440
+ }
2441
+ }, [helpTopics, valuesForHelpTopicContext]);
2442
+ return (React.createElement(HelpTopicContext.Provider, { value: valuesForHelpTopicContext },
2443
+ React.createElement(HelpTopicDrawer, Object.assign({}, props), children)));
2444
+ };
2445
+ const HelpTopicDrawer = (_a) => {
2446
+ var { children } = _a, props = __rest(_a, ["children"]);
2447
+ const { activeHelpTopic, filteredHelpTopics, setActiveHelpTopicByName } = React.useContext(HelpTopicContext);
2448
+ const onClose = () => {
2449
+ setActiveHelpTopicByName('');
2450
+ };
2451
+ const panelContent = (React.createElement(HelpTopicPanelContent, { activeHelpTopic: activeHelpTopic, filteredHelpTopics: filteredHelpTopics, onClose: onClose }));
2452
+ return (React.createElement(React.Fragment, null,
2453
+ React.createElement(Drawer, Object.assign({ isExpanded: !!activeHelpTopic, isInline: true }, props), children ? (React.createElement(DrawerContent, { panelContent: panelContent },
2454
+ React.createElement(DrawerContentBody, { className: "pfext-quick-start-drawer__body" }, children))) : (React.createElement("div", { className: "pf-v5-c-drawer__main" }, panelContent)))));
2455
+ };
2456
+
2457
+ const useLocalStorage = (key, initialValue) => {
2458
+ // State to store our value
2459
+ // Pass initial state function to useState so logic is only executed once
2460
+ const [storedValue, setStoredValue] = useState(() => {
2461
+ try {
2462
+ // Get from local storage by key
2463
+ const item = window.localStorage.getItem(key);
2464
+ // Parse stored json or if none return initialValue
2465
+ return item ? JSON.parse(item) : initialValue;
2466
+ }
2467
+ catch (error) {
2468
+ // If error also return initialValue
2469
+ // eslint-disable-next-line no-console
2470
+ console.log(error);
2471
+ return initialValue;
2472
+ }
2473
+ });
2474
+ // Return a wrapped version of useState's setter function that ...
2475
+ // ... persists the new value to localStorage.
2476
+ const setValue = (value) => {
2477
+ try {
2478
+ // Allow value to be a function so we have same API as useState
2479
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
2480
+ // Save state
2481
+ setStoredValue(valueToStore);
2482
+ // Save to local storage
2483
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
2484
+ }
2485
+ catch (error) {
2486
+ // A more advanced implementation would handle the error case
2487
+ // eslint-disable-next-line no-console
2488
+ console.log(error);
2489
+ }
2490
+ };
2491
+ return [storedValue, setValue];
2492
+ };
2493
+
2494
+ /* eslint-disable */
2495
+ // Brought in from dev to publish this with QS module
2496
+ // Dev now imports from here
2497
+ const ProcQuickStartParser = (quickStart, environmentVariables) => {
2498
+ var _a;
2499
+ const replaceEnvironmentVariables = (s) => s === null || s === void 0 ? void 0 : s.replace(/\${(\w+)}/, (substring, name) => {
2500
+ return environmentVariables ? ([name] ? environmentVariables[name] : substring) : substring;
2501
+ });
2502
+ quickStart.spec.tasks = (_a = quickStart.spec.tasks) === null || _a === void 0 ? void 0 : _a.map((task, index) => {
2503
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
2504
+ let proc;
2505
+ let answer;
2506
+ if (typeof task === 'string') {
2507
+ proc = task;
2508
+ answer = {};
2509
+ }
2510
+ else {
2511
+ proc = task.proc;
2512
+ answer = task;
2513
+ delete task.proc;
2514
+ }
2515
+ let description = '', procedure, verification, title, summaryFailed, success, reviewFailed, prerequisites;
2516
+ if (proc) {
2517
+ const taskDOM = document.createElement('div');
2518
+ taskDOM.innerHTML = proc;
2519
+ // remove the screencapture images
2520
+ taskDOM.querySelectorAll('.imageblock.screencapture').forEach((node) => {
2521
+ var _a;
2522
+ (_a = node.parentElement) === null || _a === void 0 ? void 0 : _a.removeChild(node);
2523
+ });
2524
+ title = (_a = taskDOM
2525
+ .querySelector('h1:first-child,h2:first-child,h3:first-child,h4:first-child,h5:first-child')) === null || _a === void 0 ? void 0 : _a.innerHTML.trim();
2526
+ let sectionBody = taskDOM.querySelector('.sectionbody');
2527
+ if (!(sectionBody === null || sectionBody === void 0 ? void 0 : sectionBody.hasChildNodes())) {
2528
+ // possibly in other templates, where we want to look for article
2529
+ sectionBody = taskDOM.querySelector('article');
2530
+ }
2531
+ if (sectionBody) {
2532
+ for (let i = 0; i < sectionBody.children.length || 0; i++) {
2533
+ /**
2534
+ child typically looks like:
2535
+
2536
+ <div class="paragraph|olist|ulist|admonitionblock">
2537
+ <div class="title">Procedure|Prerequisites|Verification|Note|Warning</div>
2538
+ <ol|ul class="arabic">
2539
+ <li>
2540
+ <li>...
2541
+ </ol|ul>
2542
+ </div>
2543
+
2544
+ And the below code extracts the <ol> or <ul>
2545
+ Except for when there is no <div class="title|heading"/>, then the description is extracted
2546
+ in the else if below
2547
+ */
2548
+ const child = sectionBody.children.item(i);
2549
+ // find the title
2550
+ const sectionTitle = child === null || child === void 0 ? void 0 : child.querySelector('.heading,.title');
2551
+ // should this section be assigned to a specific section
2552
+ const sectionTitleText = (_b = sectionTitle === null || sectionTitle === void 0 ? void 0 : sectionTitle.textContent) === null || _b === void 0 ? void 0 : _b.trim();
2553
+ const isKnownSection = ['Procedure', 'Verification', 'Prerequisites'].includes((_c = sectionTitle === null || sectionTitle === void 0 ? void 0 : sectionTitle.textContent) === null || _c === void 0 ? void 0 : _c.trim());
2554
+ if (isKnownSection) {
2555
+ switch (sectionTitleText) {
2556
+ case 'Procedure':
2557
+ procedure = (_d = child === null || child === void 0 ? void 0 : child.querySelector(':not(.heading):not(.title)')) === null || _d === void 0 ? void 0 : _d.outerHTML.trim();
2558
+ break;
2559
+ case 'Verification':
2560
+ verification = (_e = child === null || child === void 0 ? void 0 : child.querySelector(':not(.heading):not(.title)')) === null || _e === void 0 ? void 0 : _e.outerHTML.trim();
2561
+ break;
2562
+ case 'Prerequisites':
2563
+ prerequisites = (_f = child === null || child === void 0 ? void 0 : child.querySelector(':not(.heading):not(.title)')) === null || _f === void 0 ? void 0 : _f.outerHTML.trim();
2564
+ break;
2565
+ }
2566
+ }
2567
+ else if (!procedure) {
2568
+ // Otherwise if it comes before a procedure it's part of the description
2569
+ description = description + (child === null || child === void 0 ? void 0 : child.outerHTML.trim());
2570
+ }
2571
+ }
2572
+ }
2573
+ success = (_g = taskDOM.querySelector('.qs-summary.success')) === null || _g === void 0 ? void 0 : _g.innerHTML.trim();
2574
+ reviewFailed = (_h = taskDOM.querySelector('.qs-review.failed')) === null || _h === void 0 ? void 0 : _h.innerHTML.trim();
2575
+ summaryFailed = (_j = taskDOM.querySelector('.qs-summary.failed')) === null || _j === void 0 ? void 0 : _j.innerHTML.trim();
2576
+ }
2577
+ answer.title = replaceEnvironmentVariables(answer.title || title);
2578
+ answer.description = replaceEnvironmentVariables(answer.description || `${description} ${prerequisites || ''} ${procedure}`);
2579
+ answer.review = answer.review || {};
2580
+ answer.review.instructions = replaceEnvironmentVariables(((_k = answer.review) === null || _k === void 0 ? void 0 : _k.instructions) || verification || 'Have you completed these steps?');
2581
+ answer.review.failedTaskHelp = replaceEnvironmentVariables(answer.review.failedTaskHelp ||
2582
+ reviewFailed ||
2583
+ 'This task isn’t verified yet. Try the task again.');
2584
+ answer.summary = answer.summary || {};
2585
+ answer.summary.success = replaceEnvironmentVariables(answer.summary.success || success || 'You have completed this task!');
2586
+ answer.summary.failed = replaceEnvironmentVariables(answer.summary.failed || summaryFailed || 'Try the steps again.');
2587
+ return answer;
2588
+ });
2589
+ return quickStart;
2590
+ };
2591
+
2592
+ export { Box, CamelCaseWrap, EmptyBox, HELP_TOPIC_NAME_KEY, HelpTopicContainer, HelpTopicContext, HelpTopicContextDefaults, HelpTopicDrawer, Loading, LoadingBox, ProcQuickStartParser, QUICKSTART_ID_FILTER_KEY, QUICKSTART_SEARCH_FILTER_KEY, QUICKSTART_STATUS_FILTER_KEY, QUICKSTART_TASKS_INITIAL_STATES, QUICK_START_NAME, QuickStartCatalog, QuickStartCatalogEmptyState, QuickStartCatalogFilter, QuickStartCatalogFilterCount, QuickStartCatalogFilterCountWrapper, QuickStartCatalogFilterSearch, QuickStartCatalogFilterSearchWrapper, QuickStartCatalogFilterSelect, QuickStartCatalogFilterStatusWrapper, QuickStartCatalogHeader, QuickStartCatalogPage, QuickStartCatalogSection, QuickStartCatalogToolbar, QuickStartCloseModal, QuickStartContainer, QuickStartContext, QuickStartContextDefaults, QuickStartContextProvider, QuickStartDrawer, QuickStartPanelContent, QuickStartStatus, QuickStartTaskStatus, QuickStartTile, QuickStartTileDescription, QuickStartTileFooter, QuickStartTileFooterExternal, QuickStartTileHeader, camelize, clearFilterParams, equalsIgnoreOrder, filterQuickStarts, getDefaultQuickStartState, getDisabledQuickStarts, getQuickStartByName, getQuickStartStatus, getQuickStartStatusCount, getResource, getTaskStatusKey, history, isDisabledQuickStart, removeQueryArgument, setQueryArgument, useLocalStorage, useValuesForHelpTopicContext, useValuesForQuickStartContext };
2593
+ //# sourceMappingURL=index.es.js.map