@inploi/plugin-chatbot 2.1.0 → 2.1.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 (56) hide show
  1. package/cdn/index.js +56 -0
  2. package/package.json +12 -1
  3. package/.env +0 -2
  4. package/.env.example +0 -2
  5. package/.env.test +0 -2
  6. package/.eslintrc.cjs +0 -10
  7. package/CHANGELOG.md +0 -91
  8. package/bunfig.toml +0 -2
  9. package/happydom.ts +0 -10
  10. package/index.html +0 -29
  11. package/playwright.config.ts +0 -82
  12. package/postcss.config.cjs +0 -7
  13. package/src/chatbot.api.ts +0 -46
  14. package/src/chatbot.constants.ts +0 -9
  15. package/src/chatbot.css +0 -93
  16. package/src/chatbot.dom.ts +0 -28
  17. package/src/chatbot.idb.ts +0 -17
  18. package/src/chatbot.state.ts +0 -114
  19. package/src/chatbot.ts +0 -59
  20. package/src/chatbot.utils.ts +0 -56
  21. package/src/index.cdn.ts +0 -12
  22. package/src/index.dev.ts +0 -31
  23. package/src/index.ts +0 -1
  24. package/src/interpreter/interpreter.test.ts +0 -69
  25. package/src/interpreter/interpreter.ts +0 -249
  26. package/src/mocks/browser.ts +0 -5
  27. package/src/mocks/example.flows.ts +0 -801
  28. package/src/mocks/handlers.ts +0 -57
  29. package/src/style/palette.test.ts +0 -20
  30. package/src/style/palette.ts +0 -69
  31. package/src/ui/chat-bubble.tsx +0 -51
  32. package/src/ui/chat-input/chat-input.boolean.tsx +0 -62
  33. package/src/ui/chat-input/chat-input.file.tsx +0 -213
  34. package/src/ui/chat-input/chat-input.multiple-choice.tsx +0 -117
  35. package/src/ui/chat-input/chat-input.text.tsx +0 -111
  36. package/src/ui/chat-input/chat-input.tsx +0 -81
  37. package/src/ui/chatbot-header.tsx +0 -95
  38. package/src/ui/chatbot.tsx +0 -94
  39. package/src/ui/input-error.tsx +0 -33
  40. package/src/ui/job-application-content.tsx +0 -144
  41. package/src/ui/job-application-messages.tsx +0 -64
  42. package/src/ui/loading-indicator.tsx +0 -37
  43. package/src/ui/send-button.tsx +0 -27
  44. package/src/ui/transition.tsx +0 -1
  45. package/src/ui/typing-indicator.tsx +0 -12
  46. package/src/ui/useChatService.ts +0 -67
  47. package/src/ui/useFocus.ts +0 -10
  48. package/src/vite-env.d.ts +0 -1
  49. package/tailwind.config.ts +0 -119
  50. package/tests/integration.spec.ts +0 -19
  51. package/tests/test.ts +0 -22
  52. package/tsconfig.json +0 -33
  53. package/tsconfig.node.json +0 -10
  54. package/types.d.ts +0 -2
  55. package/vite.config.ts +0 -18
  56. /package/{public → cdn}/mockServiceWorker.js +0 -0
