Skip to content

Commit 3eddaac

Browse files
committed
Merge branch 'main' into pr/345
2 parents a7c0d09 + e9c9537 commit 3eddaac

12 files changed

Lines changed: 1326 additions & 1176 deletions

File tree

.babelrc

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424
},
2525
"extensions": [".ts", ".tsx"]
2626
}
27-
],
28-
"@babel/plugin-proposal-class-properties",
29-
"@babel/plugin-proposal-object-rest-spread"
27+
]
3028
]
3129
},
3230
"module": {
@@ -36,7 +34,7 @@
3634
"@babel/preset-env",
3735
{
3836
"targets": {
39-
"node": true
37+
"browsers": "last 2 versions"
4038
},
4139
"modules": false
4240
}
@@ -54,9 +52,7 @@
5452
},
5553
"extensions": [".ts", ".tsx"]
5654
}
57-
],
58-
"@babel/plugin-proposal-class-properties",
59-
"@babel/plugin-proposal-object-rest-spread"
55+
]
6056
]
6157
}
6258
}

README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ You can pass the following props to the `LiveChatLoaderProvider` provider:
132132

133133
## 💬 Supported Providers
134134

135-
Currently there are six supported providers:
135+
Currently there are seven supported providers:
136136

137137
<details>
138138
<summary id="help-scout">Help Scout</summary>
@@ -378,6 +378,34 @@ You can customise the Front placeholder icon by passing the following props to t
378378

