@confidencesystemsinc/sdk 1.2.0 → 1.2.2

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 (61) hide show
  1. package/dist/components/playbook/confidence-playbook.d.ts +12 -5
  2. package/dist/components/playbook/playbook-header.d.ts +3 -1
  3. package/dist/components/playbook-button/ConfidencePlaybookButton.d.ts +2 -1
  4. package/dist/components/task/confidence-task.d.ts +10 -3
  5. package/dist/components/task/task-buttons.d.ts +2 -1
  6. package/dist/components/task/task-expanded-content.d.ts +3 -0
  7. package/dist/components/ui/button.d.ts +1 -0
  8. package/dist/confidence_logo.png +0 -0
  9. package/dist/constants/settings.constants.d.ts +2 -2
  10. package/dist/context/confidence-context.d.ts +10 -0
  11. package/dist/hooks/task/useTaskDetails.d.ts +173 -0
  12. package/dist/hooks/usePlaybookExpandedTasks.d.ts +4 -0
  13. package/dist/hooks/useTaskButtons.d.ts +2 -1
  14. package/dist/index.cjs +15 -15
  15. package/dist/index.js +3587 -3317
  16. package/dist/services/task-details.service.d.ts +4 -0
  17. package/dist/stories/confidence-task.stories.d.ts +50 -0
  18. package/dist/theme.css +1 -1
  19. package/package.json +3 -2
  20. package/src/components/badge.tsx +116 -0
  21. package/src/components/initiate-playbook-modal/InitiatePlaybookModal.tsx +53 -0
  22. package/src/components/playbook/confidence-playbook.tsx +346 -0
  23. package/src/components/playbook/playbook-header.tsx +32 -0
  24. package/src/components/playbook-button/ConfidencePlaybookButton.tsx +79 -0
  25. package/src/components/task/confidence-task.tsx +297 -0
  26. package/src/components/task/task-buttons.tsx +35 -0
  27. package/src/components/task/task-dropdown-badge.tsx +118 -0
  28. package/src/components/task/task-expanded-content.tsx +46 -0
  29. package/src/components/task/task-left-panel.tsx +60 -0
  30. package/src/components/task/task-status-badge.tsx +23 -0
  31. package/src/components/ui/button.tsx +272 -0
  32. package/src/components/ui/input.tsx +39 -0
  33. package/src/components/ui/modal.tsx +88 -0
  34. package/src/components/ui/ui-wrapper.tsx +7 -0
  35. package/src/constants/settings.constants.ts +4 -0
  36. package/src/context/confidence-context.tsx +25 -0
  37. package/src/hooks/task/useCompleteTask.ts +32 -0
  38. package/src/hooks/task/useStartTask.ts +35 -0
  39. package/src/hooks/task/useTaskDetails.ts +42 -0
  40. package/src/hooks/usePlaybook.ts +54 -0
  41. package/src/hooks/usePlaybookActions.ts +69 -0
  42. package/src/hooks/usePlaybookExpandedTasks.ts +35 -0
  43. package/src/hooks/useTaskButtons.ts +47 -0
  44. package/src/index.ts +7 -0
  45. package/src/services/complete-task.service.ts +25 -0
  46. package/src/services/initiate-playbook.service.ts +26 -0
  47. package/src/services/start-task.services.ts +27 -0
  48. package/src/services/task-details.service.ts +17 -0
  49. package/src/stories/confidence-playbook.stories.tsx +124 -0
  50. package/src/stories/confidence-task.stories.tsx +63 -0
  51. package/src/stories/initiate-playbook-modal.stories.tsx +31 -0
  52. package/src/stories/modal.stories.tsx +50 -0
  53. package/src/task-description.css +629 -0
  54. package/src/theme.css +11 -0
  55. package/src/types/playbook.types.ts +22 -0
  56. package/src/types/task.types.ts +20 -0
  57. package/src/utils/cn.ts +6 -0
  58. package/src/vite-env.d.ts +1 -0
  59. package/dist/components/ui/header.d.ts +0 -1
  60. /package/dist/hooks/{task-events → task}/useCompleteTask.d.ts +0 -0
  61. /package/dist/hooks/{task-events → task}/useStartTask.d.ts +0 -0
