@bloonio/chat-angular 0.1.0 → 0.2.0
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.
- package/CHANGELOG.md +54 -0
- package/README.md +120 -6
- package/fesm2022/bloonio-chat-angular.mjs +557 -168
- package/fesm2022/bloonio-chat-angular.mjs.map +1 -1
- package/package.json +5 -7
- package/src/lib/styles/chat.css +16 -3
- package/types/bloonio-chat-angular.d.ts +330 -0
- package/esm2022/bloonio-chat-angular.mjs +0 -5
- package/esm2022/index.mjs +0 -25
- package/esm2022/lib/bloonio-chat.service.mjs +0 -311
- package/esm2022/lib/bloonio-chat.token.mjs +0 -46
- package/esm2022/lib/components/input-bar.component.mjs +0 -91
- package/esm2022/lib/components/launcher.component.mjs +0 -81
- package/esm2022/lib/components/message-list.component.mjs +0 -58
- package/esm2022/lib/components/panel.component.mjs +0 -211
- package/esm2022/lib/components/quick-replies.component.mjs +0 -58
- package/esm2022/lib/components/thread.component.mjs +0 -103
- package/index.d.ts +0 -27
- package/lib/bloonio-chat.service.d.ts +0 -79
- package/lib/bloonio-chat.token.d.ts +0 -67
- package/lib/components/input-bar.component.d.ts +0 -18
- package/lib/components/launcher.component.d.ts +0 -14
- package/lib/components/message-list.component.d.ts +0 -8
- package/lib/components/panel.component.d.ts +0 -31
- package/lib/components/quick-replies.component.d.ts +0 -10
- package/lib/components/thread.component.d.ts +0 -27
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
Backwards compatible with 0.1.x.
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `locale` (`'fr' | 'en' | 'zh'`, default `'en'`): built-in translations for
|
|
10
|
+
every string the widget renders itself, also sent with each new visitor
|
|
11
|
+
session. It may be a function or a signal, and `provideBloonioChat` accepts
|
|
12
|
+
a factory run in an injection context, so the widget can follow the host
|
|
13
|
+
app's language at runtime. With no `locale`, sessions are still created
|
|
14
|
+
with `fr`, as in 0.1.x.
|
|
15
|
+
- Host copy: `greeting`, `launcherLabel`, `onlineStatusText`,
|
|
16
|
+
`offlineStatusText`, `quickReplies`. Each replaces the matching text of the
|
|
17
|
+
tenant's single-language relay config and may be a function or a signal.
|
|
18
|
+
The greeting is a local opening bubble, never sent or stored.
|
|
19
|
+
- Unread badge on the launcher for answers received while the panel is
|
|
20
|
+
closed; the count is in its accessible name.
|
|
21
|
+
- Resume after a reload: the visitor session is stored per tenant in
|
|
22
|
+
`localStorage`; on load the token is refreshed, the thread replayed and the
|
|
23
|
+
socket reopened. A session the relay refuses is replaced by a fresh one
|
|
24
|
+
without an error. Not applied when a `visitorTokenProvider` is configured.
|
|
25
|
+
- The panel says so when the chat is connecting or cannot be reached, and
|
|
26
|
+
reopening it retries. The input is disabled while there is no session.
|
|
27
|
+
- Accessibility: `aria-expanded` on the launcher, the floating panel is a
|
|
28
|
+
labelled dialog that takes focus on open, Escape closes it and focus
|
|
29
|
+
returns to the launcher, the message list is a `log` region, the input bar
|
|
30
|
+
shows keyboard focus.
|
|
31
|
+
- `BloonioChatService.visibleMessages`.
|
|
32
|
+
- Specs (`npm test`).
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- Bubbles are aligned again (visitor right, answers left, notices centred):
|
|
37
|
+
the message list host no longer sits between the flex column and its
|
|
38
|
+
items.
|
|
39
|
+
- The typing dots clear when the answer arrives, and after 30 seconds
|
|
40
|
+
without a new typing frame.
|
|
41
|
+
- The input and the quick replies wait for the socket's welcome frame, so a
|
|
42
|
+
message can no longer be typed or tapped before it can be sent
|
|
43
|
+
(`connecting` now lasts until then).
|
|
44
|
+
- Messages received while the panel was open no longer count as unread once
|
|
45
|
+
it is closed.
|
|
46
|
+
- A socket the relay closes with 4401, 4403 or 4404 is no longer retried
|
|
47
|
+
forever with the same token.
|
|
48
|
+
- The header initials are styled from the stylesheet, not a style attribute
|
|
49
|
+
(a strict CSP dropped it).
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- The ticket notice no longer carries an emoji or a dash, and the agent
|
|
54
|
+
joined / left notices lose their final period.
|
package/README.md
CHANGED
|
@@ -46,22 +46,135 @@ export const appConfig: ApplicationConfig = {
|
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
```ts
|
|
49
|
-
// any standalone component —
|
|
50
|
-
import {
|
|
49
|
+
// any standalone component — the launcher toggles the panel next to it
|
|
50
|
+
import {
|
|
51
|
+
BloonioChatLauncherComponent,
|
|
52
|
+
BloonioChatPanelComponent,
|
|
53
|
+
} from '@bloonio/chat-angular';
|
|
51
54
|
|
|
52
55
|
@Component({
|
|
53
56
|
standalone: true,
|
|
54
|
-
imports: [BloonioChatLauncherComponent],
|
|
55
|
-
template: `<router-outlet /> <bloonio-chat-launcher />`,
|
|
57
|
+
imports: [BloonioChatLauncherComponent, BloonioChatPanelComponent],
|
|
58
|
+
template: `<router-outlet /> <bloonio-chat-launcher /> <bloonio-chat-panel />`,
|
|
56
59
|
})
|
|
57
60
|
export class AppComponent {}
|
|
58
61
|
```
|
|
59
62
|
|
|
63
|
+
## Language
|
|
64
|
+
|
|
65
|
+
`locale` picks the built-in translation of every string the widget renders
|
|
66
|
+
itself (placeholder, labels, connection and error lines, agent and ticket
|
|
67
|
+
notices, aria-labels). Supported: `'fr'`, `'en'`, `'zh'`. Default `'en'`; a
|
|
68
|
+
region is trimmed (`'fr-FR'` is `'fr'`) and anything else falls back to
|
|
69
|
+
English.
|
|
70
|
+
|
|
71
|
+
The configured value is also sent, as given, with each new visitor session.
|
|
72
|
+
With no `locale` configured the session is created with `fr`, as in 0.1.x.
|
|
73
|
+
|
|
74
|
+
Text configured on the relay (status texts, launcher label, offline message,
|
|
75
|
+
quick replies) is shown as received, unless the host supplies its own: see
|
|
76
|
+
"Host copy" below.
|
|
77
|
+
|
|
78
|
+
To follow the host app's language at runtime, pass a function. A signal is
|
|
79
|
+
one, and `provideBloonioChat` accepts a factory that runs in an injection
|
|
80
|
+
context so it can reach your own language service:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
provideBloonioChat(() => ({
|
|
84
|
+
tenantId: '019e4ae7-…',
|
|
85
|
+
publicKey: 'pk_…',
|
|
86
|
+
baseUrl: 'https://chat-relay.example.com',
|
|
87
|
+
locale: inject(MyI18nService).lang, // Signal<'fr' | 'en'>
|
|
88
|
+
})),
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The widget's strings switch immediately. A conversation keeps the language
|
|
92
|
+
it was opened with.
|
|
93
|
+
|
|
94
|
+
## Host copy
|
|
95
|
+
|
|
96
|
+
A tenant's relay config holds one language. These optional entries replace
|
|
97
|
+
the matching tenant text; each takes a value or a function (a signal works),
|
|
98
|
+
so it can follow the host's language. Left out, the tenant's text is used.
|
|
99
|
+
|
|
100
|
+
| Entry | Replaces |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `greeting` | Nothing on the relay: an opening bubble drawn like an assistant message at the top of a new conversation. It is local only (never sent, never stored), stays above the first messages, and is not shown above a thread replayed after a reload. When set, the tenant's offline message is not shown. |
|
|
103
|
+
| `launcherLabel` | The label next to the launcher. An empty string shows no label. |
|
|
104
|
+
| `onlineStatusText` | The header subtitle during opening hours. |
|
|
105
|
+
| `offlineStatusText` | The header subtitle outside opening hours. |
|
|
106
|
+
| `quickReplies` | The suggested replies shown until the visitor's first message. |
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
provideBloonioChat(() => {
|
|
110
|
+
const i18n = inject(MyI18nService);
|
|
111
|
+
return {
|
|
112
|
+
tenantId: '019e4ae7-…',
|
|
113
|
+
publicKey: 'pk_…',
|
|
114
|
+
baseUrl: 'https://chat-relay.example.com',
|
|
115
|
+
locale: i18n.lang,
|
|
116
|
+
launcherLabel: '',
|
|
117
|
+
greeting: () => i18n.t('chat.greeting'),
|
|
118
|
+
onlineStatusText: () => i18n.t('chat.online'),
|
|
119
|
+
quickReplies: () => [i18n.t('chat.reply.sales'), i18n.t('chat.reply.help')],
|
|
120
|
+
};
|
|
121
|
+
}),
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Resume after a reload
|
|
125
|
+
|
|
126
|
+
The visitor session (`session_id`, `visitor_token`, `expires_at`) is kept in
|
|
127
|
+
`localStorage` under `bloonio:chat:<tenantId>:session`. On the next page
|
|
128
|
+
load the widget refreshes the token (`POST /refresh/visitor-token`), replays
|
|
129
|
+
the newest 50 messages (`GET /fetch/visitor-messages`) and reopens the
|
|
130
|
+
socket in the background, so a visitor waiting for an agent keeps the
|
|
131
|
+
thread and still receives the reply with the panel closed.
|
|
132
|
+
|
|
133
|
+
When the session cannot be resumed (the relay answers 4xx, or closes the
|
|
134
|
+
socket with 4401 / 4404) the stored session is dropped and a new one starts
|
|
135
|
+
the next time the panel is open, with no error shown. A network failure
|
|
136
|
+
keeps the stored session for the next load. Nothing is read or written on
|
|
137
|
+
the server, and when storage is blocked the chat works without resume.
|
|
138
|
+
|
|
139
|
+
Sessions are not stored when a `visitorTokenProvider` is configured: an
|
|
140
|
+
identified visitor's thread would otherwise show to the next account on the
|
|
141
|
+
same browser. An anonymous thread stays resumable on that browser for as
|
|
142
|
+
long as the relay keeps the session, shared computers included.
|
|
143
|
+
|
|
144
|
+
## Theming
|
|
145
|
+
|
|
146
|
+
Colours, radius, shadow and font are CSS variables declared on `.bch-root`.
|
|
147
|
+
Redeclare them in a rule placed after the stylesheet import:
|
|
148
|
+
|
|
149
|
+
```css
|
|
150
|
+
@import "@bloonio/chat-angular/styles.css";
|
|
151
|
+
|
|
152
|
+
.bch-root {
|
|
153
|
+
--bch-primary: #0b5d3b;
|
|
154
|
+
--bch-bg: #ffffff;
|
|
155
|
+
--bch-font: "Inter", sans-serif;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Variables: `--bch-primary`, `--bch-primary-contrast`, `--bch-bg`,
|
|
160
|
+
`--bch-surface`, `--bch-text`, `--bch-text-muted`, `--bch-border`,
|
|
161
|
+
`--bch-radius`, `--bch-shadow`, `--bch-font`. The tenant's branding colour,
|
|
162
|
+
when set on the relay, is applied inline as `--bch-primary` on `.bch-root`
|
|
163
|
+
and `.bch-panel`; mark your own value `!important` on both to keep it.
|
|
164
|
+
|
|
165
|
+
## Accessibility
|
|
166
|
+
|
|
167
|
+
The launcher is a labelled toggle (`aria-expanded`). Answers received while
|
|
168
|
+
the panel is closed show as a count badge on it, and the count is part of
|
|
169
|
+
its accessible name. The floating panel is a non-modal dialog: opening moves
|
|
170
|
+
focus into it, Escape or its close button closes it and returns focus to the
|
|
171
|
+
launcher, and new messages are announced through a `log` region.
|
|
172
|
+
|
|
60
173
|
## Three rendering modes
|
|
61
174
|
|
|
62
175
|
| Mode | Component | When |
|
|
63
176
|
|---|---|---|
|
|
64
|
-
| **Floating** | `<bloonio-chat-launcher />`
|
|
177
|
+
| **Floating** | `<bloonio-chat-launcher />` + `<bloonio-chat-panel />` | Tidio-style — a bubble in the corner that expands on click. |
|
|
65
178
|
| **Docked panel** | `<bloonio-chat-panel mode="docked" />` | Always-on chat in a sidebar / dedicated column. No floating chrome. |
|
|
66
179
|
| **Headless thread** | `<bloonio-chat-thread />` | Just messages + input, no header. Embed inside your own support pages. |
|
|
67
180
|
|
|
@@ -98,7 +211,8 @@ For tenants on `@angular/ssr`, no extra configuration is needed.
|
|
|
98
211
|
```bash
|
|
99
212
|
npm install
|
|
100
213
|
npm run build # ng-packagr → dist/ (fesm2022 + .d.ts + Ivy partial)
|
|
101
|
-
npm run typecheck # tsc --noEmit
|
|
214
|
+
npm run typecheck # tsc --noEmit (sources + specs)
|
|
215
|
+
npm test # vitest (jsdom): locale, resume, focus handling
|
|
102
216
|
```
|
|
103
217
|
|
|
104
218
|
Every component uses inline `template:` strings, so there are no separate
|