@patternfly/quickstarts 2.2.1 → 2.2.4

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 (203) hide show
  1. package/README.md +20 -20
  2. package/dist/ConsoleShared/src/components/markdown-extensions/code-extension.d.ts +7 -0
  3. package/dist/ConsoleShared/src/components/markdown-extensions/index.d.ts +1 -0
  4. package/dist/HelpTopicDrawer.d.ts +8 -2
  5. package/dist/QuickStartDrawer.d.ts +21 -2
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.es.js +127 -21
  8. package/dist/index.es.js.map +1 -1
  9. package/dist/index.js +126 -19
  10. package/dist/index.js.map +1 -1
  11. package/dist/patternfly-docs/quick-starts/design-guidelines/design-guidelines.md +105 -0
  12. package/dist/patternfly-docs/quick-starts/design-guidelines/img/card-elements copy.png +0 -0
  13. package/dist/patternfly-docs/quick-starts/design-guidelines/img/card-elements.png +0 -0
  14. package/dist/patternfly-docs/quick-starts/design-guidelines/img/catalog-elements.png +0 -0
  15. package/dist/patternfly-docs/quick-starts/design-guidelines/img/check-your-work.png +0 -0
  16. package/dist/patternfly-docs/quick-starts/design-guidelines/img/introduction-screen.png +0 -0
  17. package/dist/patternfly-docs/quick-starts/design-guidelines/img/mixed-catalog.png +0 -0
  18. package/dist/patternfly-docs/quick-starts/design-guidelines/img/prerequisites.png +0 -0
  19. package/dist/patternfly-docs/quick-starts/design-guidelines/img/qs-context.png +0 -0
  20. package/dist/patternfly-docs/quick-starts/design-guidelines/img/side-panel-elements.png +0 -0
  21. package/dist/patternfly-docs/quick-starts/design-guidelines/img/side-panel-resized.png +0 -0
  22. package/dist/patternfly-docs/quick-starts/design-guidelines/img/side-panel.png +0 -0
  23. package/dist/patternfly-docs/quick-starts/design-guidelines/img/task-no.png +0 -0
  24. package/dist/patternfly-docs/quick-starts/design-guidelines/img/task-yes.png +0 -0
  25. package/dist/patternfly-docs/quick-starts/design-guidelines/img/task.png +0 -0
  26. package/dist/patternfly-docs/quick-starts/examples/Basic.jsx +73 -0
  27. package/dist/patternfly-docs/quick-starts/examples/HelpTopic.jsx +53 -0
  28. package/dist/patternfly-docs/quick-starts/examples/about.md +77 -0
  29. package/dist/patternfly-docs/quick-starts/examples/basic.md +27 -0
  30. package/dist/patternfly-docs/quick-starts/examples/example-data/example-help-topics.js +173 -0
  31. package/dist/patternfly-docs/quick-starts/examples/example-data/example-quickstarts.js +215 -0
  32. package/dist/patternfly-docs/quick-starts/examples/example-data/index.js +15 -0
  33. package/dist/patternfly-docs/quick-starts/examples/help-topics.md +25 -0
  34. package/dist/patternfly-docs/quick-starts/examples/img/catalog.png +0 -0
  35. package/dist/patternfly-docs/quick-starts/examples/img/help-topic.png +0 -0
  36. package/dist/patternfly-docs/quick-starts/examples/img/side-panel.png +0 -0
  37. package/dist/patternfly-nested.css +11 -1
  38. package/dist/quickstarts-base.css +49 -11
  39. package/dist/quickstarts-full.es.js +451 -305
  40. package/dist/quickstarts-full.es.js.map +1 -1
  41. package/dist/quickstarts-standalone.css +5 -15
  42. package/dist/quickstarts-standalone.min.css +1 -1
  43. package/dist/quickstarts.css +49 -11
  44. package/dist/quickstarts.min.css +1 -1
  45. package/dist/utils/asciidoc-procedure-parser.d.ts +12 -0
  46. package/dist/utils/help-topic-types.d.ts +7 -1
  47. package/package.json +11 -4
  48. package/src/ConsoleInternal/components/_icon-and-text.scss +14 -0
  49. package/src/ConsoleInternal/components/_markdown-view.scss +19 -0
  50. package/src/ConsoleInternal/components/catalog/_catalog.scss +390 -0
  51. package/src/ConsoleInternal/components/markdown-view.tsx +305 -0
  52. package/src/ConsoleInternal/components/utils/_status-box.scss +58 -0
  53. package/src/ConsoleInternal/components/utils/camel-case-wrap.tsx +33 -0
  54. package/src/ConsoleInternal/components/utils/index.tsx +3 -0
  55. package/src/ConsoleInternal/components/utils/router.ts +47 -0
  56. package/src/ConsoleInternal/components/utils/status-box.tsx +94 -0
  57. package/src/ConsoleInternal/module/k8s/types.ts +53 -0
  58. package/src/ConsoleShared/index.ts +1 -0
  59. package/src/ConsoleShared/src/components/index.ts +7 -0
  60. package/src/ConsoleShared/src/components/layout/PageLayout.scss +29 -0
  61. package/src/ConsoleShared/src/components/markdown-extensions/MarkdownCopyClipboard.tsx +93 -0
  62. package/src/ConsoleShared/src/components/markdown-extensions/__tests__/MarkdownCopyClipboard.spec.tsx +25 -0
  63. package/src/ConsoleShared/src/components/markdown-extensions/__tests__/test-data.ts +5 -0
  64. package/src/ConsoleShared/src/components/markdown-extensions/admonition-extension.tsx +66 -0
  65. package/src/ConsoleShared/src/components/markdown-extensions/code-extension.tsx +25 -0
  66. package/src/ConsoleShared/src/components/markdown-extensions/const.ts +3 -0
  67. package/src/ConsoleShared/src/components/markdown-extensions/index.ts +5 -0
  68. package/src/ConsoleShared/src/components/markdown-extensions/inline-clipboard-extension.tsx +45 -0
  69. package/src/ConsoleShared/src/components/markdown-extensions/multiline-clipboard-extension.tsx +50 -0
  70. package/src/ConsoleShared/src/components/markdown-extensions/showdown-extension.scss +52 -0
  71. package/src/ConsoleShared/src/components/markdown-extensions/utils.ts +3 -0
  72. package/src/ConsoleShared/src/components/markdown-highlight-extension/MarkdownHighlightExtension.tsx +64 -0
  73. package/src/ConsoleShared/src/components/markdown-highlight-extension/highlight-consts.ts +9 -0
  74. package/src/ConsoleShared/src/components/markdown-highlight-extension/index.ts +1 -0
  75. package/src/ConsoleShared/src/components/modal/Modal.scss +3 -0
  76. package/src/ConsoleShared/src/components/modal/Modal.tsx +19 -0
  77. package/src/ConsoleShared/src/components/modal/index.ts +1 -0
  78. package/src/ConsoleShared/src/components/popper/Portal.tsx +23 -0
  79. package/src/ConsoleShared/src/components/popper/SimplePopper.tsx +90 -0
  80. package/src/ConsoleShared/src/components/popper/index.ts +2 -0
  81. package/src/ConsoleShared/src/components/spotlight/InteractiveSpotlight.tsx +58 -0
  82. package/src/ConsoleShared/src/components/spotlight/Spotlight.tsx +35 -0
  83. package/src/ConsoleShared/src/components/spotlight/StaticSpotlight.tsx +32 -0
  84. package/src/ConsoleShared/src/components/spotlight/index.ts +1 -0
  85. package/src/ConsoleShared/src/components/spotlight/spotlight.scss +63 -0
  86. package/src/ConsoleShared/src/components/status/GenericStatus.tsx +33 -0
  87. package/src/ConsoleShared/src/components/status/NotStartedIcon.tsx +27 -0
  88. package/src/ConsoleShared/src/components/status/PopoverStatus.tsx +42 -0
  89. package/src/ConsoleShared/src/components/status/Status.tsx +38 -0
  90. package/src/ConsoleShared/src/components/status/StatusIconAndText.tsx +42 -0
  91. package/src/ConsoleShared/src/components/status/icons.tsx +77 -0
  92. package/src/ConsoleShared/src/components/status/index.tsx +1 -0
  93. package/src/ConsoleShared/src/components/status/statuses.tsx +36 -0
  94. package/src/ConsoleShared/src/components/status/types.ts +7 -0
  95. package/src/ConsoleShared/src/components/utils/FallbackImg.tsx +20 -0
  96. package/src/ConsoleShared/src/components/utils/index.ts +1 -0
  97. package/src/ConsoleShared/src/constants/index.ts +1 -0
  98. package/src/ConsoleShared/src/constants/ui.ts +1 -0
  99. package/src/ConsoleShared/src/hooks/index.ts +6 -0
  100. package/src/ConsoleShared/src/hooks/scroll.ts +52 -0
  101. package/src/ConsoleShared/src/hooks/useBoundingClientRect.ts +18 -0
  102. package/src/ConsoleShared/src/hooks/useEventListener.ts +14 -0
  103. package/src/ConsoleShared/src/hooks/useForceRender.ts +6 -0
  104. package/src/ConsoleShared/src/hooks/useResizeObserver.ts +20 -0
  105. package/src/ConsoleShared/src/hooks/useScrollShadows.ts +45 -0
  106. package/src/ConsoleShared/src/index.ts +4 -0
  107. package/src/ConsoleShared/src/utils/index.ts +1 -0
  108. package/src/ConsoleShared/src/utils/useCombineRefs.ts +17 -0
  109. package/src/HelpTopicDrawer.tsx +124 -0
  110. package/src/HelpTopicPanelContent.tsx +152 -0
  111. package/src/QuickStartCatalogPage.tsx +190 -0
  112. package/src/QuickStartCloseModal.tsx +47 -0
  113. package/src/QuickStartController.tsx +113 -0
  114. package/src/QuickStartDrawer.scss +11 -0
  115. package/src/QuickStartDrawer.tsx +265 -0
  116. package/src/QuickStartMarkdownView.tsx +75 -0
  117. package/src/QuickStartPanelContent.scss +46 -0
  118. package/src/QuickStartPanelContent.tsx +153 -0
  119. package/src/__tests__/quick-start-utils.spec.tsx +16 -0
  120. package/src/catalog/Catalog/QuickStartCatalogHeader.tsx +18 -0
  121. package/src/catalog/Catalog/QuickStartCatalogSection.tsx +9 -0
  122. package/src/catalog/Catalog/QuickStartCatalogToolbar.tsx +12 -0
  123. package/src/catalog/Catalog/index.ts +3 -0
  124. package/src/catalog/QuickStartCatalog.scss +8 -0
  125. package/src/catalog/QuickStartCatalog.tsx +42 -0
  126. package/src/catalog/QuickStartTile.scss +11 -0
  127. package/src/catalog/QuickStartTile.tsx +105 -0
  128. package/src/catalog/QuickStartTileDescription.scss +29 -0
  129. package/src/catalog/QuickStartTileDescription.tsx +79 -0
  130. package/src/catalog/QuickStartTileFooter.tsx +101 -0
  131. package/src/catalog/QuickStartTileFooterExternal.tsx +40 -0
  132. package/src/catalog/QuickStartTileHeader.scss +12 -0
  133. package/src/catalog/QuickStartTileHeader.tsx +77 -0
  134. package/src/catalog/Toolbar/QuickStartCatalogFilter.scss +25 -0
  135. package/src/catalog/Toolbar/QuickStartCatalogFilter.tsx +34 -0
  136. package/src/catalog/Toolbar/QuickStartCatalogFilterItems.tsx +199 -0
  137. package/src/catalog/__tests__/QuickStartCatalog.spec.tsx +35 -0
  138. package/src/catalog/__tests__/QuickStartTile.spec.tsx +38 -0
  139. package/src/catalog/__tests__/QuickStartTileDescription.spec.tsx +44 -0
  140. package/src/catalog/index.ts +9 -0
  141. package/src/controller/QuickStartConclusion.tsx +63 -0
  142. package/src/controller/QuickStartContent.scss +12 -0
  143. package/src/controller/QuickStartContent.tsx +72 -0
  144. package/src/controller/QuickStartFooter.scss +13 -0
  145. package/src/controller/QuickStartFooter.tsx +128 -0
  146. package/src/controller/QuickStartIntroduction.scss +35 -0
  147. package/src/controller/QuickStartIntroduction.tsx +66 -0
  148. package/src/controller/QuickStartTaskHeader.scss +58 -0
  149. package/src/controller/QuickStartTaskHeader.tsx +116 -0
  150. package/src/controller/QuickStartTaskHeaderList.scss +17 -0
  151. package/src/controller/QuickStartTaskHeaderList.tsx +35 -0
  152. package/src/controller/QuickStartTaskReview.scss +30 -0
  153. package/src/controller/QuickStartTaskReview.tsx +81 -0
  154. package/src/controller/QuickStartTasks.scss +89 -0
  155. package/src/controller/QuickStartTasks.tsx +75 -0
  156. package/src/controller/__tests__/QuickStartConclusion.spec.tsx +95 -0
  157. package/src/controller/__tests__/QuickStartContent.spec.tsx +52 -0
  158. package/src/controller/__tests__/QuickStartFooter.spec.tsx +148 -0
  159. package/src/controller/__tests__/QuickStartTaskHeader.spec.tsx +56 -0
  160. package/src/controller/__tests__/QuickStartTaskReview.spec.tsx +45 -0
  161. package/src/controller/__tests__/QuickStartTasks.spec.tsx +81 -0
  162. package/src/data/mocks/json/explore-pipeline-quickstart.ts +66 -0
  163. package/src/data/mocks/json/explore-serverless-quickstart.ts +90 -0
  164. package/src/data/mocks/json/monitor-sampleapp-quickstart.ts +77 -0
  165. package/src/data/mocks/json/tour-icons.ts +3 -0
  166. package/src/data/mocks/yamls/add-healthchecks-quickstart.yaml +67 -0
  167. package/src/data/mocks/yamls/explore-pipeline-quickstart.yaml +57 -0
  168. package/src/data/mocks/yamls/explore-serverless-quickstart.yaml +83 -0
  169. package/src/data/mocks/yamls/install-associate-pipeline-quickstart.yaml +74 -0
  170. package/src/data/mocks/yamls/monitor-sampleapp-quickstart.yaml +66 -0
  171. package/src/data/mocks/yamls/sample-application-quickstart.yaml +97 -0
  172. package/src/data/mocks/yamls/serverless-application-quickstart.yaml +141 -0
  173. package/src/data/quick-start-test-data.ts +10 -0
  174. package/src/data/test-utils.ts +11 -0
  175. package/src/declaration.d.ts +2 -0
  176. package/src/index.ts +17 -0
  177. package/src/locales/en/quickstart.json +46 -0
  178. package/src/styles/_base.scss +54 -0
  179. package/src/styles/_dark-custom-override.scss +62 -0
  180. package/src/styles/legacy-bootstrap/README.md +21 -0
  181. package/src/styles/legacy-bootstrap/_code.scss +44 -0
  182. package/src/styles/legacy-bootstrap/_tables.scss +38 -0
  183. package/src/styles/legacy-bootstrap/_type.scss +90 -0
  184. package/src/styles/legacy-bootstrap/_variables.scss +48 -0
  185. package/src/styles/legacy-bootstrap.scss +5 -0
  186. package/src/styles/patternfly-global-entry.ts +1 -0
  187. package/src/styles/patternfly-global.scss +28 -0
  188. package/src/styles/patternfly-nested-entry.ts +1 -0
  189. package/src/styles/patternfly-nested.scss +18 -0
  190. package/src/styles/quickstarts-standalone-entry.ts +1 -0
  191. package/src/styles/quickstarts-standalone.scss +7 -0
  192. package/src/styles/style.scss +12 -0
  193. package/src/styles/vendor-entry.ts +1 -0
  194. package/src/styles/vendor.scss +7 -0
  195. package/src/utils/PluralResolver.ts +356 -0
  196. package/src/utils/asciidoc-procedure-parser.ts +132 -0
  197. package/src/utils/const.ts +10 -0
  198. package/src/utils/help-topic-context.tsx +74 -0
  199. package/src/utils/help-topic-types.ts +16 -0
  200. package/src/utils/quick-start-context.tsx +477 -0
  201. package/src/utils/quick-start-types.ts +72 -0
  202. package/src/utils/quick-start-utils.ts +92 -0
  203. package/src/utils/useLocalStorage.ts +38 -0