@@ -0,0 +1,346 @@
1
+ import { useEffect, useMemo, useRef, useState } from "react";
2
+ import { ConfidenceContext } from "../../context/confidence-context";
3
+ import { usePlaybook } from "../../hooks/usePlaybook";
4
+ import { TASK_BUTTONS, TaskButton } from "../../hooks/useTaskButtons";
5
+ import { initiatePlaybook } from "../../services/initiate-playbook.service";
6
+ import { Playbook } from "../../types/playbook.types";
7
+ import { TASK_STATUS } from "../../types/task.types";
8
+ import { cn } from "../../utils/cn";
9
+ import { ConfidencePlaybookButton } from "../playbook-button/ConfidencePlaybookButton";
10
+ import { ConfidenceTask } from "../task/confidence-task";
11
+ import { PlaybookHeader } from "./playbook-header";
12
+ import ConfidenceLogo from "../../../public/confidence_logo.png";
13
+ import { usePlaybookExpandedTasks } from "../../hooks/usePlaybookExpandedTasks";
14
+ export interface ConfidencePlaybookStyleConfiguration {
15
+ overlay?: {
16
+ position?: "left" | "right";
17
+ width?: number | string; // Use string to allow 'calc()' or other CSS values
18
+ height?: number | string;
19
+ right?: number; // For right positioning
20
+ left?: number; // For left positioning
21
+ };
22
+ whiteLabel?: {
23
+ titleBackgroundColor?: string;
24
+ titleTextColor?: string;
25
+ primaryColor?: string;
26
+ };
27
+ }
28
+
29
+ const ConfidencePlaybookInternal = ({
30
+ playbookInstanceId,
31
+ playbookMode,
32
+ playbookStyle,
33
+ }: {
34
+ playbookInstanceId: string | number;
35
+ playbookMode: "list" | "card";
36
+ playbookStyle?: ConfidencePlaybookStyleConfiguration;
37
+ }) => {
38
+ const { playbook, actions: playbookActions } =
39
+ usePlaybook(playbookInstanceId);
40
+
41
+ if (!playbook) {
42
+ return <div></div>;
43
+ }
44
+
45
+ const handleButtonClick = async (buttonType: TaskButton, taskId: number) => {
46
+ if (buttonType === TASK_BUTTONS.COMPLETE) {
47
+ const sequenceOrder = playbook.tasks.find(
48
+ (task) => task.taskInstanceId === taskId,
49
+ )?.sequenceOrder;
50
+ if (sequenceOrder === undefined) {
51
+ console.error("Task not found in playbook");
52
+ return;
53
+ }
54
+
55
+ return playbookActions.completeTask(taskId, sequenceOrder);
56
+ }
57
+
58
+ if (buttonType === TASK_BUTTONS.START) {
59
+ return playbookActions.startTask(taskId);
60
+ }
61
+ };
62
+
63
+ return (
64
+ <PlaybookView
65
+ playbook={playbook}
66
+ playbookMode={playbookMode}
67
+ onTaskButtonClick={handleButtonClick}
68
+ playbookStyle={playbookStyle}
69
+ />
70
+ );
71
+ };
72
+
73
+ const TasksContainer = ({
74
+ className,
75
+ children,
76
+ numberOfTasks,
77
+ playbookMode,
78
+ }: {
79
+ className?: string;
80
+ children: React.ReactNode;
81
+ numberOfTasks?: number; // Default to 3 if not provided
82
+ playbookMode: "list" | "card";
83
+ }) => {
84
+ return (
85
+ <div className={cn("w-full p-4", className)}>
86
+ {numberOfTasks && (
87
+ <div className={cn(playbookMode === "card" && "mb-4")}>
88
+ <span className="font-medium">Tasks</span> (3)
89
+ </div>
90
+ )}
91
+ <div className={cn(playbookMode === "card" && "space-y-4")}>
92
+ {children}
93
+ </div>
94
+ </div>
95
+ );
96
+ };
97
+
98
+ const PlaybookView = ({
99
+ playbook,
100
+ playbookMode,
101
+ onTaskButtonClick,
102
+ playbookStyle,
103
+ }: {
104
+ playbookMode: "list" | "card";
105
+ playbook: Playbook;
106
+ onTaskButtonClick: (btn: TaskButton, taskId: number) => Promise<void>;
107
+ playbookStyle?: ConfidencePlaybookStyleConfiguration;
108
+ }) => {
109
+ const { playbookInstanceName, tasks } = playbook;
110
+ const playbookHeaderRef = useRef<HTMLDivElement>(null);
111
+ const [playbookHeaderHeight, setPlaybookHeaderHeight] = useState(0);
112
+ const { isTaskExpanded, toggleTaskExpanded } = usePlaybookExpandedTasks(
113
+ playbook.playbookInstanceId,
114
+ );
115
+
116
+ useEffect(() => {
117
+ if (playbookHeaderRef.current) {
118
+ /** Setup a resize observer */
119
+ const resizeObserver = new ResizeObserver((entries) => {
120
+ for (const entry of entries) {
121
+ console.log("ResizeObserver entry:", entry);
122
+ if (entry.contentRect) {
123
+ setPlaybookHeaderHeight(
124
+ playbookHeaderRef.current?.offsetHeight || 0,
125
+ );
126
+ }
127
+ }
128
+ });
129
+ resizeObserver.observe(playbookHeaderRef.current);
130
+ }
131
+
132
+ return () => {
133
+ if (playbookHeaderRef.current) {
134
+ /** Cleanup the resize observer */
135
+ const resizeObserver = new ResizeObserver(() => {});
136
+ resizeObserver.unobserve(playbookHeaderRef.current);
137
+ }
138
+ };
139
+ }, [playbookHeaderRef]);
140
+ const sequenceOrderToStart = useMemo(() => {
141
+ const lastCompletedTask = tasks.find(
142
+ (task) => task.workflowStatus === TASK_STATUS.COMPLETED,
143
+ );
144
+ if (!lastCompletedTask) {
145
+ return 0;
146
+ }
147
+
148
+ return lastCompletedTask.sequenceOrder + 1;
149
+ }, [tasks]);
150
+
151
+ return (
152
+ <div
153
+ className={cn(
154
+ !playbookStyle?.overlay && "min-h-screen",
155
+ playbookStyle?.overlay && "fixed bottom-0 z-[99999999999999] flex",
156
+ )}
157
+ {...(playbookStyle?.overlay && {
158
+ style: {
159
+ width: playbookStyle.overlay.width || 450,
160
+ height: playbookStyle.overlay.height || "calc(100vh - 4rem)",
161
+ maxHeight: "calc(100vh - 4rem)",
162
+ right:
163
+ playbookStyle.overlay.right !== undefined
164
+ ? playbookStyle.overlay.right
165
+ : playbookStyle.overlay.position === "right"
166
+ ? 32
167
+ : undefined,
168
+ left:
169
+ playbookStyle.overlay.left !== undefined
170
+ ? playbookStyle.overlay.left
171
+ : playbookStyle.overlay.position === "left"
172
+ ? 32
173
+ : undefined,
174
+ },
175
+ })}
176
+ >
177
+ {playbookStyle?.overlay && (
178
+ <div
179
+ className={cn(
180
+ "size-9 relative p-1 top-3 z-[99999999999999] border-none rounded-l-sm ",
181
+ )}
182
+ style={{
183
+ backgroundColor:
184
+ playbookStyle?.whiteLabel?.primaryColor || "#007BFF",
185
+ boxShadow: "0px 3px 3px 0px #00000040",
186
+ }}
187
+ >
188
+ <img
189
+ src={ConfidenceLogo}
190
+ alt="Confidence Logo"
191
+ className="w-full h-full object-contain"
192
+ />
193
+ </div>
194
+ )}
195
+ <div
196
+ className={cn(
197
+ "flex flex-col flex-1 bg-gray-50",
198
+ playbookStyle?.overlay &&
199
+ "border border-gray-200 shadow-2xl rounded-t-sm overflow-y-auto",
200
+ )}
201
+ >
202
+ <PlaybookHeader
203
+ title={playbookInstanceName}
204
+ className={cn("top-0 sticky z-2")}
205
+ playbookStyle={playbookStyle}
206
+ ref={playbookHeaderRef}
207
+ />
208
+
209
+ <TasksContainer
210
+ playbookMode={playbookMode}
211
+ numberOfTasks={playbook.numberofTasks}
212
+ >
213
+ {tasks.map((task, index) => {
214
+ return (
215
+ <ConfidenceTask
216
+ key={index}
217
+ task={task}
218
+ step={index + 1}
219
+ viewMode={playbookMode}
220
+ playbookId={playbook.playbookId}
221
+ canStart={task.sequenceOrder === sequenceOrderToStart}
222
+ onButtonClick={(btn) => {
223
+ return onTaskButtonClick(btn, task.taskInstanceId);
224
+ }}
225
+ playbookType={"Non-Sequential"}
226
+ taskStyle={{
227
+ titleColor: playbookStyle?.whiteLabel?.primaryColor,
228
+ }}
229
+ isExpanded={isTaskExpanded(task.taskInstanceId)}
230
+ toggleExpanded={() => toggleTaskExpanded(task.taskInstanceId)}
231
+ listStickyTopBase={playbookHeaderHeight || 104} // Adjust this value based on your header height
232
+ />
233
+ );
234
+ })}
235
+ </TasksContainer>
236
+ </div>
237
+ </div>
238
+ );
239
+ };
240
+
241
+ const AutoInstantiated = ({
242
+ email,
243
+ playbookId,
244
+ playbookMode,
245
+ }: {
246
+ email: string;
247
+ playbookId: string;
248
+ playbookMode: "list" | "card";
249
+ }) => {
250
+ const [playbookInstanceId, setPlaybookInstanceId] = useState<number | null>(
251
+ null,
252
+ );
253
+
254
+ useEffect(() => {
255
+ (async () => {
256
+ const { playbookInstanceId, errorCode, details, message } =
257
+ (await initiatePlaybook({
258
+ bank: "public-sdk",
259
+ email,
260
+ timezone:
261
+ Intl.DateTimeFormat().resolvedOptions().timeZone ||
262
+ "America/Los_Angeles",
263
+ playbookUid: playbookId,
264
+ })) || {};
265
+
266
+ if (errorCode) {
267
+ throw new Error(
268
+ `Error initiating playbook: ${message} (Code: ${errorCode}) - Details: ${details}`,
269
+ );
270
+ }
271
+
272
+ setPlaybookInstanceId(playbookInstanceId);
273
+ })();
274
+ }, []);
275
+
276
+ if (!playbookInstanceId) {
277
+ return <div>Loading...</div>;
278
+ }
279
+
280
+ return (
281
+ <ConfidencePlaybook
282
+ playbookInstanceId={playbookInstanceId}
283
+ playbookMode={playbookMode}
284
+ />
285
+ );
286
+ };
287
+
288
+ const WithInstantiateButton = ({
289
+ playbookId,
290
+ playbookMode = "list",
291
+ playbookStyle,
292
+ btnLabel = "Start Playbook",
293
+ }: {
294
+ playbookId: string;
295
+ playbookMode?: "list" | "card";
296
+ playbookStyle?: ConfidencePlaybookStyleConfiguration;
297
+ btnLabel?: string;
298
+ }) => {
299
+ const [playbookInstanceId, setPlaybookInstanceId] = useState<number | null>(
300
+ null,
301
+ );
302
+
303
+ return (
304
+ <>
305
+ <ConfidencePlaybookButton
306
+ playbookId={playbookId}
307
+ disabled={!!playbookInstanceId}
308
+ onInitiated={setPlaybookInstanceId}
309
+ btnLabel={btnLabel}
310
+ />
311
+
312
+ {playbookInstanceId && (
313
+ <ConfidencePlaybook
314
+ playbookInstanceId={playbookInstanceId}
315
+ playbookMode={playbookMode}
316
+ playbookStyle={playbookStyle}
317
+ />
318
+ )}
319
+ </>
320
+ );
321
+ };
322
+
323
+ export const ConfidencePlaybook = ({
324
+ playbookInstanceId,
325
+ playbookMode,
326
+ playbookStyle,
327
+ }: {
328
+ playbookInstanceId: string | number;
329
+ playbookMode: "list" | "card";
330
+ playbookStyle?: ConfidencePlaybookStyleConfiguration;
331
+ }) => {
332
+ return (
333
+ <ConfidenceContext>
334
+ <ConfidencePlaybookInternal
335
+ playbookInstanceId={playbookInstanceId}
336
+ playbookMode={playbookMode}
337
+ playbookStyle={playbookStyle}
338
+ />
339
+ </ConfidenceContext>
340
+ );
341
+ };
342
+
343
+ ConfidencePlaybook.Context = ConfidenceContext;
344
+ ConfidencePlaybook.View = PlaybookView;
345
+ ConfidencePlaybook.AutoInstantiated = AutoInstantiated;
346
+ ConfidencePlaybook.WithInstantiateButton = WithInstantiateButton;
@@ -0,0 +1,32 @@
1
+ import { cn } from "../../utils/cn";
2
+ import { type ConfidencePlaybookStyleConfiguration } from "./confidence-playbook";
3
+
4
+ export const PlaybookHeader = ({
5
+ title,
6
+ className,
7
+ playbookStyle,
8
+ ...props
9
+ }: React.ComponentProps<"div"> & {
10
+ title: string;
11
+ playbookStyle?: ConfidencePlaybookStyleConfiguration;
12
+ }) => {
13
+ return (
14
+ <div
15
+ className={cn("border-b border-gray-200 flex items-center", className)}
16
+ style={{
17
+ backgroundColor:
18
+ playbookStyle?.whiteLabel?.titleBackgroundColor || "#f8f9fa",
19
+ }}
20
+ {...props}
21
+ >
22
+ <div
23
+ className="text-xl min-h-16 p-4"
24
+ style={{
25
+ color: playbookStyle?.whiteLabel?.titleTextColor,
26
+ }}
27
+ >
28
+ {title}
29
+ </div>
30
+ </div>
31
+ );
32
+ };
@@ -0,0 +1,79 @@
1
+ import { useState } from "react";
2
+ import { initiatePlaybook } from "../../services/initiate-playbook.service";
3
+ import { InitiatePlaybookModal } from "../initiate-playbook-modal/InitiatePlaybookModal";
4
+ import Button, { ButtonSizeType } from "../ui/button";
5
+
6
+ export const ConfidencePlaybookButton = ({
7
+ btnClassName,
8
+ buttonNode,
9
+ size,
10
+ playbookId,
11
+ onInitiated,
12
+ disabled,
13
+ btnLabel = "Run Playbook",
14
+ }: {
15
+ btnClassName?: string;
16
+ buttonNode?: React.ReactNode;
17
+ size?: ButtonSizeType;
18
+ playbookId: string;
19
+ disabled?: boolean;
20
+ btnLabel?: string;
21
+ onInitiated: (playbookInstanceId: number) => void;
22
+ }) => {
23
+ const [isOpen, setIsOpen] = useState(false);
24
+
25
+ function open() {
26
+ setIsOpen(true);
27
+ }
28
+
29
+ function close() {
30
+ setIsOpen(false);
31
+ }
32
+
33
+ const onInitiatePlaybook = async (email: string) => {
34
+ const { playbookInstanceId, errorCode, details, message } =
35
+ (await initiatePlaybook({
36
+ bank: "public-sdk",
37
+ email,
38
+ timezone:
39
+ Intl.DateTimeFormat().resolvedOptions().timeZone ||
40
+ "America/Los_Angeles",
41
+ playbookUid: playbookId,
42
+ })) || {};
43
+
44
+ if (errorCode) {
45
+ throw new Error(
46
+ `Error initiating playbook: ${message} (Code: ${errorCode}) - Details: ${details}`,
47
+ );
48
+ }
49
+
50
+ onInitiated(playbookInstanceId);
51
+ };
52
+
53
+ return (
54
+ <>
55
+ {buttonNode ? (
56
+ { buttonNode }
57
+ ) : (
58
+ <Button
59
+ onClick={open}
60
+ className={btnClassName}
61
+ color="primary"
62
+ size={size}
63
+ disabled={disabled}
64
+ >
65
+ {btnLabel}
66
+ </Button>
67
+ )}
68
+
69
+ <InitiatePlaybookModal
70
+ isOpen={isOpen}
71
+ onClose={close}
72
+ onConfirm={async (email) => {
73
+ await onInitiatePlaybook(email);
74
+ close();
75
+ }}
76
+ />
77
+ </>
78
+ );
79
+ };