bibot 1.0.3 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. package/dist/components/bibot.js +171 -0
  2. package/dist/components/bibot.js.map +1 -0
  3. package/dist/config/appStateEnums.js +5 -10
  4. package/dist/config/endpointEnums.js +22 -27
  5. package/dist/config/index.js +5 -38
  6. package/dist/config/statusCode.js +44 -49
  7. package/dist/context/AppContext.js +56 -73
  8. package/dist/context/index.js +3 -16
  9. package/dist/hooks/index.d.ts +0 -1
  10. package/dist/hooks/index.js +4 -38
  11. package/dist/hooks/index.js.map +1 -1
  12. package/dist/hooks/mobileView.js +18 -33
  13. package/dist/hooks/usePluginFactory.js +77 -60
  14. package/dist/index.d.ts +2 -1
  15. package/dist/index.js +6 -9
  16. package/dist/index.js.map +1 -1
  17. package/dist/reducers/appReducer.js +22 -24
  18. package/dist/reducers/index.js +3 -16
  19. package/dist/services/index.js +3 -16
  20. package/dist/services/plugin-api.js +182 -179
  21. package/dist/types/coreInterfaces.d.ts +10 -1
  22. package/dist/types/coreInterfaces.js +2 -5
  23. package/dist/types/index.js +3 -16
  24. package/dist/utils/index.js +3 -27
  25. package/dist/utils/sessionManager.js +12 -16
  26. package/dist/utils/trimWhitespace.js +11 -15
  27. package/package.json +54 -50
  28. package/.babelrc +0 -7
  29. package/.vscode/settings.json +0 -5
  30. package/dist/bibot.js +0 -173
  31. package/dist/bibot.js.map +0 -1
  32. package/dist/hooks/useBiBotChatBot.d.ts +0 -29
  33. package/dist/hooks/useBiBotChatBot.js +0 -206
  34. package/dist/hooks/useBiBotChatBot.js.map +0 -1
  35. package/dist/index.css +0 -36
  36. package/dist/styles/RegisterPageStyle.css +0 -63
  37. package/dist/styles/adminPortal.css +0 -26
  38. package/dist/styles/appConfig.css +0 -90
  39. package/dist/styles/buttonStyle.css +0 -27
  40. package/dist/styles/chatStyle.css +0 -140
  41. package/dist/styles/index.css +0 -82
  42. package/dist/styles/predefinedStyle.css +0 -35
  43. package/dist/styles/themeStyle.css +0 -42
  44. package/dist/styles/training.css +0 -86
  45. package/example/README.md +0 -46
  46. package/example/package-lock.json +0 -18173
  47. package/example/package.json +0 -47
  48. package/example/public/favicon.ico +0 -0
  49. package/example/public/index.html +0 -43
  50. package/example/public/logo192.png +0 -0
  51. package/example/public/logo512.png +0 -0
  52. package/example/public/manifest.json +0 -25
  53. package/example/public/robots.txt +0 -3
  54. package/example/src/App.css +0 -38
  55. package/example/src/App.test.tsx +0 -9
  56. package/example/src/App.tsx +0 -28
  57. package/example/src/index.css +0 -13
  58. package/example/src/index.tsx +0 -13
  59. package/example/src/logo.svg +0 -1
  60. package/example/src/react-app-env.d.ts +0 -1
  61. package/example/tsconfig.json +0 -26
  62. package/src/bibot.tsx +0 -111
  63. package/src/config/appStateEnums.ts +0 -3
  64. package/src/config/endpointEnums.ts +0 -28
  65. package/src/config/index.ts +0 -5
  66. package/src/config/statusCode.ts +0 -49
  67. package/src/context/AppContext.tsx +0 -66
  68. package/src/context/index.ts +0 -3
  69. package/src/hooks/index.ts +0 -5
  70. package/src/hooks/mobileView.tsx +0 -17
  71. package/src/hooks/useBiBotChatBot.tsx +0 -107
  72. package/src/hooks/usePluginFactory.tsx +0 -38
  73. package/src/index.css +0 -36
  74. package/src/index.tsx +0 -3
  75. package/src/reducers/appReducer.ts +0 -16
  76. package/src/reducers/index.ts +0 -4
  77. package/src/services/index.ts +0 -2
  78. package/src/services/plugin-api.tsx +0 -120
  79. package/src/styles/RegisterPageStyle.css +0 -63
  80. package/src/styles/adminPortal.css +0 -26
  81. package/src/styles/appConfig.css +0 -90
  82. package/src/styles/buttonStyle.css +0 -27
  83. package/src/styles/chatStyle.css +0 -140
  84. package/src/styles/index.css +0 -82
  85. package/src/styles/predefinedStyle.css +0 -35
  86. package/src/styles/themeStyle.css +0 -42
  87. package/src/styles/training.css +0 -86
  88. package/src/types/coreInterfaces.ts +0 -69
  89. package/src/types/index.ts +0 -4
  90. package/src/utils/index.ts +0 -2
  91. package/src/utils/sessionManager.tsx +0 -15
  92. package/src/utils/trimWhitespace.ts +0 -11
  93. package/tsconfig.json +0 -25
  94. package/webpack.config.js +0 -19
  95. /package/dist/{bibot.d.ts → components/bibot.d.ts} +0 -0