@@ -0,0 +1,52 @@
1
+ .pfext-markdown-view {
2
+ .pfext-code-block__pre {
3
+ /* override the styles applied by showdown while parsing <pre /> */
4
+ display: flex;
5
+ border: none;
6
+ border-radius: none;
7
+ background-color: transparent;
8
+ margin: 0;
9
+ padding: 0;
10
+ }
11
+
12
+ .pfext-markdown-execute-snippet {
13
+
14
+ &__button {
15
+ & > i.fa-check {
16
+ display: none;
17
+ }
18
+
19
+ & > i.fa-play {
20
+ display: inline;
21
+ }
22
+
23
+ &[data-executed] {
24
+ & > i.fa-check {
25
+ display: inline;
26
+ }
27
+
28
+ & > i.fa-play {
29
+ display: none;
30
+ }
31
+ }
32
+ }
33
+ }
34
+
35
+ .pfext-markdown-admonition {
36
+ &.pf-c-alert {
37
+ // add margins to match design
38
+ margin: var(--pf-global--spacer--md) 0;
39
+ .pf-c-alert__title {
40
+ // remove margins from markdown css
41
+ margin-top: 0;
42
+ margin-bottom: 0;
43
+ // lift PF style specificity to override markdown css
44
+ font-weight: var(--pf-c-alert__title--FontWeight);
45
+ font-family: inherit;
46
+ line-height: inherit;
47
+ color: var(--pf-c-alert__title--Color);
48
+ word-break: break-word;
49
+ }
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,3 @@
1
+ export const removeTemplateWhitespace = (template: string): string => {
2
+ return template.replace(/>(?:\s|\n)+</g, '><');
3
+ };
@@ -0,0 +1,64 @@
1
+ import * as React from 'react';
2
+ import { Spotlight } from '../spotlight';
3
+
4
+ type MarkdownHighlightExtensionProps = {
5
+ docContext: HTMLDocument;
6
+ rootSelector: string;
7
+ };
8
+ const MarkdownHighlightExtension: React.FC<MarkdownHighlightExtensionProps> = ({
9
+ docContext,
10
+ rootSelector,
11
+ }) => {
12
+ const [selector, setSelector] = React.useState<string>(null);
13
+ React.useEffect(() => {
14
+ const elements = docContext.querySelectorAll(`${rootSelector} [data-highlight]`);
15
+ let timeoutId: NodeJS.Timeout;
16
+ function startHighlight(e) {
17
+ const highlightId = e.target.getAttribute('data-highlight');
18
+ if (!highlightId) {
19
+ return;
20
+ }
21
+ setSelector(null);
22
+ timeoutId = setTimeout(() => {
23
+ setSelector(`[data-quickstart-id="${highlightId}"]`);
24
+ }, 0);
25
+ }
26
+ elements && elements.forEach((elm) => elm.addEventListener('click', startHighlight));
27
+ return () => {
28
+ clearTimeout(timeoutId);
29
+ elements && elements.forEach((elm) => elm.removeEventListener('click', startHighlight));
30
+ };
31
+ }, [docContext, rootSelector]);
32
+ React.useEffect(() => {
33
+ const elements = docContext.querySelectorAll(`${rootSelector} [class^=data-highlight__]`);
34
+ let timeoutId: NodeJS.Timeout;
35
+ function startHighlight(e) {
36
+ e.preventDefault();
37
+ const classes = e.target.getAttribute('class').split(' ');
38
+ let highlightId;
39
+ for (let i = 0; i < classes.length; i++) {
40
+ if (classes[0].startsWith('data-highlight__')) {
41
+ highlightId = classes[0].split('__')[1];
42
+ break;
43
+ }
44
+ }
45
+ if (!highlightId) {
46
+ return;
47
+ }
48
+ setSelector(null);
49
+ timeoutId = setTimeout(() => {
50
+ setSelector(`[data-quickstart-id="${highlightId}"]`);
51
+ }, 0);
52
+ }
53
+ elements && elements.forEach((elm) => elm.addEventListener('click', startHighlight));
54
+ return () => {
55
+ clearTimeout(timeoutId);
56
+ elements && elements.forEach((elm) => elm.removeEventListener('click', startHighlight));
57
+ };
58
+ }, [docContext, rootSelector]);
59
+ if (!selector) {
60
+ return null;
61
+ }
62
+ return <Spotlight selector={selector} interactive />;
63
+ };
64
+ export default MarkdownHighlightExtension;
@@ -0,0 +1,9 @@
1
+ export const LINK_LABEL = '[\\d\\w\\s-()$!]+';
2
+ export const HIGHLIGHT_ACTIONS = ['highlight'];
3
+ export const SELECTOR_ID = `[\\w-]+`;
4
+
5
+ // [linkLabel]{{action id}}
6
+ export const HIGHLIGHT_REGEXP = new RegExp(
7
+ `\\[(${LINK_LABEL})]{{(${HIGHLIGHT_ACTIONS.join('|')}) (${SELECTOR_ID})}}`,
8
+ 'g',
9
+ );
@@ -0,0 +1 @@
1
+ export { default as MarkdownHighlightExtension } from './MarkdownHighlightExtension';
@@ -0,0 +1,3 @@
1
+ .pfext-modal {
2
+ position: absolute !important;
3
+ }
@@ -0,0 +1,19 @@
1
+ import './Modal.scss';
2
+ import * as React from 'react';
3
+ import { Modal as PfModal, ModalProps as PfModalProps } from '@patternfly/react-core';
4
+ import { css } from '@patternfly/react-styles';
5
+
6
+ type ModalProps = {
7
+ isFullScreen?: boolean;
8
+ ref?: React.LegacyRef<PfModal>;
9
+ } & PfModalProps;
10
+
11
+ const Modal: React.FC<ModalProps> = ({ isFullScreen = false, className, ...props }) => (
12
+ <PfModal
13
+ {...props}
14
+ className={css('pfext-modal', className)}
15
+ appendTo={() => (isFullScreen ? document.body : document.querySelector('#modal-container'))}
16
+ />
17
+ );
18
+
19
+ export default Modal;
@@ -0,0 +1 @@
1
+ export { default as Modal } from './Modal';
@@ -0,0 +1,23 @@
1
+ import * as React from 'react';
2
+ import * as ReactDOM from 'react-dom';
3
+
4
+ type GetContainer = Element | null | undefined | (() => Element);
5
+
6
+ type PortalProps = {
7
+ container?: GetContainer;
8
+ };
9
+
10
+ const getContainer = (container: GetContainer): Element | null | undefined =>
11
+ typeof container === 'function' ? container() : container;
12
+
13
+ const Portal: React.FC<PortalProps> = ({ children, container }) => {
14
+ const [containerNode, setContainerNode] = React.useState<Element>();
15
+
16
+ React.useLayoutEffect(() => {
17
+ setContainerNode(getContainer(container) || document.body);
18
+ }, [container]);
19
+
20
+ return containerNode ? ReactDOM.createPortal(children, containerNode) : null;
21
+ };
22
+
23
+ export default Portal;
@@ -0,0 +1,90 @@
1
+ import * as React from 'react';
2
+ import Portal from './Portal';
3
+
4
+ const SimplePopper: React.FC = ({ children }) => {
5
+ const openProp = true;
6
+ const nodeRef = React.useRef<Element>();
7
+ const popperRef = React.useRef(null);
8
+ const [isOpen, setOpenState] = React.useState(openProp);
9
+
10
+ const setOpen = React.useCallback((newOpen: boolean) => {
11
+ setOpenState(newOpen);
12
+ }, []);
13
+
14
+ React.useEffect(() => {
15
+ setOpen(openProp);
16
+ }, [openProp, setOpen]);
17
+
18
+ const onKeyDown = React.useCallback(
19
+ (e: KeyboardEvent) => {
20
+ if (e.keyCode === 27) {
21
+ setOpen(false);
22
+ }
23
+ },
24
+ [setOpen],
25
+ );
26
+
27
+ const onClickOutside = React.useCallback(
28
+ (e: MouseEvent) => {
29
+ if (!nodeRef.current || (e.target instanceof Node && !nodeRef.current.contains(e.target))) {
30
+ setOpen(false);
31
+ }
32
+ },
33
+ [setOpen],
34
+ );
35
+
36
+ const destroy = React.useCallback(() => {
37
+ if (popperRef.current) {
38
+ popperRef.current.destroy();
39
+ document.removeEventListener('keydown', onKeyDown, true);
40
+ document.removeEventListener('mousedown', onClickOutside, true);
41
+ document.removeEventListener('touchstart', onClickOutside, true);
42
+ }
43
+ }, [onClickOutside, onKeyDown]);
44
+
45
+ const initialize = React.useCallback(() => {
46
+ if (!nodeRef.current || !isOpen) {
47
+ return;
48
+ }
49
+
50
+ destroy();
51
+ }, [isOpen, destroy]);
52
+
53
+ const nodeRefCallback = React.useCallback(
54
+ (node) => {
55
+ nodeRef.current = node;
56
+ initialize();
57
+ },
58
+ [initialize],
59
+ );
60
+
61
+ React.useEffect(() => {
62
+ initialize();
63
+ }, [initialize]);
64
+
65
+ React.useEffect(() => {
66
+ return () => {
67
+ destroy();
68
+ };
69
+ }, [destroy]);
70
+
71
+ React.useEffect(() => {
72
+ if (!isOpen) {
73
+ destroy();
74
+ }
75
+ }, [destroy, isOpen]);
76
+
77
+ return isOpen ? (
78
+ <Portal>
79
+ <div
80
+ ref={nodeRefCallback}
81
+ style={{ zIndex: 9999, position: 'absolute', top: 0, left: 0 }}
82
+ className="pfext-quick-start__base"
83
+ >
84
+ {children}
85
+ </div>
86
+ </Portal>
87
+ ) : null;
88
+ };
89
+
90
+ export default SimplePopper;
@@ -0,0 +1,2 @@
1
+ export { default as SimplePopper } from './SimplePopper';
2
+ export { default as Portal } from './Portal';
@@ -0,0 +1,58 @@
1
+ import './spotlight.scss';
2
+ import * as React from 'react';
3
+ import { Portal, SimplePopper } from '../popper';
4
+
5
+ type InteractiveSpotlightProps = {
6
+ element: Element;
7
+ };
8
+
9
+ const isInViewport = (elementToCheck: Element) => {
10
+ const rect = elementToCheck.getBoundingClientRect();
11
+ return (
12
+ rect.top >= 0 &&
13
+ rect.left >= 0 &&
14
+ rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
15
+ rect.right <= (window.innerWidth || document.documentElement.clientWidth)
16
+ );
17
+ };
18
+
19
+ const InteractiveSpotlight: React.FC<InteractiveSpotlightProps> = ({ element }) => {
20
+ const { top, bottom, left, right, height, width } = element.getBoundingClientRect();
21
+ const style: React.CSSProperties = {
22
+ height,
23
+ width,
24
+ top,
25
+ left,
26
+ bottom,
27
+ right,
28
+ };
29
+ const [clicked, setClicked] = React.useState(false);
30
+
31
+ React.useEffect(() => {
32
+ if (!clicked) {
33
+ if (!isInViewport(element)) {
34
+ element.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
35
+ }
36
+ const handleClick = () => setClicked(true);
37
+ document.addEventListener('click', handleClick);
38
+ return () => {
39
+ document.removeEventListener('click', handleClick);
40
+ };
41
+ }
42
+ return () => {};
43
+ }, [element, clicked]);
44
+
45
+ if (clicked) {
46
+ return null;
47
+ }
48
+
49
+ return (
50
+ <Portal>
51
+ <SimplePopper>
52
+ <div className="pfext-spotlight pfext-spotlight__element-highlight-animate" style={style} />
53
+ </SimplePopper>
54
+ </Portal>
55
+ );
56
+ };
57
+
58
+ export default InteractiveSpotlight;
@@ -0,0 +1,35 @@
1
+ import * as React from 'react';
2
+ import InteractiveSpotlight from './InteractiveSpotlight';
3
+ import StaticSpotlight from './StaticSpotlight';
4
+
5
+ type SpotlightProps = {
6
+ selector: string;
7
+ interactive?: boolean;
8
+ };
9
+
10
+ const Spotlight: React.FC<SpotlightProps> = ({ selector, interactive }) => {
11
+ // if target element is a hidden one return null
12
+ const element = React.useMemo(() => {
13
+ const highlightElement = document.querySelector(selector);
14
+ let hiddenElement = highlightElement;
15
+ while (hiddenElement) {
16
+ const ariaHidden = hiddenElement.getAttribute('aria-hidden');
17
+ if (ariaHidden === 'true') {
18
+ return null;
19
+ }
20
+ hiddenElement = hiddenElement.parentElement;
21
+ }
22
+ return highlightElement;
23
+ }, [selector]);
24
+
25
+ if (!element) {
26
+ return null;
27
+ }
28
+ return interactive ? (
29
+ <InteractiveSpotlight element={element} />
30
+ ) : (
31
+ <StaticSpotlight element={element} />
32
+ );
33
+ };
34
+
35
+ export default Spotlight;
@@ -0,0 +1,32 @@
1
+ import './spotlight.scss';
2
+ import * as React from 'react';
3
+ import { useBoundingClientRect } from '../../hooks';
4
+ import Portal from '../popper/Portal';
5
+
6
+ type StaticSpotlightProps = {
7
+ element: Element;
8
+ };
9
+
10
+ const StaticSpotlight: React.FC<StaticSpotlightProps> = ({ element }) => {
11
+ const clientRect = useBoundingClientRect(element as HTMLElement);
12
+ const style: React.CSSProperties = clientRect
13
+ ? {
14
+ top: clientRect.top,
15
+ left: clientRect.left,
16
+ height: clientRect.height,
17
+ width: clientRect.width,
18
+ }
19
+ : {};
20
+ return clientRect ? (
21
+ <Portal>
22
+ <div className="pf-c-backdrop pfext-spotlight__with-backdrop">
23
+ <div
24
+ className="pfext-spotlight pfext-spotlight__element-highlight-noanimate"
25
+ style={style}
26
+ />
27
+ </div>
28
+ </Portal>
29
+ ) : null;
30
+ };
31
+
32
+ export default StaticSpotlight;
@@ -0,0 +1 @@
1
+ export { default as Spotlight } from './Spotlight';
@@ -0,0 +1,63 @@
1
+ @keyframes pfext-spotlight-expand {
2
+ 0% {
3
+ outline-offset: -4px;
4
+ outline-width: 4px;
5
+ opacity: 1;
6
+ }
7
+ 100% {
8
+ outline-offset: 21px;
9
+ outline-width: 12px;
10
+ opacity: 0;
11
+ }
12
+ }
13
+
14
+ @keyframes pfext-spotlight-fade-in {
15
+ 0% {
16
+ opacity: 0;
17
+ }
18
+ 100% {
19
+ opacity: 1;
20
+ }
21
+ }
22
+
23
+ @keyframes pfext-spotlight-fade-out {
24
+ 0% {
25
+ opacity: 1;
26
+ }
27
+ 100% {
28
+ opacity: 0;
29
+ }
30
+ }
31
+
32
+ .pfext-spotlight {
33
+ pointer-events: none;
34
+ position: absolute;
35
+ &__with-backdrop {
36
+ mix-blend-mode: hard-light;
37
+ }
38
+ &__element-highlight-noanimate {
39
+ border: var(--pf-global--BorderWidth--xl) solid var(--pf-global--palette--blue-200);
40
+ background-color: var(--pf-global--palette--black-500);
41
+ z-index: 9999;
42
+ }
43
+ &__element-highlight-animate {
44
+ pointer-events: none;
45
+ position: absolute;
46
+ box-shadow: inset 0px 0px 0px 4px var(--pf-global--palette--blue-200);
47
+ opacity: 0;
48
+ animation: 0.4s pfext-spotlight-fade-in 0s ease-in-out, 5s pfext-spotlight-fade-out 12.8s ease-in-out;
49
+ animation-fill-mode: forwards;
50
+ &::after {
51
+ content: '';
52
+ position: absolute;
53
+ left: 0;
54
+ right: 0;
55
+ top: 0;
56
+ bottom: 0;
57
+ animation: 1.2s pfext-spotlight-expand 1.6s ease-out;
58
+ animation-fill-mode: forwards;
59
+ outline: 4px solid var(--pf-global--palette--blue-200);
60
+ outline-offset: -4px;
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,33 @@
1
+ import * as React from 'react';
2
+ import PopoverStatus from './PopoverStatus';
3
+ import StatusIconAndText from './StatusIconAndText';
4
+ import { StatusComponentProps } from './types';
5
+
6
+ const GenericStatus: React.FC<GenericStatusProps> = (props) => {
7
+ const { Icon, children, popoverTitle, title, noTooltip, iconOnly, ...restProps } = props;
8
+ const renderIcon = iconOnly && !noTooltip ? <Icon title={title} /> : <Icon />;
9
+ const statusBody = (
10
+ <StatusIconAndText
11
+ {...restProps}
12
+ noTooltip={noTooltip}
13
+ title={title}
14
+ iconOnly={iconOnly}
15
+ icon={renderIcon}
16
+ />
17
+ );
18
+ return React.Children.toArray(children).length ? (
19
+ <PopoverStatus title={popoverTitle || title} {...restProps} statusBody={statusBody}>
20
+ {children}
21
+ </PopoverStatus>
22
+ ) : (
23
+ statusBody
24
+ );
25
+ };
26
+
27
+ type GenericStatusProps = StatusComponentProps & {
28
+ Icon: React.ComponentType<{ title?: string }>;
29
+ popoverTitle?: string;
30
+ noTooltip?: boolean;
31
+ };
32
+
33
+ export default GenericStatus;
@@ -0,0 +1,27 @@
1
+ // TODO: Pull from Patternfly when they add it
2
+ // https://github.com/patternfly/patternfly-design/issues/921#issuecomment-726183814
3
+ import * as React from 'react';
4
+
5
+ export default (props) => (
6
+ <svg
7
+ width="12px"
8
+ height="13px"
9
+ {...props}
10
+ viewBox="0 0 12 13"
11
+ version="1.1"
12
+ xmlns="http://www.w3.org/2000/svg"
13
+ xmlnsXlink="http://www.w3.org/1999/xlink"
14
+ >
15
+ <g id="icon_notstarted" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
16
+ <path
17
+ d="M5.99998569,12.3124969 C7.04685832,12.3124969 8.01560589,12.0507786 8.90622877,11.5273425 C9.79685164,11.0039064 10.5038813,10.2968767 11.0273175,9.4062538 C11.5507536,8.51563092 11.8124718,7.54688335 11.8124718,6.50001073 C11.8124718,5.45313811 11.5507536,4.48439053 11.0273175,3.59376766 C10.5038813,2.70314478 9.79685164,1.9961151 8.90622877,1.47267896 C8.01560589,0.949242832 7.04685832,0.687524587 5.99998569,0.687524587 C4.95311307,0.687524587 3.9843655,0.949242832 3.09374262,1.47267896 C2.20311975,1.9961151 1.49609006,2.70314478 0.972653931,3.59376766 C0.449217798,4.48439053 0.187499553,5.45313811 0.187499553,6.50001073 C0.187499553,7.54688335 0.449217798,8.51563092 0.972653931,9.4062538 C1.49609006,10.2968767 2.20311975,11.0039064 3.09374262,11.5273425 C3.9843655,12.0507786 4.95311307,12.3124969 5.99998569,12.3124969 Z M5.99998569,11.1874996 C5.15623771,11.1874996 4.37498969,10.9765626 3.65624128,10.5546886 C2.93749288,10.1328146 2.36718186,9.56250355 1.94530786,8.84375514 C1.52343387,8.12500674 1.31249687,7.34375872 1.31249687,6.50001073 C1.31249687,5.65626274 1.52343387,4.87501472 1.94530786,4.15626632 C2.36718186,3.43751791 2.93749288,2.86720689 3.65624128,2.4453329 C4.37498969,2.0234589 5.15623771,1.8125219 5.99998569,1.8125219 C6.84373368,1.8125219 7.6249817,2.0234589 8.34373011,2.4453329 C9.06247851,2.86720689 9.63278953,3.43751791 10.0546635,4.15626632 C10.4765375,4.87501472 10.6874745,5.65626274 10.6874745,6.50001073 C10.6874745,7.34375872 10.4765375,8.12500674 10.0546635,8.84375514 C9.63278953,9.56250355 9.06247851,10.1328146 8.34373011,10.5546886 C7.6249817,10.9765626 6.84373368,11.1874996 5.99998569,11.1874996 Z"
18
+ id="Circle"
19
+ fill="#6A6E73"
20
+ fillRule="nonzero"
21
+ />
22
+ <circle id="Oval" fill="#6A6E73" cx="3" cy="6.5" r="1" />
23
+ <circle id="Oval-Copy-2" fill="#6A6E73" cx="6" cy="6.5" r="1" />
24
+ <circle id="Oval-Copy-3" fill="#6A6E73" cx="9" cy="6.5" r="1" />
25
+ </g>
26
+ </svg>
27
+ );
@@ -0,0 +1,42 @@
1
+ import * as React from 'react';
2
+ import { Button, Popover, PopoverPosition } from '@patternfly/react-core';
3
+
4
+ const PopoverStatus: React.FC<PopoverStatusProps> = ({
5
+ hideHeader,
6
+ children,
7
+ isVisible = null,
8
+ shouldClose = null,
9
+ statusBody,
10
+ title,
11
+ onHide,
12
+ onShow,
13
+ }) => {
14
+ return (
15
+ <Popover
16
+ position={PopoverPosition.right}
17
+ headerContent={hideHeader ? null : title}
18
+ bodyContent={children}
19
+ aria-label={title}
20
+ onHide={onHide}
21
+ onShow={onShow}
22
+ isVisible={isVisible}
23
+ shouldClose={shouldClose}
24
+ >
25
+ <Button variant="link" isInline>
26
+ {statusBody}
27
+ </Button>
28
+ </Popover>
29
+ );
30
+ };
31
+
32
+ type PopoverStatusProps = {
33
+ statusBody: React.ReactNode;
34
+ onHide?: () => void;
35
+ onShow?: () => void;
36
+ title?: string;
37
+ hideHeader?: boolean;
38
+ isVisible?: boolean;
39
+ shouldClose?: (hideFunction: any) => void;
40
+ };
41
+
42
+ export default PopoverStatus;
@@ -0,0 +1,38 @@
1
+ import * as React from 'react';
2
+ import SyncAltIcon from '@patternfly/react-icons/dist/js/icons/sync-alt-icon';
3
+ import { DASH } from '../../constants';
4
+ import { SuccessStatus } from './statuses';
5
+ import StatusIconAndText from './StatusIconAndText';
6
+ import { StatusComponentProps } from './types';
7
+
8
+ export const Status: React.FC<StatusProps> = ({
9
+ status,
10
+ title,
11
+ iconOnly,
12
+ noTooltip,
13
+ className,
14
+ }) => {
15
+ const statusProps = { title: title || status, iconOnly, noTooltip, className };
16
+ switch (status) {
17
+ case 'In Progress':
18
+ return <StatusIconAndText {...statusProps} icon={<SyncAltIcon />} />;
19
+
20
+ case 'Complete':
21
+ return <SuccessStatus {...statusProps} />;
22
+
23
+ default:
24
+ return <>{status || DASH}</>;
25
+ }
26
+ };
27
+
28
+ export const StatusIcon: React.FC<StatusIconProps> = ({ status }) => (
29
+ <Status status={status} iconOnly />
30
+ );
31
+
32
+ type StatusIconProps = {
33
+ status: string;
34
+ };
35
+
36
+ type StatusProps = StatusComponentProps & {
37
+ status: string;
38
+ };
@@ -0,0 +1,42 @@
1
+ import * as React from 'react';
2
+ import { css } from '@patternfly/react-styles';
3
+ import { CamelCaseWrap } from '@console/internal/components/utils';
4
+ import { DASH } from '../../constants';
5
+ import { StatusComponentProps } from './types';
6
+
7
+ type StatusIconAndTextProps = StatusComponentProps & {
8
+ icon?: React.ReactElement;
9
+ spin?: boolean;
10
+ };
11
+
12
+ const StatusIconAndText: React.FC<StatusIconAndTextProps> = ({
13
+ icon,
14
+ title,
15
+ spin,
16
+ iconOnly,
17
+ noTooltip,
18
+ className,
19
+ }) => {
20
+ if (!title) {
21
+ return <>{DASH}</>;
22
+ }
23
+
24
+ return (
25
+ <span
26
+ className={css('pfext-icon-and-text', className)}
27
+ title={iconOnly && !noTooltip ? title : undefined}
28
+ >
29
+ {icon &&
30
+ React.cloneElement(icon, {
31
+ className: css(
32
+ spin && 'fa-spin',
33
+ icon.props.className,
34
+ !iconOnly && 'pfext-icon-and-text__icon pfext-icon-flex-child',
35
+ ),
36
+ })}
37
+ {!iconOnly && <CamelCaseWrap value={title} dataTest="status-text" />}
38
+ </span>
39
+ );
40
+ };
41
+
42
+ export default StatusIconAndText;