package/package.json CHANGED
@@ -1,7 +1,18 @@
1
1
  {
2
2
  "name": "@inploi/plugin-chatbot",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "type": "module",
5
+ "files": [
6
+ "/dist",
7
+ "/cdn"
8
+ ],
9
+ "exports": {
10
+ ".": {
11
+ "require": "./dist/index.js",
12
+ "import": "./dist/index.mjs",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
5
16
  "dependencies": {
6
17
  "@hookform/resolvers": "^3.3.2",
7
18
  "@preact/signals": "^1.2.2",
package/.env DELETED
@@ -1,2 +0,0 @@
1
- VITE_PUBLISHABLE_KEY='pk_edce29b92c2773898c482851'
2
- VITE_MOCKS=true
package/.env.example DELETED
@@ -1,2 +0,0 @@
1
- VITE_PUBLISHABLE_KEY=''
2
- VITE_MOCKS=true
package/.env.test DELETED
@@ -1,2 +0,0 @@
1
- VITE_PUBLISHABLE_KEY='fake_key'
2
- VITE_MOCKS=false # mocking is handled by the spec
package/.eslintrc.cjs DELETED
@@ -1,10 +0,0 @@
1
- /*eslint-env node */
2
- /** @type {import('eslint').Linter.Config} */
3
- module.exports = {
4
- root: true,
5
- // This tells ESLint to load the config from the package `eslint-config-custom`
6
- extends: ['custom', 'plugin:react-hooks/recommended'],
7
- plugins: ['react-hooks'],
8
- env: { browser: true, es2020: true },
9
- parserOptions: { project: ['./tsconfig.json'], tsconfigRootDir: __dirname },
10
- };
package/CHANGELOG.md DELETED
@@ -1,91 +0,0 @@
1
- # @inploi/plugin-chatbot
2
-
3
- ## 2.1.0
4
-
5
- ### Minor Changes
6
-
7
- - Support hues for colouring the chatbot
8
-
9
- ## 2.0.0
10
-
11
- ### Patch Changes
12
-
13
- - 2975c09: Replace `zustand` with `idb-keyval` and `@preact/signals` to better utilise indexeddb and reduce bundle size
14
- - cc46781: Track started applications via the new `analytics` service exposed by sdk
15
- - Updated dependencies [d8dc36f]
16
- - Updated dependencies [d8dc36f]
17
- - @inploi/sdk@1.5.0
18
- - @inploi/core@1.5.6
19
-
20
- ## 1.0.7
21
-
22
- ### Patch Changes
23
-
24
- - Updated dependencies
25
- - @inploi/core@1.5.5
26
- - @inploi/sdk@1.4.6
27
-
28
- ## 1.0.6
29
-
30
- ### Patch Changes
31
-
32
- - Updated dependencies [3cbdf6b]
33
- - @inploi/core@1.5.4
34
- - @inploi/sdk@1.4.5
35
-
36
- ## 1.0.5
37
-
38
- ### Patch Changes
39
-
40
- - Implement map of node types
41
- - Updated dependencies
42
- - @inploi/core@1.5.3
43
- - @inploi/sdk@1.4.4
44
-
45
- ## 1.0.4
46
-
47
- ### Patch Changes
48
-
49
- - Updated dependencies
50
- - @inploi/core@1.5.2
51
- - @inploi/sdk@1.4.3
52
-
53
- ## 1.0.3
54
-
55
- ### Patch Changes
56
-
57
- - Updated dependencies
58
- - @inploi/core@1.5.1
59
- - @inploi/sdk@1.4.2
60
-
61
- ## 1.0.2
62
-
63
- ### Patch Changes
64
-
65
- - Updated dependencies [ba05115]
66
- - @inploi/core@1.5.0
67
- - @inploi/sdk@1.4.1
68
-
69
- ## 1.0.1
70
-
71
- ### Patch Changes
72
-
73
- - e9c1677: (Following 1.0) rewrite exports to new plugin format
74
- - Updated dependencies [d0f1d33]
75
- - @inploi/sdk@1.0.1
76
-
77
- ## 1.0.0
78
-
79
- ### Patch Changes
80
-
81
- - d8a904e: Split SDK plugins into their own packages
82
- - Updated dependencies [5a34b5a]
83
- - Updated dependencies [5d1e92b]
84
- - Updated dependencies [5d1e92b]
85
- - Updated dependencies [df4f06d]
86
- - Updated dependencies [d5caf7e]
87
- - Updated dependencies [a582965]
88
- - Updated dependencies [d8a904e]
89
- - Updated dependencies [553e630]
90
- - @inploi/core@1.4.0
91
- - @inploi/sdk@1.0.0
package/bunfig.toml DELETED
@@ -1,2 +0,0 @@
1
- [test]
2
- preload = "./happydom.ts"
package/happydom.ts DELETED
@@ -1,10 +0,0 @@
1
- import { GlobalRegistrator } from '@happy-dom/global-registrator';
2
- import { IWindow } from 'happy-dom';
3
-
4
- GlobalRegistrator.register();
5
-
6
- declare global {
7
- interface Window {
8
- happyDOM: IWindow['happyDOM'];
9
- }
10
- }
package/index.html DELETED
@@ -1,29 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <title>Vite + Preact + TS</title>
8
- </head>
9
- <body
10
- style="
11
- font-family: 'Courier New', Courier, monospace;
12
- height: 100vh;
13
- display: flex;
14
- align-items: center;
15
- justify-content: center;
16
- "
17
- >
18
- <div>
19
- <h1 style="font-size: 2rem; letter-spacing: -0.02em; text-align: center">Super legit careers hub</h1>
20
- <p>Welcome, start applying by clicking on one of the buttons below</p>
21
-
22
- <button onclick="chatbot.startApplication({ jobId: '150153' })">Apply for Compass job</button>
23
- <button onclick="chatbot.startApplication({ jobId: '1' })">Apply for Wagamama job</button>
24
- <button onclick="chatbot.startApplication({ jobId: 'test' })">Apply for job Test flow</button>
25
- </div>
26
-
27
- <script type="module" src="/src/index.dev.ts"></script>
28
- </body>
29
- </html>
@@ -1,82 +0,0 @@
1
- import { defineConfig, devices } from '@playwright/test';
2
- import dotenv from 'dotenv';
3
- import path from 'path';
4
-
5
- /**
6
- * Read environment variables from file.
7
- * https://github.com/motdotla/dotenv
8
- */
9
- dotenv.config({ path: path.resolve(process.cwd(), '.env.test') });
10
-
11
- const PORT = 3333;
12
-
13
- /**
14
- * See https://playwright.dev/docs/test-configuration.
15
- */
16
- export default defineConfig({
17
- testDir: './tests',
18
- /* Run tests in files in parallel */
19
- fullyParallel: true,
20
- /* Fail the build on CI if you accidentally left test.only in the source code. */
21
- forbidOnly: !!process.env.CI,
22
- /* Retry on CI only */
23
- retries: process.env.CI ? 2 : 0,
24
- /* Opt out of parallel tests on CI. */
25
- workers: process.env.CI ? 1 : undefined,
26
- /* Reporter to use. See https://playwright.dev/docs/test-reporters */
27
- reporter: 'html',
28
- /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
29
- use: {
30
- /* Base URL to use in actions like `await page.goto('/')`. */
31
- baseURL: process.env.BASE_URL || `http://localhost:${PORT}`,
32
-
33
- /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
34
- trace: 'on-first-retry',
35
- },
36
-
37
- /* Configure projects for major browsers */
38
- projects: [
39
- {
40
- name: 'chromium',
41
- use: { ...devices['Desktop Chrome'] },
42
- },
43
-
44
- // {
45
- // name: 'firefox',
46
- // use: { ...devices['Desktop Firefox'] },
47
- // },
48
-
49
- // {
50
- // name: 'webkit',
51
- // use: { ...devices['Desktop Safari'] },
52
- // },
53
-
54
- /* Test against mobile viewports. */
55
- {
56
- name: 'Mobile Chrome',
57
- use: { ...devices['Pixel 5'] },
58
- },
59
- {
60
- name: 'Mobile Safari',
61
- use: { ...devices['iPhone 12'] },
62
- },
63
-
64
- /* Test against branded browsers. */
65
- // {
66
- // name: 'Microsoft Edge',
67
- // use: { ...devices['Desktop Edge'], channel: 'msedge' },
68
- // },
69
- // {
70
- // name: 'Google Chrome',
71
- // use: { ...devices['Desktop Chrome'], channel: 'chrome' },
72
- // },
73
- ],
74
-
75
- /* Run your local dev server before starting the tests */
76
- webServer: process.env.BASE_URL
77
- ? undefined
78
- : {
79
- command: `pnpm dev --port ${PORT} --mode test`,
80
- port: PORT,
81
- },
82
- });
@@ -1,7 +0,0 @@
1
- module.exports = {
2
- plugins: {
3
- tailwindcss: {},
4
- autoprefixer: {},
5
- 'tailwindcss/nesting': {},
6
- },
7
- };
@@ -1,46 +0,0 @@
1
- import { FlowNode } from '@inploi/core/flows';
2
- import { ApiClient } from '@inploi/sdk';
3
- import { any, array, coerce, number, object, optional, parse, string } from 'valibot';
4
-
5
- export type JobApplication = {
6
- job: {
7
- id: string; // internal inploi job id
8
- title: string; //job title
9
- };
10
- company: {
11
- name: string; // company name
12
- logo?: string; // company logo
13
- };
14
- flow: {
15
- id: string; // flow id
16
- version: number; // hardcode the version as 0 until we have versioning
17
- nodes: FlowNode[]; // new jsonb flow nodes, no need for the legacy parser to run
18
- };
19
- };
20
-
21
- const ApplicationSchema = object({
22
- job: object({
23
- id: coerce(string(), String),
24
- title: string(),
25
- }),
26
- company: object({
27
- name: string(),
28
- logo: optional(string()),
29
- }),
30
- flow: object({
31
- id: coerce(string(), String),
32
- nodes: array(any()),
33
- version: number(),
34
- }),
35
- });
36
-
37
- export async function getApplicationData({
38
- jobId,
39
- apiClient,
40
- }: {
41
- jobId: string;
42
- apiClient: ApiClient;
43
- }): Promise<JobApplication> {
44
- const rawData = await apiClient.fetch(`/flow/job/${jobId}`);
45
- return parse(ApplicationSchema, rawData);
46
- }
@@ -1,9 +0,0 @@
1
- export const CHATBOT_ELEMENT_ID = 'isdk';
2
-
3
- export const HEADER_HEIGHT = 44;
4
-
5
- export const ERROR_MESSAGES = {
6
- not_in_local_storage: 'Application not found in local storage',
7
- invalid_end_node: 'Unexpected node type to finish flow',
8
- no_submissions: 'Application ended without any fields submitted',
9
- };
package/src/chatbot.css DELETED
@@ -1,93 +0,0 @@
1
- #isdk {
2
- font-size: 16px;
3
- font-family: sans-serif;
4
-
5
- /* Lowest colour */
6
- --i-lowest: 0 0% 100%;
7
-
8
- /* Neutral colors */
9
- --i-n-1: 206 30% 98.8%;
10
- --i-n-2: 210 16.7% 97.6%;
11
- --i-n-3: 209 13.3% 95.3%;
12
- --i-n-4: 209 12.2% 93.2%;
13
- --i-n-5: 208 11.7% 91.1%;
14
- --i-n-6: 208 11.3% 88.9%;
15
- --i-n-7: 207 11.1% 85.9%;
16
- --i-n-8: 205 10.7% 78%;
17
- --i-n-9: 206 6% 56.1%;
18
- --i-n-10: 206 5.8% 52.3%;
19
- --i-n-11: 206 6% 43.5%;
20
- --i-n-12: 206 24% 9%;
21
-
22
- /** Error colours */
23
- --i-e-1: 340 100% 99%;
24
- --i-e-2: 353 100% 98%;
25
- --i-e-3: 351 91% 96%;
26
- --i-e-4: 351 100% 93%;
27
- --i-e-5: 350 100% 90%;
28
- --i-e-6: 351 80% 86%;
29
- --i-e-7: 349 68% 81%;
30
- --i-e-8: 348 61% 74%;
31
- --i-e-9: 348 75% 59%;
32
- --i-e-10: 347 70% 55%;
33
- --i-e-11: 345 70% 47%;
34
- --i-e-12: 344 63% 24%;
35
-
36
- @tailwind base;
37
- @tailwind components;
38
- @tailwind utilities;
39
- @tailwind variants;
40
-
41
- @layer base {
42
- --tw-content: '';
43
- font-family:
44
- system-ui,
45
- -apple-system,
46
- BlinkMacSystemFont,
47
- Segoe UI,
48
- Roboto,
49
- Oxygen,
50
- Ubuntu,
51
- Cantarell,
52
- Open Sans,
53
- Helvetica Neue,
54
- sans-serif;
55
-
56
- * {
57
- box-sizing: border-box;
58
- border-style: solid;
59
- border-width: 0;
60
- -webkit-tap-highlight-color: transparent;
61
- }
62
-
63
- ::before,
64
- ::after {
65
- box-sizing: border-box;
66
- }
67
-
68
- :is(ul, ol) {
69
- list-style: none;
70
- padding: 0;
71
- margin: 0;
72
- }
73
-
74
- :is(p) {
75
- margin: 0;
76
- padding: 0;
77
- }
78
-
79
- :is(li) {
80
- margin: 0;
81
- padding: 0;
82
- list-style: none;
83
- }
84
-
85
- :is(button) {
86
- margin: 0;
87
- padding: 0;
88
- border: unset;
89
- background: unset;
90
- text-align: unset;
91
- }
92
- }
93
- }
@@ -1,28 +0,0 @@
1
- import { CHATBOT_ELEMENT_ID } from './chatbot.constants';
2
-
3
- export const createChatbotDomManager = () => {
4
- let chatbotElement: HTMLDivElement | null = null;
5
- const styleElements: HTMLStyleElement[] = [];
6
-
7
- return {
8
- getOrCreateChatbotElement: () => {
9
- if (chatbotElement) return chatbotElement;
10
-
11
- const newElement = document.createElement('div');
12
- document.body.appendChild(newElement);
13
- newElement.id = CHATBOT_ELEMENT_ID;
14
- chatbotElement = newElement;
15
- return newElement;
16
- },
17
- addStyle: (css: string, id: string) => {
18
- const head = document.head;
19
- const element = document.createElement('style');
20
- element.id = id;
21
- element.innerHTML = css;
22
-
23
- styleElements.push(element);
24
- head.appendChild(element);
25
- },
26
- };
27
- };
28
- export type ChatbotDomManager = ReturnType<typeof createChatbotDomManager>;
@@ -1,17 +0,0 @@
1
- import { createStore, get, set } from 'idb-keyval';
2
-
3
- import { JobApplication } from './chatbot.api';
4
- import { ApplicationData, getCacheKey } from './chatbot.state';
5
-
6
- const store = createStore('inploi', 'applications');
7
-
8
- export const idb = {
9
- getApplicationData: async (application: JobApplication) => {
10
- const key = getCacheKey(application);
11
- return await get<ApplicationData>(key, store);
12
- },
13
- setApplicationData: async (params: { application: JobApplication; data: ApplicationData }) => {
14
- const key = getCacheKey(params.application);
15
- return await set(key, params.data, store);
16
- },
17
- };
@@ -1,114 +0,0 @@
1
- import { invariant } from '@inploi/core/common';
2
- import { batch, signal } from '@preact/signals';
3
-
4
- import { JobApplication } from './chatbot.api';
5
- import { idb } from './chatbot.idb';
6
- import { DistributivePick, getHeadOrThrow } from './chatbot.utils';
7
- import { ChatInput } from './ui/chat-input/chat-input';
8
- import { ChatbotInput } from './ui/chat-input/chat-input';
9
-
10
- export const getCacheKey = (application: JobApplication) =>
11
- [application.job.id, application.flow.id, application.flow.version].join('/');
12
-
13
- export type ViewState = 'maximised' | 'minimised';
14
- export const viewState = signal<ViewState>('maximised');
15
-
16
- export const inputHeight = signal(53);
17
-
18
- export type StartedJobApplication = JobApplication & { data: ApplicationData };
19
-
20
- type CurrentApplication =
21
- | { state: 'idle'; application?: never }
22
- | { state: 'loading'; application?: never }
23
- | { state: 'loaded'; application: StartedJobApplication }
24
- | { state: 'error'; application?: never; error: string };
25
-
26
- const currentApplication = signal<CurrentApplication>({ state: 'idle' });
27
-
28
- const updateApplicationData = async (updateFn: (data: ApplicationData) => ApplicationData) => {
29
- const { state, application } = currentApplication.value;
30
- if (state !== 'loaded') return;
31
- invariant(application, 'No application to update');
32
- const newData = updateFn(application.data);
33
- const newApplication = { ...application, data: newData };
34
- currentApplication.value = { state, application: newApplication };
35
- await idb.setApplicationData({ application, data: newData });
36
- };
37
-
38
- export const application = {
39
- current$: currentApplication,
40
- start: async (application: JobApplication) => {
41
- const data = (await idb.getApplicationData(application)) ?? createNewApplicationData(application);
42
- batch(() => {
43
- viewState.value = 'maximised';
44
- currentApplication.value = { state: 'loaded', application: { ...application, data } };
45
- });
46
- data.isFinished = false;
47
- idb.setApplicationData({ application, data });
48
- },
49
- cancel: () => {
50
- currentApplication.value = { state: 'idle' };
51
- },
52
- markAsFinished: () => updateApplicationData(data => ({ ...data, isFinished: true })),
53
- setCurrentNodeId: (currentNodeId: string) => updateApplicationData(data => ({ ...data, currentNodeId })),
54
- restart: () => {
55
- const { state, application } = currentApplication.value;
56
- if (state !== 'loaded') throw new Error('Application cannot be restarted: not in valid state');
57
- const data = createNewApplicationData(application);
58
- currentApplication.value = { state, application: { ...application, data } };
59
- idb.setApplicationData({ application, data });
60
- },
61
- addMessage: (message: ChatMessage, groupId?: string) => {
62
- const newMessage = { ...message, groupId };
63
- return updateApplicationData(data => ({ ...data, messages: [...data.messages, newMessage] }));
64
- },
65
- /** Removes from the last message backwards, all the messages that have the groupId passed, until it reaches one that doesn't */
66
- removeLastGroupMessagesById: (groupId: string) => {
67
- const { state, application } = currentApplication.value;
68
- if (state !== 'loaded') throw new Error('Application cannot be restarted: not in valid state');
69
-
70
- const messages = [...application.data.messages];
71
- let i = messages.length - 1;
72
- while (i >= 0 && messages[i] && messages[i]?.groupId === groupId) {
73
- messages.pop();
74
- i--;
75
- }
76
- application.data.messages = messages;
77
- idb.setApplicationData({ application, data: application.data });
78
- },
79
- setSubmission: (fieldKey: string, submission: ApplicationSubmission) =>
80
- updateApplicationData(data => ({ ...data, submissions: { ...data.submissions, [fieldKey]: submission } })),
81
- setInput: (input: ChatInput | undefined) => updateApplicationData(data => ({ ...data, currentInput: input })),
82
- };
83
-
84
- export type MessageAuthor = 'bot' | 'user';
85
-
86
- type SystemMessage = { type: 'system'; text: string; variant: 'info' | 'warning' | 'error' | 'success' };
87
- type TextMessage = { author: MessageAuthor; type: 'text'; text: string };
88
- type ImageMessage = { author: MessageAuthor; type: 'image'; url: string; width: number; height: number };
89
- type FileMessage = { author: MessageAuthor; type: 'file'; fileName: string; fileSizeKb: number };
90
- export type ChatMessage = TextMessage | ImageMessage | SystemMessage | FileMessage;
91
-
92
- export type ApplicationSubmission = DistributivePick<ChatbotInput, 'type' | 'value'>;
93
-
94
- export type KeyToSubmissionMap = {
95
- [key: string]: ApplicationSubmission;
96
- };
97
-
98
- /** Dynamic part of an application */
99
- export type ApplicationData = {
100
- /** History of messages left in the chat */
101
- messages: (ChatMessage & { groupId?: string })[];
102
- submissions: KeyToSubmissionMap;
103
- currentNodeId: string;
104
- /** Needs to be separate because a node can have many inputs */
105
- currentInput?: ChatInput;
106
- isFinished: boolean;
107
- };
108
-
109
- const createNewApplicationData = (application: JobApplication): ApplicationData => ({
110
- messages: [],
111
- submissions: {},
112
- currentNodeId: getHeadOrThrow(application.flow.nodes).id,
113
- isFinished: false,
114
- });
package/src/chatbot.ts DELETED
@@ -1,59 +0,0 @@
1
- import { createPlugin } from '@inploi/sdk';
2
- import { h, render } from 'preact';
3
- import { Chatbot } from '~/ui/chatbot';
4
-
5
- import { getApplicationData } from './chatbot.api';
6
- import tailwind from './chatbot.css?inline';
7
- import { ChatbotDomManager, createChatbotDomManager } from './chatbot.dom';
8
- import { application } from './chatbot.state';
9
- import { formatCssVariables, generatePalette } from './style/palette';
10
-
11
- export const chatbotPlugin = ({
12
- _internal_domManager: dom = createChatbotDomManager(),
13
- hue,
14
- }: {
15
- geolocationApiKey?: string;
16
- hue: number;
17
- _internal_domManager?: ChatbotDomManager;
18
- }) =>
19
- createPlugin(({ apiClient, logger, analytics }) => {
20
- let prepared = false;
21
- const renderAndPrepare = () => {
22
- const chatbotElement = dom.getOrCreateChatbotElement();
23
- // Add styles generated by tailwind
24
- dom.addStyle(tailwind, 'inploi-chatbot-style');
25
- // Add dynamic styles generated by the plugin
26
- dom.addStyle(formatCssVariables(generatePalette(hue)), 'inploi-chatbot-theme');
27
- render(h(Chatbot, { apiClient, logger, analytics }), chatbotElement);
28
- prepared = true;
29
- };
30
-
31
- return {
32
- /** Optionally eagerly renders the interface ahead of application requests. */
33
- prepare: async () => {
34
- try {
35
- if (prepared) return;
36
- renderAndPrepare();
37
- logger.info('Chatbot plugin prepared');
38
- } catch (error) {
39
- console.error(error);
40
- logger.error('Error preparing chatbot plugin', error);
41
- }
42
- },
43
- startApplication: async ({ jobId }: { jobId: string }) => {
44
- try {
45
- application.cancel();
46
- getApplicationData({ jobId, apiClient }).then(application.start);
47
-
48
- if (!prepared) renderAndPrepare();
49
- } catch (error) {
50
- console.error(error);
51
- logger.error('Error starting application', error);
52
- }
53
- },
54
- closeApplication: async () => {
55
- logger.info('Closing application from an external source');
56
- application.cancel();
57
- },
58
- };
59
- });