@@ -1,107 +0,0 @@
1
- import { message } from 'antd'
2
- import { appStateEnums } from '../config/appStateEnums'
3
- import React, { useEffect, useRef, useState, useContext, useCallback } from 'react'
4
- import { AppContext } from '../context/AppContext'
5
-
6
- import { v4 as uuidv4 } from 'uuid'
7
- import { askBiBot, getRemoteClientChatBubbleConfig, getRemoteClientChatPredefinedQuestions } from '../services/plugin-api'
8
- interface UseBiBotChatBotProps {
9
- clientId: string
10
- }
11
-
12
- interface ChatBubbleConfigProps {
13
- bgColor?: string,
14
- color?: string,
15
- title?: string,
16
- logo_url?: string
17
- }
18
- const useBiBotChatBot = ({ clientId }: UseBiBotChatBotProps) => {
19
- const [predefinedQuestions, setPredefinedQuestions] = useState<string[]>([]) // State to store predefined questions
20
- const [showPredefinedQuestions, setShowPredefinedQuestions] = useState(true); // State to toggle predefined questions
21
- const { state, dispatch } = useContext(AppContext)
22
- const { chatIsOpen } = state
23
- const [messages, setMessages] = useState<Array<{ sender: 'user' | 'bot', text: string }>>([])
24
- const [userInput, setUserInput] = useState('')
25
- const [isLoading, setIsLoading] = useState(false)
26
- const messageEndRef = useRef<HTMLDivElement>(null)
27
- const [chatBubbleConfig, setChatBubbleConfig] = useState<ChatBubbleConfigProps>()
28
-
29
- // Function to handle selecting a predefined question
30
- const handlePredefinedQuestionSelect = (question: any) => {
31
- setUserInput(question);
32
- sendInputInquiry();
33
- setShowPredefinedQuestions(false); // Hide predefined questions after selection
34
- }
35
-
36
- const getChatBubbleConfig = useCallback(async()=>{
37
- const remotePredefinedQuestions = await getRemoteClientChatPredefinedQuestions({client_id: clientId})
38
- if (remotePredefinedQuestions){
39
- setPredefinedQuestions(remotePredefinedQuestions)
40
- }
41
- const remoteChatBubbleConfig = await getRemoteClientChatBubbleConfig({client_id: clientId})
42
- if (remoteChatBubbleConfig){
43
- setChatBubbleConfig(remoteChatBubbleConfig)
44
- }
45
- },[clientId])
46
-
47
- useEffect(()=>{
48
- void getChatBubbleConfig()
49
- }, [getChatBubbleConfig])
50
-
51
- useEffect(() => {
52
- if (messageEndRef?.current) { messageEndRef.current.scrollIntoView({ behavior: 'smooth' }) }
53
- }, [messages])
54
-
55
- const toggleChat = () => {
56
- dispatch({ type: appStateEnums.BIBOT, chatIsOpen: !chatIsOpen })
57
- }
58
-
59
- const handleUserInput = (e: React.ChangeEvent<HTMLInputElement>) => {
60
- setUserInput(e.target.value)
61
- }
62
-
63
- async function sendInputInquiry () {
64
- setIsLoading(true)
65
- setUserInput('')
66
- try {
67
- if (userInput.trim()) {
68
- // dispatch({ type: appStateEnums.BIBOT, chatIsOpen: true })
69
- setMessages(messages => [...messages, { sender: 'user', text: userInput }])
70
- const response = await askBiBot({
71
- client_id: clientId,
72
- q: userInput.trim(),
73
- session_id: state.sessionId,
74
- chat_id: uuidv4()
75
- })
76
- setMessages(messages => [...messages, { sender: 'bot', text: response }])
77
- }
78
- } catch (error: any) {
79
- void message.error(error?.message ?? 'Failed to get response from server')
80
- } finally {
81
- setIsLoading(false)
82
- }
83
- }
84
-
85
- const handleKeyPress = async (e: React.KeyboardEvent<HTMLInputElement>) => {
86
- if (e.key === 'Enter' && !isLoading) {
87
- await sendInputInquiry()
88
- }
89
- }
90
- return {
91
- chatIsOpen,
92
- messages,
93
- isLoading,
94
- messageEndRef,
95
- userInput,
96
- handleUserInput,
97
- handleKeyPress,
98
- toggleChat,
99
- sendInputInquiry,
100
- chatBubbleConfig,
101
- showPredefinedQuestions,
102
- predefinedQuestions,
103
- handlePredefinedQuestionSelect,
104
- }
105
- }
106
-
107
- export { useBiBotChatBot }
@@ -1,38 +0,0 @@
1
- import axios from 'axios';
2
- import { endpoints } from '../config/endpointEnums';
3
- import React from 'react';
4
- const inferenceBaseURL = endpoints.inference;
5
-
6
- export const createPluginAxiosInstance = (params = {}, headers = {}) => {
7
- const instance = axios.create({
8
- baseURL: inferenceBaseURL,
9
- timeout: 60000, // 1 minute
10
- headers: {
11
- 'Content-Type': 'application/json',
12
- ...headers
13
- },
14
- ...params
15
- });
16
-
17
-
18
- instance.interceptors.response.use(
19
- (response) => {
20
- return response
21
- },
22
- async (error) => {
23
- let errMsg = 'An unknown error occurred'
24
- if (error.response) {
25
- errMsg = error.response.data.message
26
- } else if (error.request) {
27
- errMsg = 'No response received from the server.'
28
- } else {
29
- errMsg = `Error setting up the request: ${error.message}`
30
- }
31
- return await Promise.reject(new Error(errMsg))
32
- }
33
- )
34
-
35
- return instance
36
- }
37
-
38
-
package/src/index.css DELETED
@@ -1,36 +0,0 @@
1
- body {
2
- margin: 0;
3
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5
- sans-serif;
6
- -webkit-font-smoothing: antialiased;
7
- -moz-osx-font-smoothing: grayscale;
8
- }
9
-
10
-
11
- *{
12
- margin: 0;
13
- padding: 0;
14
- box-sizing: border-box;
15
- }
16
- code {
17
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
18
- monospace;
19
- }
20
-
21
- .upload-component {
22
- .drop-area {
23
- border: 2px dashed #ccc;
24
- border-radius: 5px;
25
- padding: 20px;
26
- text-align: center;
27
- cursor: pointer;
28
- &:hover, &:focus {
29
- border-color: #007bff;
30
- }
31
- }
32
-
33
- .uploading { background-color: #fff3cd; }
34
- .completed { background-color: #d4edda; }
35
- .error { background-color: #f8d7da; }
36
- }
package/src/index.tsx DELETED
@@ -1,3 +0,0 @@
1
- import React from 'react';
2
- import BiBot from './bibot';
3
- export default BiBot;
@@ -1,16 +0,0 @@
1
- import { appStateEnums } from '../config/appStateEnums'
2
- import type { AppStates, AppAction } from 'types'
3
- import React from 'react';
4
-
5
- export const appReducer = (state: AppStates, action: AppAction): AppStates => {
6
- console.log('This is the appReducer state', state, action)
7
- switch (action.type) {
8
- case appStateEnums.BIBOT:
9
- return {
10
- ...state,
11
- chatIsOpen: action.chatIsOpen
12
- }
13
- default:
14
- return state
15
- }
16
- }
@@ -1,4 +0,0 @@
1
- // created from 'create-ts-index'
2
-
3
- export * from './appReducer'
4
-
@@ -1,2 +0,0 @@
1
- // export * from './bibot'
2
- export * from './plugin-api'
@@ -1,120 +0,0 @@
1
- import { domain, resources } from '../config/endpointEnums'
2
- import React from 'react';
3
- // import { createPluginAxiosInstance } from '../hooks/usePluginFactory'
4
-
5
- // const pluginAxiosInstance=createPluginAxiosInstance()
6
-
7
- interface Q_DATA_TYPE {
8
- client_id: string
9
- q: string
10
- endSession?: boolean
11
- session_id: string
12
- chat_id: string
13
- tries?: number
14
- }
15
-
16
- interface RemoteChatBubbleConfigProps {
17
- bgColor: string,
18
- chatColor: string,
19
- title: string,
20
- userImage: string
21
- }
22
-
23
- async function askTimedOutBiBot(data: Q_DATA_TYPE): Promise<string> {
24
- try {
25
- return 'Hello'
26
- // const path=`${domain.bibot}${resources.timedOutLocalQ}`
27
- // const response=await pluginAxiosInstance.post<any>(path, data)
28
- // console.log(response)
29
- // return response.data.message
30
- } catch (error: any) {
31
- console.log(error.message)
32
- return error.message
33
- }
34
- }
35
-
36
- async function askBiBot(data: Q_DATA_TYPE): Promise<string> {
37
- try {
38
- // const path=`${domain.inference}${resources.q}`
39
- // const response=await pluginAxiosInstance.post<any>(path, data)
40
- // console.log(response)
41
- // return response.data.message
42
- return 'Hello'
43
- } catch (error1: any) {
44
- console.log(error1.message)
45
- if (error1.code==='ECONNABORTED'||error1.message.includes('Endpoint request timed out')) {
46
- try {
47
- return await askTimedOutBiBot({
48
- ...data,
49
- tries: 2
50
- })
51
- } catch (error2: any) {
52
- if (error2.code==='ECONNABORTED'||error2.message.includes('Endpoint request timed out')) {
53
- try {
54
- return await askTimedOutBiBot({
55
- ...data,
56
- tries: 3
57
- })
58
- } catch (error3: any) {
59
- return error3.message
60
- }
61
- } else {
62
- return error2.message
63
- }
64
- }
65
- } else {
66
- return error1.message
67
- }
68
- }
69
- }
70
- // TODO: Emmanuel fix the default returned values, especially the userImage to a default robot image
71
- async function getRemoteClientChatBubbleConfig(params: { client_id: string }): Promise<RemoteChatBubbleConfigProps> {
72
- try {
73
- return {
74
- bgColor: 'white',
75
- chatColor: 'blue',
76
- title: 'ChatBot',
77
- userImage: 'string'
78
- }
79
- // const path=`${domain.inference}${resources.chatBubble}`
80
- // const response=await pluginAxiosInstance.get<any>(path, { params })
81
- // return response.data
82
- } catch (error: any) {
83
- return {
84
- bgColor: 'white',
85
- chatColor: 'blue',
86
- title: 'ChatBot',
87
- userImage: 'string'
88
- }
89
- }
90
- }
91
-
92
- async function getRemoteClientChatPredefinedQuestions(params: { client_id: string }): Promise<string[]> {
93
- try {
94
- return ['Hello']
95
- // const path=`${domain.inference}${resources.predefinedQ}`
96
- // const response=await pluginAxiosInstance.get<any>(path, { params })
97
- // return response.data.predefined_messages
98
- } catch (error: any) {
99
- return ['These are placeholders', 'They will be removed in production', 'This will be empty if there are no predefined questions', 'So hide if there are no predefined questions']
100
- }
101
- }
102
-
103
- async function GetPredefinedQuestion (){
104
- const clientId = '6c74b4bb-0395-4751-a55f-7d065d67c56b'
105
- try {
106
- return [{question: "q", answer: "a"}]
107
- // const path = `${domain.inference}${resources.predefinedQ}?client_id=${clientId}`
108
- // const response = await pluginAxiosInstance.get(path)
109
- // return response.data
110
- } catch (error) {
111
- console.error('Error fetching subscription:', error)
112
- }
113
- }
114
-
115
- export {
116
- askBiBot,
117
- getRemoteClientChatBubbleConfig,
118
- getRemoteClientChatPredefinedQuestions,
119
- GetPredefinedQuestion
120
- }
@@ -1,63 +0,0 @@
1
-
2
- .amplify-button--primary {
3
- background-color: #0fa781;
4
- }
5
-
6
- .preAuditLogo-on-registerPage{
7
- max-height: 50px;
8
- margin-bottom: 20px;
9
- }
10
- .amplify-tabs-item[data-state=active] {
11
- color: #fff;
12
- border-color: #0fa781;
13
- }
14
- .amplify-tabs-item[data-state=active]:hover {
15
- color: #fff;
16
- }
17
-
18
- .amplify-tabs-item:hover {
19
- color: #00152a;
20
- }
21
-
22
- [data-amplify-authenticator] [data-amplify-router] {
23
- background-color: #ffffff;
24
- border-color: #b9eee1;
25
- }
26
- .amplify-tabs-item[data-spacing=equal]{
27
-
28
- }
29
- .amplify-button--link {
30
- color: #00152a;
31
- }
32
- .amplify-button--link:hover {
33
- color: #00152a;
34
- background-color: #fff;
35
- }
36
-
37
- .amplify-input, .amplify-input:focus {
38
- border-color: #bed7f0;
39
- border: 1px solid;
40
- }
41
- .fieldContainer{
42
- display: flex;
43
- justify-content: space-between;
44
- flex-direction: row;
45
- }
46
- select, .amplify-field-group__outer-end .amplify-field-group__control, .amplify-field-group__outer-start .amplify-select__wrapper:not(:first-child) .amplify-select:not(:first-child), .amplify-field-group__outer-start--quiet .amplify-field-group__control, .amplify-field-group__outer-start .amplify-field-group__control:not(:first-child), .amplify-field-group :not(:first-child) .amplify-input {
47
- border-color: #c9ebe2;
48
- }
49
- .amplify-input{
50
- border-color: #c9ebe2;
51
- }
52
-
53
- .amplify-checkbox__icon {
54
- background-color: #c9ebe2;
55
- border-color: #c9ebe2;
56
- }
57
- .input-select-field{
58
- border-color: #0fa781;
59
- }
60
- .amplify-select{
61
- border-color: #c9ebe2 !important;
62
-
63
- }
@@ -1,26 +0,0 @@
1
- .useremail{
2
- width: 70px;
3
- white-space: nowrap;
4
- overflow: hidden;
5
- text-overflow: ellipsis;
6
- margin-top: 0;
7
- }
8
-
9
- /* Media query for screens smaller than 600px */
10
- @media screen and (max-width: 600px) {
11
- .hideOnMobile{
12
- display: none !important;
13
- }
14
- }
15
-
16
- /* Media query for screens between 600px and 900px */
17
- /* @media screen and (min-width: 600px) and (max-width: 900px) {
18
- .hideProfile{
19
- display: none;
20
- }
21
- } */
22
-
23
- /* Media query for screens larger than 1200px */
24
- @media screen and (min-width: 1200px) {
25
-
26
- }
@@ -1,90 +0,0 @@
1
- .mainContent{
2
- display: flex;
3
- width: 100%;
4
- justify-content: space-around;
5
- flex-wrap: wrap;
6
- }
7
- .firstSection{
8
- text-align: start;
9
- }
10
- .secondSection{
11
- display: flex;
12
- align-items: center;
13
- justify-content: center;
14
- }
15
- .previewSection{
16
- height: 100%;
17
- }
18
- input[type="file"] {
19
- display: none;
20
- }
21
- .inputfileButton{
22
- display: inline-block;
23
- align-items: center;
24
- /* background-color: #73767a; */
25
- border: none;
26
- border-radius: 5px;
27
- cursor: pointer;
28
- }
29
-
30
-
31
- /* Media query for screens smaller than 600px */
32
- @media screen and (max-width: 600px) {
33
- .mainContent{
34
- display: flex;
35
- width: 100%;
36
- flex-direction: column;
37
- justify-content: space-around;
38
- align-items: center;
39
- }
40
- .button{
41
- width: 100% !important;
42
- }
43
- .previewSection{
44
- width: 100%;
45
- margin-top: 30px;
46
- }
47
- .firstSection{
48
- width: 100%;
49
- text-align: start;
50
- margin-bottom: 50px;
51
- }
52
- .secondSection{
53
- width: 100%;
54
- display: flex;
55
- align-items: center;
56
- justify-content: center;
57
- text-align: start;
58
- }
59
- }
60
-
61
- /* Media query for screens between 600px and 900px */
62
- @media screen and (min-width: 600px) and (max-width: 900px) {
63
- .mainContent{
64
- display: flex;
65
- width: 100%;
66
- flex-direction: column;
67
- justify-content: space-around;
68
- align-items: center;
69
- }
70
- .previewSection{
71
- width: 100%;
72
- }
73
- .firstSection{
74
- width: 100%;
75
- text-align: start;
76
- margin-bottom: 50px;
77
- }
78
- .secondSection{
79
- width: 100%;
80
- display: flex;
81
- align-items: center;
82
- justify-content: center;
83
- text-align: start;
84
- }
85
- }
86
-
87
- /* Media query for screens larger than 1200px */
88
- @media screen and (min-width: 1200px) {
89
-
90
- }
@@ -1,27 +0,0 @@
1
- .button,
2
- .ant-btn.button {
3
- font-family: Arial, sans-serif;
4
- font-size: 14px;
5
- display: flex;
6
- justify-content: center;
7
- align-items: center;
8
- border-radius: 10px;
9
- border: 2px solid #d67632;
10
- outline: none;
11
- cursor: pointer;
12
- transition: background-color 0.3s, color 0.3s;
13
- background-color: #5f2d78;
14
- color: white;
15
- }
16
-
17
- .ant-popover-buttons {
18
- display: flex;
19
- justify-content: flex-end;
20
- background-color: #5f2d78;
21
- color: white
22
- }
23
-
24
- .ant-popover-button {
25
- margin: 8px;
26
- }
27
-
@@ -1,140 +0,0 @@
1
- .chat-bubble {
2
- position: fixed;
3
- bottom: 20px;
4
- right: 20px;
5
- z-index: 9999;
6
- }
7
-
8
- .chat-toggle {
9
- color: #fff;
10
- border-radius: 50%;
11
- height: 60px;
12
- width: 60px;
13
- display: flex;
14
- align-items: center;
15
- justify-content: center;
16
- }
17
-
18
- .chat-window {
19
- position: absolute;
20
- bottom: 50px;
21
- right: 25px;
22
- width: 350px;
23
- height: 500px;
24
- background-color: white;
25
- border: 1px solid #ddd;
26
- border-radius: 10px;
27
- /* padding: 10px; */
28
- box-shadow: 0 2px 10px rgba(0,0,0,0.2);
29
- display: flex;
30
- flex-direction: column;
31
- justify-content: space-between;
32
- }
33
-
34
- /* Existing styles... */
35
- .chat-header{
36
- height: 50px;
37
- border-top-left-radius: 8px;
38
- border-top-right-radius: 8px;
39
- display: flex;
40
- align-items: center;
41
- justify-content: flex-start;
42
- padding-inline: 15px;
43
- padding-block: 30px;
44
- }
45
- .message-list {
46
- height: calc(100% - 100px);
47
- overflow-y: auto;
48
- padding: 10px;
49
- display: flex;
50
- flex-grow: 1;
51
- flex-direction: column;
52
- }
53
-
54
- .message {
55
- margin-bottom: 10px;
56
- padding: 5px 10px;
57
- border-radius: 8px;
58
- max-width: 70%;
59
- }
60
-
61
- .message.user {
62
- background-color: #b8b8b8c6;
63
- align-self: flex-end;
64
- }
65
-
66
- .message.bot {
67
- background-color: #f0f0f0;
68
- align-self: flex-start;
69
- }
70
- textarea:focus, input:focus{
71
- outline: none;
72
- }
73
-
74
- /* Chat loader*/
75
- .loader {
76
- width: 12px;
77
- aspect-ratio: 1;
78
- border-radius: 50%;
79
- animation: l5 1s infinite linear alternate;
80
- }
81
- @keyframes l5 {
82
- 0% {box-shadow: 20px 0 #000, -20px 0 #0002;background: #000 }
83
- 33% {box-shadow: 20px 0 #000, -20px 0 #0002;background: #0002}
84
- 66% {box-shadow: 20px 0 #0002,-20px 0 #000; background: #0002}
85
- 100%{box-shadow: 20px 0 #0002,-20px 0 #000; background: #000 }
86
- }
87
-
88
-
89
- .input-area {
90
- display: flex;
91
- align-items: center;
92
- border-top: 1px solid #ddd;
93
- padding: 10px;
94
- border-bottom-left-radius: 8px;
95
- border-bottom-right-radius: 8px;
96
- }
97
-
98
- .input-area input {
99
- flex-grow: 1;
100
- border: none;
101
- background-color: transparent;
102
- /* border: 1px solid #ccc; */
103
- /* border-radius: 15px; */
104
- padding: 5px 10px;
105
- margin-right: 10px;
106
- }
107
-
108
- .input-area button {
109
- background-color: #007bff;
110
- color: white;
111
- border: none;
112
- border-radius: 15px;
113
- padding: 5px 10px;
114
- cursor: pointer;
115
- }
116
-
117
- /* Existing styles... */
118
-
119
- .loading-bubbles {
120
- display: flex;
121
- justify-content: center;
122
- align-items: center;
123
- }
124
-
125
- .bubble {
126
- width: 8px;
127
- height: 8px;
128
- border-radius: 50%;
129
- margin: 0 3px;
130
- animation: bounce 0.6s infinite alternate;
131
- }
132
-
133
- @keyframes bounce {
134
- from {
135
- transform: translateY(0);
136
- }
137
- to {
138
- transform: translateY(-15px);
139
- }
140
- }