@patternfly/chatbot 2.1.0 → 2.2.0-prerelease.10

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 (177) hide show
  1. package/dist/cjs/Chatbot/Chatbot.js +0 -9
  2. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +5 -1
  3. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +4 -4
  4. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +3 -3
  5. package/dist/cjs/ChatbotHeader/ChatbotHeaderCloseButton.d.ts +17 -0
  6. package/dist/cjs/ChatbotHeader/ChatbotHeaderCloseButton.js +14 -0
  7. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.d.ts +2 -0
  8. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +2 -2
  9. package/dist/cjs/ChatbotHeader/index.d.ts +1 -0
  10. package/dist/cjs/ChatbotHeader/index.js +1 -0
  11. package/dist/cjs/CodeModal/CodeModal.js +2 -12
  12. package/dist/cjs/Message/ListMessage/OrderedListMessage.d.ts +1 -1
  13. package/dist/cjs/Message/ListMessage/OrderedListMessage.js +2 -2
  14. package/dist/cjs/Message/Message.d.ts +16 -6
  15. package/dist/cjs/Message/Message.js +6 -6
  16. package/dist/cjs/Message/Message.test.js +51 -0
  17. package/dist/cjs/Message/QuickResponse/QuickResponse.d.ts +15 -0
  18. package/dist/cjs/Message/QuickResponse/QuickResponse.js +33 -0
  19. package/dist/cjs/Message/QuickStarts/FallbackImg.d.ts +13 -0
  20. package/dist/cjs/Message/QuickStarts/FallbackImg.js +34 -0
  21. package/dist/cjs/Message/QuickStarts/QuickStartTile.d.ts +27 -0
  22. package/dist/cjs/Message/QuickStarts/QuickStartTile.js +82 -0
  23. package/dist/cjs/Message/QuickStarts/QuickStartTileDescription.d.ts +23 -0
  24. package/dist/cjs/Message/QuickStarts/QuickStartTileDescription.js +64 -0
  25. package/dist/cjs/Message/QuickStarts/QuickStartTileDescription.test.d.ts +1 -0
  26. package/dist/cjs/Message/QuickStarts/QuickStartTileDescription.test.js +76 -0
  27. package/dist/cjs/Message/QuickStarts/QuickStartTileHeader.d.ts +11 -0
  28. package/dist/cjs/Message/QuickStarts/QuickStartTileHeader.js +30 -0
  29. package/dist/cjs/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.d.ts +30 -0
  30. package/dist/cjs/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.js +77 -0
  31. package/dist/cjs/Message/QuickStarts/monitor-sampleapp-quickstart.d.ts +30 -0
  32. package/dist/cjs/Message/QuickStarts/monitor-sampleapp-quickstart.js +77 -0
  33. package/dist/cjs/Message/QuickStarts/types.d.ts +132 -0
  34. package/dist/cjs/Message/QuickStarts/types.js +17 -0
  35. package/dist/cjs/MessageBar/SendButton.js +1 -1
  36. package/dist/cjs/ResponseActions/ResponseActionButton.d.ts +6 -0
  37. package/dist/cjs/ResponseActions/ResponseActionButton.js +10 -2
  38. package/dist/cjs/ResponseActions/ResponseActionButton.test.d.ts +1 -0
  39. package/dist/cjs/ResponseActions/ResponseActionButton.test.js +54 -0
  40. package/dist/cjs/ResponseActions/ResponseActions.d.ts +4 -0
  41. package/dist/cjs/ResponseActions/ResponseActions.js +26 -9
  42. package/dist/cjs/ResponseActions/ResponseActions.test.js +79 -5
  43. package/dist/cjs/Settings/SettingsForm.d.ts +13 -0
  44. package/dist/cjs/Settings/SettingsForm.js +27 -0
  45. package/dist/cjs/Settings/index.d.ts +2 -0
  46. package/dist/cjs/Settings/index.js +23 -0
  47. package/dist/cjs/TermsOfUse/TermsOfUse.d.ts +34 -0
  48. package/dist/cjs/TermsOfUse/TermsOfUse.js +49 -0
  49. package/dist/cjs/TermsOfUse/TermsOfUse.test.d.ts +1 -0
  50. package/dist/cjs/TermsOfUse/TermsOfUse.test.js +79 -0
  51. package/dist/cjs/TermsOfUse/index.d.ts +2 -0
  52. package/dist/cjs/TermsOfUse/index.js +23 -0
  53. package/dist/cjs/index.d.ts +4 -0
  54. package/dist/cjs/index.js +7 -1
  55. package/dist/css/main.css +191 -30
  56. package/dist/css/main.css.map +1 -1
  57. package/dist/dynamic/Settings/package.json +1 -0
  58. package/dist/dynamic/TermsOfUse/package.json +1 -0
  59. package/dist/esm/Chatbot/Chatbot.js +0 -9
  60. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +5 -1
  61. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +4 -4
  62. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +3 -3
  63. package/dist/esm/ChatbotHeader/ChatbotHeaderCloseButton.d.ts +17 -0
  64. package/dist/esm/ChatbotHeader/ChatbotHeaderCloseButton.js +8 -0
  65. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.d.ts +2 -0
  66. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +2 -2
  67. package/dist/esm/ChatbotHeader/index.d.ts +1 -0
  68. package/dist/esm/ChatbotHeader/index.js +1 -0
  69. package/dist/esm/CodeModal/CodeModal.js +2 -12
  70. package/dist/esm/Message/ListMessage/OrderedListMessage.d.ts +1 -1
  71. package/dist/esm/Message/ListMessage/OrderedListMessage.js +2 -2
  72. package/dist/esm/Message/Message.d.ts +16 -6
  73. package/dist/esm/Message/Message.js +7 -7
  74. package/dist/esm/Message/Message.test.js +51 -0
  75. package/dist/esm/Message/QuickResponse/QuickResponse.d.ts +15 -0
  76. package/dist/esm/Message/QuickResponse/QuickResponse.js +26 -0
  77. package/dist/esm/Message/QuickStarts/FallbackImg.d.ts +13 -0
  78. package/dist/esm/Message/QuickStarts/FallbackImg.js +9 -0
  79. package/dist/esm/Message/QuickStarts/QuickStartTile.d.ts +27 -0
  80. package/dist/esm/Message/QuickStarts/QuickStartTile.js +52 -0
  81. package/dist/esm/Message/QuickStarts/QuickStartTileDescription.d.ts +23 -0
  82. package/dist/esm/Message/QuickStarts/QuickStartTileDescription.js +35 -0
  83. package/dist/esm/Message/QuickStarts/QuickStartTileDescription.test.d.ts +1 -0
  84. package/dist/esm/Message/QuickStarts/QuickStartTileDescription.test.js +48 -0
  85. package/dist/esm/Message/QuickStarts/QuickStartTileHeader.d.ts +11 -0
  86. package/dist/esm/Message/QuickStarts/QuickStartTileHeader.js +5 -0
  87. package/dist/esm/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.d.ts +30 -0
  88. package/dist/esm/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.js +74 -0
  89. package/dist/esm/Message/QuickStarts/monitor-sampleapp-quickstart.d.ts +30 -0
  90. package/dist/esm/Message/QuickStarts/monitor-sampleapp-quickstart.js +74 -0
  91. package/dist/esm/Message/QuickStarts/types.d.ts +132 -0
  92. package/dist/esm/Message/QuickStarts/types.js +14 -0
  93. package/dist/esm/MessageBar/SendButton.js +1 -1
  94. package/dist/esm/ResponseActions/ResponseActionButton.d.ts +6 -0
  95. package/dist/esm/ResponseActions/ResponseActionButton.js +10 -2
  96. package/dist/esm/ResponseActions/ResponseActionButton.test.d.ts +1 -0
  97. package/dist/esm/ResponseActions/ResponseActionButton.test.js +49 -0
  98. package/dist/esm/ResponseActions/ResponseActions.d.ts +4 -0
  99. package/dist/esm/ResponseActions/ResponseActions.js +26 -9
  100. package/dist/esm/ResponseActions/ResponseActions.test.js +79 -5
  101. package/dist/esm/Settings/SettingsForm.d.ts +13 -0
  102. package/dist/esm/Settings/SettingsForm.js +20 -0
  103. package/dist/esm/Settings/index.d.ts +2 -0
  104. package/dist/esm/Settings/index.js +2 -0
  105. package/dist/esm/TermsOfUse/TermsOfUse.d.ts +34 -0
  106. package/dist/esm/TermsOfUse/TermsOfUse.js +42 -0
  107. package/dist/esm/TermsOfUse/TermsOfUse.test.d.ts +1 -0
  108. package/dist/esm/TermsOfUse/TermsOfUse.test.js +74 -0
  109. package/dist/esm/TermsOfUse/index.d.ts +2 -0
  110. package/dist/esm/TermsOfUse/index.js +2 -0
  111. package/dist/esm/index.d.ts +4 -0
  112. package/dist/esm/index.js +4 -0
  113. package/dist/tsconfig.tsbuildinfo +1 -1
  114. package/package.json +7 -13
  115. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithCustomResponseActions.tsx +4 -0
  116. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithQuickStart.tsx +31 -0
  117. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +26 -4
  118. package/patternfly-docs/content/extensions/chatbot/examples/Messages/explore-pipeline-quickstart.ts +65 -0
  119. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotFooter.tsx +1 -1
  120. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotFootnote.tsx +2 -2
  121. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawer.tsx +2 -2
  122. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerNavigation.tsx +67 -0
  123. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithSelection.tsx +78 -0
  124. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarDisabled.tsx +26 -0
  125. package/patternfly-docs/content/extensions/chatbot/examples/UI/PF-TermsAndConditionsHeader.svg +148 -0
  126. package/patternfly-docs/content/extensions/chatbot/examples/UI/Settings.tsx +289 -0
  127. package/patternfly-docs/content/extensions/chatbot/examples/UI/SquareChatbotToggle.tsx +1 -1
  128. package/patternfly-docs/content/extensions/chatbot/examples/UI/TermsOfUse.tsx +147 -0
  129. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +56 -0
  130. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +2 -2
  131. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.tsx +2 -2
  132. package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotAttachment.tsx +20 -19
  133. package/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotAttachmentMenu.tsx +1 -1
  134. package/patternfly-docs/content/extensions/chatbot/examples/demos/EmbeddedChatbot.tsx +2 -2
  135. package/src/Chatbot/Chatbot.scss +0 -10
  136. package/src/Chatbot/Chatbot.tsx +0 -9
  137. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +14 -0
  138. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +3 -3
  139. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +11 -3
  140. package/src/ChatbotFooter/ChatbotFooter.scss +2 -1
  141. package/src/ChatbotHeader/ChatbotHeaderCloseButton.tsx +51 -0
  142. package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +5 -2
  143. package/src/ChatbotHeader/index.ts +1 -0
  144. package/src/CodeModal/CodeModal.scss +8 -0
  145. package/src/CodeModal/CodeModal.tsx +2 -13
  146. package/src/FileDropZone/__snapshots__/FileDropZone.test.tsx.snap +1 -1
  147. package/src/Message/ListMessage/OrderedListMessage.tsx +2 -2
  148. package/src/Message/Message.scss +0 -14
  149. package/src/Message/Message.test.tsx +76 -0
  150. package/src/Message/Message.tsx +35 -26
  151. package/src/Message/QuickResponse/QuickResponse.scss +33 -0
  152. package/src/Message/QuickResponse/QuickResponse.tsx +50 -0
  153. package/src/Message/QuickStarts/FallbackImg.tsx +24 -0
  154. package/src/Message/QuickStarts/QuickStartTile.scss +25 -0
  155. package/src/Message/QuickStarts/QuickStartTile.tsx +147 -0
  156. package/src/Message/QuickStarts/QuickStartTileDescription.test.tsx +57 -0
  157. package/src/Message/QuickStarts/QuickStartTileDescription.tsx +81 -0
  158. package/src/Message/QuickStarts/QuickStartTileHeader.tsx +21 -0
  159. package/src/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.ts +75 -0
  160. package/src/Message/QuickStarts/monitor-sampleapp-quickstart.ts +75 -0
  161. package/src/Message/QuickStarts/types.ts +154 -0
  162. package/src/MessageBar/SendButton.scss +24 -0
  163. package/src/MessageBar/SendButton.tsx +1 -1
  164. package/src/ResponseActions/ResponseActionButton.test.tsx +52 -0
  165. package/src/ResponseActions/ResponseActionButton.tsx +46 -27
  166. package/src/ResponseActions/ResponseActions.scss +10 -8
  167. package/src/ResponseActions/ResponseActions.test.tsx +103 -5
  168. package/src/ResponseActions/ResponseActions.tsx +54 -7
  169. package/src/Settings/Settings.scss +34 -0
  170. package/src/Settings/SettingsForm.tsx +25 -0
  171. package/src/Settings/index.ts +3 -0
  172. package/src/TermsOfUse/TermsOfUse.scss +66 -0
  173. package/src/TermsOfUse/TermsOfUse.test.tsx +138 -0
  174. package/src/TermsOfUse/TermsOfUse.tsx +117 -0
  175. package/src/TermsOfUse/index.ts +3 -0
  176. package/src/index.ts +6 -0
  177. package/src/main.scss +7 -3