379379
See the [official Front documentation](https://help.front.com/) for more details.
380380

381+
<summary id="hubspot">Hubspot</summary>
382+
383+
To use Hubspot import the `LiveChatLoaderProvider` and set the `provider` prop
384+
as `hubSpot` and the `providerKey` prop as your Hubspot API Key.
385+
386+
Then import the `Hubspot` component.
387+
388+
```jsx
389+
import { LiveChatLoaderProvider, Hubspot } from 'react-live-chat-loader'
390+
391+
export default class App extends React.Component {
392+
render() {
393+
return (
394+
<LiveChatLoaderProvider providerKey="asdjkasl123123" provider="hubspot">
395+
/* ... */
396+
<Hubspot />
397+
</LiveChatLoaderProvider>
398+
)
399+
}
400+
}
401+
```
402+
403+
You can customise the Hubspot placeholder by passing the following props to the
404+
`Hubspot` component:
405+
406+
- `backgroundColor`: The background color of the placeholder
407+
- `loader`: A react component shown while the Hubspot libraries are loading
408+
381409
</details>
382410

383411
## ➕ Adding a Provider

package-lock.json

Lines changed: 1055 additions & 1160 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@
4343
"devDependencies": {
4444
"@babel/cli": "^7.19.3",
4545
"@babel/core": "^7.19.3",
46-
"@babel/plugin-proposal-class-properties": "^7.18.6",
47-
"@babel/plugin-proposal-object-rest-spread": "^7.19.4",
4846
"@babel/preset-env": "^7.19.4",
4947
"@babel/preset-react": "^7.18.6",
5048
"@babel/preset-typescript": "^7.18.6",
@@ -56,7 +54,7 @@
5654
"babel-plugin-module-resolver": "^5.0.0",
5755
"eslint": "^8.25.0",
5856
"eslint-plugin-react": "^7.31.10",
59-
"prettier": "3.0.3",
57+
"prettier": "3.1.1",
6058
"ts-loader": "^9.4.1",
6159
"typescript": "^5.0.4"
6260
},

src/components/HubSpot/index.tsx

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import React, {
2+
ReactElement,
3+
useState
4+
} from 'react'
5+
import useChat from '../../hooks/useChat'
6+
const Icon = () => (
7+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="30" viewBox="0 0 39 37"><g fill="none"><path fill="#fff" d="M37.65 4.303c-.314-1.943-1.486-3.113-3.374-3.38C34.23.912 29.632.03 22.416.03c-7.214 0-11.812.882-11.843.889-1.477.21-2.507.967-3.042 2.192a83.103 83.103 0 0 1 9.312-.503c6.994 0 11.647.804 12.33.93 3.079.462 5.22 2.598 5.738 5.728.224 1.02.932 4.606.932 8.887 0 2.292-.206 4.395-.428 6.002 1.22-.516 1.988-1.55 2.23-3.044.008-.037.893-3.814.893-8.415 0-4.6-.885-8.377-.89-8.394"/><path fill="#fff" d="M32.077 9.76c-.314-1.944-1.487-3.114-3.374-3.382-.046-.01-4.644-.89-11.859-.89-7.214 0-11.813.88-11.843.888-1.903.27-3.075 1.44-3.384 3.363-.01.037-.894 3.814-.894 8.415 0 4.6.884 8.377.889 8.393.314 1.944 1.486 3.114 3.374 3.382.037.007 3.02.578 7.933.801l2.928 5.072a1.151 1.151 0 0 0 1.994 0l2.929-5.071c4.913-.224 7.893-.794 7.918-.8 1.902-.27 3.075-1.44 3.384-3.363.01-.037.893-3.814.893-8.414 0-4.601-.884-8.378-.888-8.394"/></g></svg>
8+
)
9+
10+
const HubSpot = ({
11+
backgroundColor,
12+
loader: Loader
13+
}: {
14+
backgroundColor?: string
15+
loader?: ReactElement
16+
}): JSX.Element | null => {
17+
const [state, loadChat] = useChat({ loadWhenIdle: true })
18+
const [isLoading, setIsLoading] = useState(false)
19+
if (state === 'complete') {
20+
return null
21+
}
22+
return (
23+
<div
24+
style={{
25+
zIndex: 1051, // 1 more than the actual widget
26+
paddingBottom: '16px',
27+
position: 'fixed',
28+
bottom: 0,
29+
paddingLeft: '0px',
30+
paddingRight: '16px',
31+
left: 'inherit',
32+
right: '0px'
33+
}}
34+
>
35+
<span
36+
style={{
37+
display: 'flex !important',
38+
paddingLeft: '24px !important',
39+
paddingTop: '20px !important',
40+
float: 'right'
41+
}}
42+
>
43+
<div
44+
style={{
45+
position: 'relative',
46+
display: 'inline-flex',
47+
alignItems: 'baseline',
48+
lineHeight: 1
49+
}}
50+
>
51+
<button
52+
onClick={() => {
53+
setIsLoading(true);
54+
loadChat({ open: true });
55+
}}
56+
aria-label="Open live chat"
57+
aria-haspopup="false"
58+
style={{
59+
fontWeight: 400,
60+
fontSize: '14px',
61+
color: 'rgb(51, 71, 91)',
62+
backgroundColor: backgroundColor || 'rgb(66, 91, 118)',
63+
boxShadow:
64+
'rgba(0, 0, 0, 0.1) 0px 1px 6px, rgba(0, 0, 0, 0.2) 0px 2px 24px',
65+
border: 'medium none',
66+
transition: 'box-shadow 150ms ease-in-out 0s',
67+
position: 'relative',
68+
borderRadius: '50%',
69+
height: '60px',
70+
width: '60px',
71+
cursor: 'pointer'
72+
}}
73+
>
74+
<div
75+
style={{
76+
position: 'absolute',
77+
top: '50%',
78+
left: '50%',
79+
transform: 'translate(-50%, -50%)',
80+
display: 'flex',
81+
width: '32px',
82+
height: '30px',
83+
lineHeight: 1
84+
}}
85+
>
86+
{isLoading && Loader ? Loader : <Icon />}
87+
</div>
88+
</button>
89+
</div>
90+
</span>
91+
</div>
92+
)
93+
}
94+
95+
export default HubSpot

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export { default as Messenger } from './components/Messenger'
77
export { default as Userlike } from './components/Userlike'
88
export { default as Chatwoot } from './components/Chatwoot'
99
export { default as Front } from './components/Front'
10+
export { default as HubSpot } from './components/HubSpot'
1011
export { default as LiveChatLoaderProvider } from './components/LiveChatLoaderProvider'

src/providers/hubSpot.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { State } from '../types'
2+
import waitForLoad from '../utils/waitForLoad'
3+
4+
export const domain = 'js.hs-scripts.com'
5+
declare global {
6+
interface Window {
7+
//eslint-disable-next-line @typescript-eslint/no-explicit-any
8+
HubSpotConversations: any
9+
//eslint-disable-next-line @typescript-eslint/no-explicit-any
10+
hsConversationsSettings: any
11+
//eslint-disable-next-line @typescript-eslint/no-explicit-any
12+
hsConversationsOnReady: any
13+
}
14+
}
15+
16+
const isHubspotWidgetDefined = () => window.HubSpotConversations && window.HubSpotConversations.widget;
17+
18+
const loadScript = (hsId: string) => {
19+
// Detect the provider is already loaded and return early
20+
if (window.HubSpotConversations) {
21+
return false
22+
}
23+
(function loadHubSpotSDK(d, s, id) {
24+
// fetch customerchat.js
25+
const fjs = d.getElementsByTagName(s)[0]
26+
if (d.getElementById(id)) {
27+
return
28+
}
29+
//eslint-disable-next-line @typescript-eslint/no-explicit-any
30+
const js = d.createElement(s) as any
31+
js.id = id
32+
js.src = `https://${domain}/${hsId}.js`
33+
js.type = 'text/javascript'
34+
js.async = 1
35+
js.defer = 1
36+
if (fjs) {
37+
fjs.parentNode?.insertBefore(js, fjs)
38+
} else {
39+
d.body.appendChild(js)
40+
}
41+
})(window.document, 'script', 'hs-script-loader')
42+
43+
return true
44+
}
45+
46+
const load = ({
47+
providerKey,
48+
setState,
49+
beforeInit = () => undefined,
50+
onReady = () => undefined,
51+
}: {
52+
providerKey: string
53+
setState: (state: State) => void
54+
beforeInit?: () => void
55+
onReady?: () => void
56+
}): boolean => {
57+
window.hsConversationsOnReady = [
58+
() => {
59+
isHubspotWidgetDefined() && window.HubSpotConversations.widget.load()
60+
}
61+
]
62+
const loaded = loadScript(providerKey)
63+
if (loaded) {
64+
beforeInit()
65+
66+
waitForLoad(
67+
() => {
68+
return Boolean(
69+
isHubspotWidgetDefined() &&
70+
window.HubSpotConversations.widget.status().loaded
71+
)
72+
},
73+
// Allow hubspot to complete loading before removing fake widget
74+
() => {
75+
isHubspotWidgetDefined() && window.HubSpotConversations.widget.open()
76+
setState('complete')
77+
onReady()
78+
}
79+
)
80+
}
81+
return loaded
82+
}
83+
84+
const open = (): unknown => {
85+
isHubspotWidgetDefined() &&
86+
!window.HubSpotConversations.widget.status().loaded &&
87+
window.HubSpotConversations.widget.load()
88+
89+
return (
90+
isHubspotWidgetDefined() &&
91+
window.HubSpotConversations.widget.open()
92+
)
93+
} // Open provider
94+
const close = (): unknown => isHubspotWidgetDefined() && window.HubSpotConversations.widget.close() // Close provider
95+
96+
export default {
97+
load,
98+
open,
99+
close,
100+
domain
101+
}

src/providers/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ export { default as helpScout } from './helpScout'
33
export { default as intercom } from './intercom'
44
export { default as messenger } from './messenger'
55
export { default as userlike } from './userlike'
6-
export { default as chatwoot } from './chatwoot'
76
export { default as front } from './front'
7+
export { default as chatwoot } from './chatwoot'
8+
export { default as hubSpot } from './hubSpot'

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ export type Provider =
1515
| 'userlike'
1616
| 'chatwoot'
1717
| 'front'
18+
| 'hubSpot'

website/components/exampleLinks.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ const ExampleLinks = () => (
3838
<a>Front</a>
3939
</Link>
4040
</li>
41+
<li>
42+
<Link href="/hubspot">
43+
<a>HubSpot</a>
44+
</Link>
45+
</li>
4146
</ul>
4247
)
4348

0 commit comments

Comments
 (0)