@@ -12,6 +12,8 @@ import { TooltipProps } from '@patternfly/react-core';
12
12
  export interface ActionProps {
13
13
  /** Aria-label for the button */
14
14
  ariaLabel?: string;
15
+ /** Aria-label for the button, shown when the button is clicked. */
16
+ clickedAriaLabel?: string;
15
17
  /** On-click handler for the button */
16
18
  onClick?: ((event: MouseEvent | React.MouseEvent<Element, MouseEvent> | KeyboardEvent) => void) | undefined;
17
19
  /** Class name for the button */
@@ -20,6 +22,8 @@ export interface ActionProps {
20
22
  isDisabled?: boolean;
21
23
  /** Content shown in the tooltip */
22
24
  tooltipContent?: string;
25
+ /** Content shown in the tooltip when the button is clicked. */
26
+ clickedTooltipContent?: string;
23
27
  /** Props to control the PF Tooltip component */
24
28
  tooltipProps?: TooltipProps;
25
29
  /** Icon for custom response action */
@@ -38,74 +42,117 @@ export interface ResponseActionProps {
38
42
  }
39
43
 
40
44
  export const ResponseActions: React.FunctionComponent<ResponseActionProps> = ({ actions }) => {
45
+ const [activeButton, setActiveButton] = React.useState<string>();
41
46
  const { positive, negative, copy, share, listen, ...additionalActions } = actions;
47
+ const responseActions = React.useRef<HTMLDivElement>(null);
48
+
49
+ React.useEffect(() => {
50
+ const handleClickOutside = (e) => {
51
+ if (responseActions.current && !responseActions.current.contains(e.target)) {
52
+ setActiveButton(undefined);
53
+ }
54
+ };
55
+ window.addEventListener('click', handleClickOutside);
56
+
57
+ return () => {
58
+ window.removeEventListener('click', handleClickOutside);
59
+ };
60
+ }, []);
61
+
62
+ const handleClick = (
63
+ e: MouseEvent | React.MouseEvent<Element, MouseEvent> | KeyboardEvent,
64
+ id: string,
65
+ onClick?: (event: MouseEvent | React.MouseEvent<Element, MouseEvent> | KeyboardEvent) => void
66
+ ) => {
67
+ setActiveButton(id);
68
+ onClick && onClick(e);
69
+ };
70
+
42
71
  return (
43
- <div className="pf-chatbot__response-actions">
72
+ <div ref={responseActions} className="pf-chatbot__response-actions">
44
73
  {positive && (
45
74
  <ResponseActionButton
46
75
  ariaLabel={positive.ariaLabel ?? 'Good response'}
47
- onClick={positive.onClick}
76
+ clickedAriaLabel={positive.ariaLabel ?? 'Response recorded'}
77
+ onClick={(e) => handleClick(e, 'positive', positive.onClick)}
48
78
  className={positive.className}
49
79
  isDisabled={positive.isDisabled}
50
80
  tooltipContent={positive.tooltipContent ?? 'Good response'}
81
+ clickedTooltipContent={positive.clickedTooltipContent ?? 'Response recorded'}
51
82
  tooltipProps={positive.tooltipProps}
52
83
  icon={<OutlinedThumbsUpIcon />}
84
+ isClicked={activeButton === 'positive'}
53
85
  ></ResponseActionButton>
54
86
  )}
55
87
  {negative && (
56
88
  <ResponseActionButton
57
89
  ariaLabel={negative.ariaLabel ?? 'Bad response'}
58
- onClick={negative.onClick}
90
+ clickedAriaLabel={negative.ariaLabel ?? 'Response recorded'}
91
+ onClick={(e) => handleClick(e, 'negative', negative.onClick)}
59
92
  className={negative.className}
60
93
  isDisabled={negative.isDisabled}
61
94
  tooltipContent={negative.tooltipContent ?? 'Bad response'}
95
+ clickedTooltipContent={negative.clickedTooltipContent ?? 'Response recorded'}
62
96
  tooltipProps={negative.tooltipProps}
63
97
  icon={<OutlinedThumbsDownIcon />}
98
+ isClicked={activeButton === 'negative'}
64
99
  ></ResponseActionButton>
65
100
  )}
66
101
  {copy && (
67
102
  <ResponseActionButton
68
103
  ariaLabel={copy.ariaLabel ?? 'Copy'}
69
- onClick={copy.onClick}
104
+ clickedAriaLabel={copy.ariaLabel ?? 'Copied'}
105
+ onClick={(e) => handleClick(e, 'copy', copy.onClick)}
70
106
  className={copy.className}
71
107
  isDisabled={copy.isDisabled}
72
108
  tooltipContent={copy.tooltipContent ?? 'Copy'}
109
+ clickedTooltipContent={copy.clickedTooltipContent ?? 'Copied'}
73
110
  tooltipProps={copy.tooltipProps}
74
111
  icon={<OutlinedCopyIcon />}
112
+ isClicked={activeButton === 'copy'}
75
113
  ></ResponseActionButton>
76
114
  )}
77
115
  {share && (
78
116
  <ResponseActionButton
79
117
  ariaLabel={share.ariaLabel ?? 'Share'}
80
- onClick={share.onClick}
118
+ clickedAriaLabel={share.ariaLabel ?? 'Shared'}
119
+ onClick={(e) => handleClick(e, 'share', share.onClick)}
81
120
  className={share.className}
82
121
  isDisabled={share.isDisabled}
83
122
  tooltipContent={share.tooltipContent ?? 'Share'}
123
+ clickedTooltipContent={share.clickedTooltipContent ?? 'Shared'}
84
124
  tooltipProps={share.tooltipProps}
85
125
  icon={<ExternalLinkAltIcon />}
126
+ isClicked={activeButton === 'share'}
86
127
  ></ResponseActionButton>
87
128
  )}
88
129
  {listen && (
89
130
  <ResponseActionButton
90
131
  ariaLabel={listen.ariaLabel ?? 'Listen'}
91
- onClick={listen.onClick}
132
+ clickedAriaLabel={listen.ariaLabel ?? 'Listening'}
133
+ onClick={(e) => handleClick(e, 'listen', listen.onClick)}
92
134
  className={listen.className}
93
135
  isDisabled={listen.isDisabled}
94
136
  tooltipContent={listen.tooltipContent ?? 'Listen'}
137
+ clickedTooltipContent={listen.clickedTooltipContent ?? 'Listening'}
95
138
  tooltipProps={listen.tooltipProps}
96
139
  icon={<VolumeUpIcon />}
140
+ isClicked={activeButton === 'listen'}
97
141
  ></ResponseActionButton>
98
142
  )}
99
143
  {Object.keys(additionalActions).map((action) => (
100
144
  <ResponseActionButton
101
145
  key={action}
102
146
  ariaLabel={additionalActions[action]?.ariaLabel}
103
- onClick={additionalActions[action]?.onClick}
147
+ clickedAriaLabel={additionalActions[action]?.clickedAriaLabel}
148
+ onClick={(e) => handleClick(e, action, additionalActions[action]?.onClick)}
104
149
  className={additionalActions[action]?.className}
105
150
  isDisabled={additionalActions[action]?.isDisabled}
106
151
  tooltipContent={additionalActions[action]?.tooltipContent}
107
152
  tooltipProps={additionalActions[action]?.tooltipProps}
153
+ clickedTooltipContent={additionalActions[action]?.clickedTooltipContent}
108
154
  icon={additionalActions[action]?.icon}
155
+ isClicked={activeButton === action}
109
156
  />
110
157
  ))}
111
158
  </div>
@@ -0,0 +1,34 @@
1
+ .pf-chatbot__settings-form-container {
2
+ width: 100%;
3
+ display: flex;
4
+ justify-content: center;
5
+ overflow: scroll;
6
+ }
7
+
8
+ .pf-chatbot__settings-form {
9
+ display: flex;
10
+ flex-direction: column;
11
+ max-width: 60rem;
12
+ flex: 1;
13
+ }
14
+
15
+ .pf-chatbot__settings-form-row {
16
+ font-size: var(--pf-t--global--font--size--body--lg);
17
+ display: flex;
18
+ align-items: center;
19
+ justify-content: space-between;
20
+ border-bottom: 1px solid var(--pf-t--global--border--color--default);
21
+ padding: var(--pf-t--global--spacer--lg);
22
+ font-weight: 500;
23
+ }
24
+
25
+ .pf-chatbot__settings-form-row:last-of-type {
26
+ border-bottom: 0px;
27
+ }
28
+
29
+ .pf-chatbot__settings--title {
30
+ font-family: var(--pf-t--global--font--family--heading);
31
+ font-size: var(--pf-t--global--font--size--xl);
32
+ font-weight: 500;
33
+ text-align: center;
34
+ }
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+
3
+ export interface SettingsFormProps {
4
+ /** Class applied to form container */
5
+ className?: string;
6
+ /** Array of fields to display in the settings layout */
7
+ fields?: { id: string; label: string; field: React.ReactElement }[];
8
+ }
9
+
10
+ export const SettingsForm: React.FunctionComponent<SettingsFormProps> = ({ className, fields = [], ...props }) => (
11
+ <div className={`pf-chatbot__settings-form-container ${className}`} {...props}>
12
+ <form className="pf-chatbot__settings-form">
13
+ {fields.map((field) => (
14
+ <div className="pf-chatbot__settings-form-row" key={field.label}>
15
+ <label className="pf-chatbot__settings-label" htmlFor={field.id}>
16
+ {field.label}
17
+ </label>
18
+ {field.field}
19
+ </div>
20
+ ))}
21
+ </form>
22
+ </div>
23
+ );
24
+
25
+ export default SettingsForm;
@@ -0,0 +1,3 @@
1
+ export { default } from './SettingsForm';
2
+
3
+ export * from './SettingsForm';
@@ -0,0 +1,66 @@
1
+ .pf-chatbot__terms-of-use-modal {
2
+ .pf-v6-c-content {
3
+ font-size: var(--pf-t--global--font--size--body--lg);
4
+
5
+ h2 {
6
+ font-size: var(--pf-t--global--icon--size--font--heading--h2);
7
+ font-family: var(--pf-t--global--font--family--heading);
8
+ margin-bottom: var(--pf-t--global--spacer--md);
9
+ margin-top: var(--pf-t--global--spacer--md);
10
+ font-weight: var(--pf-t--global--font--weight--heading--default);
11
+ }
12
+ h2:first-of-type {
13
+ margin-top: 0;
14
+ }
15
+ }
16
+
17
+ .pf-chatbot__terms-of-use--header {
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ flex-direction: column;
22
+ gap: var(--pf-t--global--spacer--xl);
23
+ margin-block-start: var(--pf-t--global--spacer--xl);
24
+ }
25
+
26
+ .pf-chatbot__terms-of-use--title {
27
+ font-size: var(--pf-t--global--font--size--heading--h1);
28
+ font-family: var(--pf-t--global--font--family--heading);
29
+ font-weight: var(--pf-t--global--font--weight--heading--bold);
30
+ }
31
+
32
+ .pf-chatbot__terms-of-use--footer {
33
+ margin-block-start: var(--pf-t--global--spacer--md);
34
+ }
35
+
36
+ .pf-chatbot__terms-of-use--section {
37
+ display: flex;
38
+ flex-direction: column;
39
+ height: 100%;
40
+ width: 100%;
41
+ }
42
+
43
+ // for handling zoom conditions; zoom to 125% or higher to see this
44
+ @media screen and (max-height: 620px) {
45
+ .pf-v6-c-modal-box__body {
46
+ --pf-v6-c-modal-box__body--MinHeight: auto;
47
+ overflow: visible;
48
+ }
49
+ }
50
+ }
51
+
52
+ .pf-chatbot__chatbot-modal.pf-chatbot__chatbot-modal--fullscreen.pf-chatbot__terms-of-use-modal.pf-chatbot__terms-of-use-modal--fullscreen,
53
+ .pf-chatbot__chatbot-modal.pf-chatbot__chatbot-modal--embedded.pf-chatbot__terms-of-use-modal.pf-chatbot__terms-of-use-modal--embedded {
54
+ // override parent modal style
55
+ height: inherit;
56
+
57
+ .pf-v6-c-content {
58
+ h2 {
59
+ font-size: var(--pf-t--global--icon--size--font--heading--h1);
60
+ }
61
+ }
62
+
63
+ .pf-chatbot__terms-of-use--title {
64
+ font-size: var(--pf-t--global--font--size--heading--2xl);
65
+ }
66
+ }
@@ -0,0 +1,138 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+ import userEvent from '@testing-library/user-event';
5
+ import TermsOfUse from './TermsOfUse';
6
+ import { Content } from '@patternfly/react-core';
7
+
8
+ const handleModalToggle = jest.fn();
9
+ const onPrimaryAction = jest.fn();
10
+ const onSecondaryAction = jest.fn();
11
+
12
+ const body = (
13
+ <Content>
14
+ <h1>Heading 1</h1>
15
+ <p>Legal text</p>
16
+ </Content>
17
+ );
18
+ describe('TermsOfUse', () => {
19
+ afterEach(() => {
20
+ jest.clearAllMocks();
21
+ });
22
+ it('should render modal correctly', () => {
23
+ render(
24
+ <TermsOfUse
25
+ isModalOpen
26
+ onSecondaryAction={onSecondaryAction}
27
+ handleModalToggle={handleModalToggle}
28
+ ouiaId="Terms"
29
+ >
30
+ {body}
31
+ </TermsOfUse>
32
+ );
33
+ expect(screen.getByRole('heading', { name: /Terms of use/i })).toBeTruthy();
34
+ expect(screen.getByRole('button', { name: /Accept/i })).toBeTruthy();
35
+ expect(screen.getByRole('button', { name: /Decline/i })).toBeTruthy();
36
+ expect(screen.getByRole('heading', { name: /Heading 1/i })).toBeTruthy();
37
+ expect(screen.getByText(/Legal text/i)).toBeTruthy();
38
+ expect(screen.getByRole('dialog')).toHaveClass('pf-chatbot__terms-of-use-modal');
39
+ expect(screen.getByRole('dialog')).toHaveClass('pf-chatbot__terms-of-use-modal--default');
40
+ });
41
+ it('should handle image and altText props', () => {
42
+ render(
43
+ <TermsOfUse
44
+ isModalOpen
45
+ onSecondaryAction={onSecondaryAction}
46
+ handleModalToggle={handleModalToggle}
47
+ image="./image.png"
48
+ altText="Test image"
49
+ >
50
+ {body}
51
+ </TermsOfUse>
52
+ );
53
+ expect(screen.getByRole('img')).toBeTruthy();
54
+ expect(screen.getByRole('img')).toHaveAttribute('alt', 'Test image');
55
+ });
56
+ it('should handle className prop', () => {
57
+ render(
58
+ <TermsOfUse
59
+ isModalOpen
60
+ onSecondaryAction={onSecondaryAction}
61
+ handleModalToggle={handleModalToggle}
62
+ className="test"
63
+ >
64
+ {body}
65
+ </TermsOfUse>
66
+ );
67
+ expect(screen.getByRole('dialog')).toHaveClass('pf-chatbot__terms-of-use-modal');
68
+ expect(screen.getByRole('dialog')).toHaveClass('pf-chatbot__terms-of-use-modal--default');
69
+ expect(screen.getByRole('dialog')).toHaveClass('test');
70
+ });
71
+ it('should handle title prop', () => {
72
+ render(
73
+ <TermsOfUse
74
+ isModalOpen
75
+ onSecondaryAction={onSecondaryAction}
76
+ handleModalToggle={handleModalToggle}
77
+ title="Updated title"
78
+ >
79
+ {body}
80
+ </TermsOfUse>
81
+ );
82
+ expect(screen.getByRole('heading', { name: /Updated title/i })).toBeTruthy();
83
+ expect(screen.queryByRole('heading', { name: /Terms of use/i })).toBeFalsy();
84
+ });
85
+ it('should handle primary button prop', () => {
86
+ render(
87
+ <TermsOfUse
88
+ isModalOpen
89
+ onSecondaryAction={onSecondaryAction}
90
+ handleModalToggle={handleModalToggle}
91
+ primaryActionBtn="First"
92
+ >
93
+ {body}
94
+ </TermsOfUse>
95
+ );
96
+ expect(screen.getByRole('button', { name: /First/i })).toBeTruthy();
97
+ expect(screen.queryByRole('button', { name: /Accept/i })).toBeFalsy();
98
+ });
99
+ it('should handle secondary button prop', () => {
100
+ render(
101
+ <TermsOfUse
102
+ isModalOpen
103
+ onSecondaryAction={onSecondaryAction}
104
+ handleModalToggle={handleModalToggle}
105
+ secondaryActionBtn="Second"
106
+ >
107
+ {body}
108
+ </TermsOfUse>
109
+ );
110
+ expect(screen.getByRole('button', { name: /Second/i })).toBeTruthy();
111
+ expect(screen.queryByRole('button', { name: /Deny/i })).toBeFalsy();
112
+ });
113
+ it('should handle primary button click', async () => {
114
+ render(
115
+ <TermsOfUse
116
+ isModalOpen
117
+ onPrimaryAction={onPrimaryAction}
118
+ onSecondaryAction={onSecondaryAction}
119
+ handleModalToggle={handleModalToggle}
120
+ >
121
+ {body}
122
+ </TermsOfUse>
123
+ );
124
+ await userEvent.click(screen.getByRole('button', { name: /Accept/i }));
125
+ expect(onPrimaryAction).toHaveBeenCalledTimes(1);
126
+ expect(handleModalToggle).toHaveBeenCalledTimes(1);
127
+ });
128
+ it('should handle secondary button click', async () => {
129
+ render(
130
+ <TermsOfUse isModalOpen onSecondaryAction={onSecondaryAction} handleModalToggle={handleModalToggle}>
131
+ {body}
132
+ </TermsOfUse>
133
+ );
134
+ await userEvent.click(screen.getByRole('button', { name: /Decline/i }));
135
+ expect(onSecondaryAction).toHaveBeenCalledTimes(1);
136
+ expect(handleModalToggle).not.toHaveBeenCalled();
137
+ });
138
+ });
@@ -0,0 +1,117 @@
1
+ // ============================================================================
2
+ // Terms of Use Modal - Chatbot Modal Extension
3
+ // ============================================================================
4
+ import React from 'react';
5
+ import { Button, Content, ModalBody, ModalFooter, ModalHeader, ModalProps } from '@patternfly/react-core';
6
+ import { ChatbotDisplayMode } from '../Chatbot';
7
+ import ChatbotModal from '../ChatbotModal/ChatbotModal';
8
+
9
+ export interface TermsOfUseProps extends ModalProps {
10
+ /** Class applied to modal */
11
+ className?: string;
12
+ /** Action assigned to primary modal button */
13
+ onPrimaryAction?: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void;
14
+ /** Action assigned to secondary modal button */
15
+ onSecondaryAction: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void;
16
+ /** Name of primary modal button */
17
+ primaryActionBtn?: string;
18
+ /** Name of secondary modal button */
19
+ secondaryActionBtn?: string;
20
+ /** Function that handles modal toggle */
21
+ handleModalToggle: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void;
22
+ /** Whether modal is open */
23
+ isModalOpen: boolean;
24
+ /** Title of modal */
25
+ title?: string;
26
+ /** Display mode for the Chatbot parent; this influences the styles applied */
27
+ displayMode?: ChatbotDisplayMode;
28
+ /** Optional image displayed in header */
29
+ image?: string;
30
+ /** Alt text for optional image displayed in header */
31
+ altText?: string;
32
+ /** Ref applied to modal */
33
+ innerRef?: React.Ref<HTMLDivElement>;
34
+ /** OuiaID applied to modal */
35
+ ouiaId?: string;
36
+ }
37
+
38
+ export const TermsOfUseBase: React.FunctionComponent<TermsOfUseProps> = ({
39
+ handleModalToggle,
40
+ isModalOpen,
41
+ onPrimaryAction,
42
+ onSecondaryAction,
43
+ primaryActionBtn = 'Accept',
44
+ secondaryActionBtn = 'Decline',
45
+ title = 'Terms of use',
46
+ image,
47
+ altText,
48
+ displayMode = ChatbotDisplayMode.default,
49
+ className,
50
+ children,
51
+ innerRef,
52
+ ouiaId = 'TermsOfUse',
53
+ ...props
54
+ }: TermsOfUseProps) => {
55
+ const handlePrimaryAction = (_event: React.MouseEvent | MouseEvent | KeyboardEvent) => {
56
+ handleModalToggle(_event);
57
+ onPrimaryAction && onPrimaryAction(_event);
58
+ };
59
+
60
+ const handleSecondaryAction = (_event: React.MouseEvent | MouseEvent | KeyboardEvent) => {
61
+ onSecondaryAction(_event);
62
+ };
63
+
64
+ const modal = (
65
+ <ChatbotModal
66
+ isOpen={isModalOpen}
67
+ ouiaId={ouiaId}
68
+ aria-labelledby="terms-of-use-title"
69
+ aria-describedby="terms-of-use-modal"
70
+ className={`pf-chatbot__terms-of-use-modal pf-chatbot__terms-of-use-modal--${displayMode} ${className ? className : ''}`}
71
+ displayMode={displayMode}
72
+ {...props}
73
+ >
74
+ {/* This is a workaround since the PatternFly modal doesn't have ref forwarding */}
75
+ <section className={`pf-chatbot__terms-of-use--section`} aria-label={title} tabIndex={-1} ref={innerRef}>
76
+ <ModalHeader>
77
+ <div className="pf-chatbot__terms-of-use--header">
78
+ {image && altText && <img src={image} className="pf-chatbot__terms-of-use--image" alt={altText} />}
79
+ <h1 className="pf-chatbot__terms-of-use--title">{title}</h1>
80
+ </div>
81
+ </ModalHeader>
82
+ <ModalBody>
83
+ <Content>{children}</Content>
84
+ </ModalBody>
85
+ <ModalFooter className="pf-chatbot__terms-of-use--footer">
86
+ <Button
87
+ isBlock
88
+ key="terms-of-use-modal-primary"
89
+ variant="primary"
90
+ onClick={handlePrimaryAction}
91
+ form="terms-of-use-form"
92
+ size="lg"
93
+ >
94
+ {primaryActionBtn}
95
+ </Button>
96
+ <Button
97
+ isBlock
98
+ key="terms-of-use-modal-secondary"
99
+ variant="secondary"
100
+ onClick={handleSecondaryAction}
101
+ size="lg"
102
+ >
103
+ {secondaryActionBtn}
104
+ </Button>
105
+ </ModalFooter>
106
+ </section>
107
+ </ChatbotModal>
108
+ );
109
+
110
+ return modal;
111
+ };
112
+
113
+ const TermsOfUse = React.forwardRef((props: TermsOfUseProps, ref: React.Ref<HTMLDivElement>) => (
114
+ <TermsOfUseBase innerRef={ref} {...props} />
115
+ ));
116
+
117
+ export default TermsOfUse;
@@ -0,0 +1,3 @@
1
+ export { default } from './TermsOfUse';
2
+
3
+ export * from './TermsOfUse';
package/src/index.ts CHANGED
@@ -66,8 +66,14 @@ export * from './PreviewAttachment';
66
66
  export { default as ResponseActions } from './ResponseActions';
67
67
  export * from './ResponseActions';
68
68
 
69
+ export { default as Settings } from './Settings';
70
+ export * from './Settings';
71
+
69
72
  export { default as SourceDetailsMenuItem } from './SourceDetailsMenuItem';
70
73
  export * from './SourceDetailsMenuItem';
71
74
 
72
75
  export { default as SourcesCard } from './SourcesCard';
73
76
  export * from './SourcesCard';
77
+
78
+ export { default as TermsOfUse } from './TermsOfUse';
79
+ export * from './TermsOfUse';
package/src/main.scss CHANGED
@@ -18,12 +18,16 @@
18
18
  @import './Message/TextMessage/TextMessage';
19
19
  @import './Message/ListMessage/ListMessage';
20
20
  @import './Message/MessageLoading';
21
+ @import './Message/QuickStarts/QuickStartTile';
22
+ @import './Message/QuickResponse/QuickResponse';
21
23
  @import './MessageBar/MessageBar';
22
24
  @import './MessageBox/MessageBox';
23
25
  @import './MessageBox/JumpButton';
24
26
  @import './ResponseActions/ResponseActions';
27
+ @import './Settings/Settings';
25
28
  @import './SourcesCard/SourcesCard.scss';
26
29
  @import './SourceDetailsMenuItem/SourceDetailsMenuItem';
30
+ @import './TermsOfUse/TermsOfUse';
27
31
 
28
32
  :where(:root) {
29
33
  // ============================================================================
@@ -47,9 +51,9 @@
47
51
  --pf-t--chatbot--timing-function: cubic-bezier(0.77, 0, 0.175, 1);
48
52
 
49
53
  --pf-t--chatbot--blue-icon--background--color--hover: rgba(
50
- 185,
51
- 218,
52
- 252,
54
+ 146,
55
+ 197,
56
+ 249,
53
57
  0.25
54
58
  ); // --pf-t--global--color--nonstatus--blue--default @ 25%
55
59
  --pf-t--chatbot--blue-icon--fill--hover: var(--pf-t--global--color--brand--hover);