@social.io/catalog 1.3.0 → 2.1.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/.smartconfig.json +51 -0
- package/dist_bundle/bundle.js +5455 -3248
- package/dist_ts_web/00_commitinfo_data.js +3 -3
- package/dist_ts_web/elements/index.d.ts +21 -3
- package/dist_ts_web/elements/index.js +28 -7
- package/dist_ts_web/elements/sio-ai-card.d.ts +39 -0
- package/dist_ts_web/elements/sio-ai-card.js +229 -0
- package/dist_ts_web/elements/sio-avatar.d.ts +46 -0
- package/dist_ts_web/elements/sio-avatar.js +379 -0
- package/dist_ts_web/elements/sio-bucket-header.d.ts +36 -0
- package/dist_ts_web/elements/sio-bucket-header.js +197 -0
- package/dist_ts_web/elements/sio-button.d.ts +7 -3
- package/dist_ts_web/elements/sio-button.js +253 -152
- package/dist_ts_web/elements/sio-channel-rail.d.ts +38 -0
- package/dist_ts_web/elements/sio-channel-rail.js +288 -0
- package/dist_ts_web/elements/sio-chip.d.ts +25 -0
- package/dist_ts_web/elements/sio-chip.js +188 -0
- package/dist_ts_web/elements/sio-cmdk.d.ts +59 -0
- package/dist_ts_web/elements/sio-cmdk.js +471 -0
- package/dist_ts_web/elements/sio-combox.d.ts +55 -1
- package/dist_ts_web/elements/sio-combox.js +458 -261
- package/dist_ts_web/elements/sio-composer.d.ts +48 -0
- package/dist_ts_web/elements/sio-composer.js +357 -0
- package/dist_ts_web/elements/sio-conversation-selector.d.ts +41 -1
- package/dist_ts_web/elements/sio-conversation-selector.js +426 -238
- package/dist_ts_web/elements/sio-conversation-view.d.ts +34 -6
- package/dist_ts_web/elements/sio-conversation-view.js +738 -564
- package/dist_ts_web/elements/sio-dropdown-menu.d.ts +6 -6
- package/dist_ts_web/elements/sio-dropdown-menu.js +223 -169
- package/dist_ts_web/elements/sio-fab.d.ts +23 -5
- package/dist_ts_web/elements/sio-fab.js +259 -235
- package/dist_ts_web/elements/sio-glass-toolbar.d.ts +22 -0
- package/dist_ts_web/elements/sio-glass-toolbar.js +178 -0
- package/dist_ts_web/elements/sio-icon.d.ts +1 -0
- package/dist_ts_web/elements/sio-icon.js +254 -94
- package/dist_ts_web/elements/sio-image-lightbox.d.ts +3 -4
- package/dist_ts_web/elements/sio-image-lightbox.js +282 -191
- package/dist_ts_web/elements/sio-inset-list.d.ts +28 -0
- package/dist_ts_web/elements/sio-inset-list.js +191 -0
- package/dist_ts_web/elements/sio-kbd.d.ts +16 -0
- package/dist_ts_web/elements/sio-kbd.js +117 -0
- package/dist_ts_web/elements/sio-list-row.d.ts +55 -0
- package/dist_ts_web/elements/sio-list-row.js +462 -0
- package/dist_ts_web/elements/sio-logo-render.d.ts +42 -0
- package/dist_ts_web/elements/sio-logo-render.js +306 -0
- package/dist_ts_web/elements/sio-logo.d.ts +64 -0
- package/dist_ts_web/elements/sio-logo.js +393 -0
- package/dist_ts_web/elements/sio-message-input.d.ts +25 -4
- package/dist_ts_web/elements/sio-message-input.js +231 -226
- package/dist_ts_web/elements/sio-paper-thumb.d.ts +24 -0
- package/dist_ts_web/elements/sio-paper-thumb.js +293 -0
- package/dist_ts_web/elements/sio-pdf-viewer.d.ts +2 -0
- package/dist_ts_web/elements/sio-pdf-viewer.js +344 -244
- package/dist_ts_web/elements/sio-segmented.d.ts +32 -0
- package/dist_ts_web/elements/sio-segmented.js +217 -0
- package/dist_ts_web/elements/sio-step-timeline.d.ts +28 -0
- package/dist_ts_web/elements/sio-step-timeline.js +222 -0
- package/dist_ts_web/elements/sio-tab-bar.d.ts +36 -0
- package/dist_ts_web/elements/sio-tab-bar.js +232 -0
- package/dist_ts_web/elements/sio-unread-badge.d.ts +25 -0
- package/dist_ts_web/elements/sio-unread-badge.js +203 -0
- package/dist_ts_web/elements/sio-waveform.d.ts +34 -0
- package/dist_ts_web/elements/sio-waveform.js +304 -0
- package/dist_ts_web/elements/tokens.d.ts +70 -0
- package/dist_ts_web/elements/tokens.js +277 -0
- package/dist_ts_web/pages/firstpage.d.ts +5 -0
- package/dist_ts_web/pages/firstpage.js +21 -2
- package/dist_ts_web/pages/mainpage.d.ts +6 -0
- package/dist_ts_web/pages/mainpage.js +111 -39
- package/{license → license.md} +3 -1
- package/package.json +23 -29
- package/readme.hints.md +82 -0
- package/readme.md +113 -146
- package/ts_web/00_commitinfo_data.ts +2 -2
- package/ts_web/elements/index.ts +31 -7
- package/ts_web/elements/sio-ai-card.ts +175 -0
- package/ts_web/elements/sio-avatar.ts +295 -0
- package/ts_web/elements/sio-bucket-header.ts +157 -0
- package/ts_web/elements/sio-button.ts +149 -127
- package/ts_web/elements/sio-channel-rail.ts +256 -0
- package/ts_web/elements/sio-chip.ts +134 -0
- package/ts_web/elements/sio-cmdk.ts +461 -0
- package/ts_web/elements/sio-combox.ts +327 -204
- package/ts_web/elements/sio-composer.ts +306 -0
- package/ts_web/elements/sio-conversation-selector.ts +350 -228
- package/ts_web/elements/sio-conversation-view.ts +573 -457
- package/ts_web/elements/sio-dropdown-menu.ts +112 -130
- package/ts_web/elements/sio-fab.ts +192 -227
- package/ts_web/elements/sio-glass-toolbar.ts +140 -0
- package/ts_web/elements/sio-icon.ts +147 -25
- package/ts_web/elements/sio-image-lightbox.ts +62 -64
- package/ts_web/elements/sio-inset-list.ts +140 -0
- package/ts_web/elements/sio-kbd.ts +80 -0
- package/ts_web/elements/sio-list-row.ts +393 -0
- package/ts_web/elements/sio-logo-render.ts +367 -0
- package/ts_web/elements/sio-logo.ts +311 -0
- package/ts_web/elements/sio-message-input.ts +142 -221
- package/ts_web/elements/sio-paper-thumb.ts +244 -0
- package/ts_web/elements/sio-pdf-viewer.ts +58 -60
- package/ts_web/elements/sio-segmented.ts +183 -0
- package/ts_web/elements/sio-step-timeline.ts +179 -0
- package/ts_web/elements/sio-tab-bar.ts +195 -0
- package/ts_web/elements/sio-unread-badge.ts +147 -0
- package/ts_web/elements/sio-waveform.ts +239 -0
- package/ts_web/elements/tokens.ts +297 -0
- package/ts_web/pages/firstpage.ts +20 -1
- package/ts_web/pages/mainpage.ts +111 -39
- package/dist_bundle/bundle.js.map +0 -7
- package/dist_ts_web/elements/00colors.d.ts +0 -108
- package/dist_ts_web/elements/00colors.js +0 -137
- package/dist_ts_web/elements/00fonts.d.ts +0 -60
- package/dist_ts_web/elements/00fonts.js +0 -129
- package/dist_ts_web/elements/00tokens.d.ts +0 -123
- package/dist_ts_web/elements/00tokens.js +0 -176
- package/dist_ts_web/elements/sio-conversation-list.d.ts +0 -20
- package/dist_ts_web/elements/sio-conversation-list.js +0 -495
- package/dist_ts_web/elements/sio-recorder.d.ts +0 -60
- package/dist_ts_web/elements/sio-recorder.js +0 -173
- package/dist_ts_web/elements/sio-subwidget-conversations.d.ts +0 -16
- package/dist_ts_web/elements/sio-subwidget-conversations.js +0 -350
- package/dist_ts_web/elements/sio-subwidget-onboardme.d.ts +0 -7
- package/dist_ts_web/elements/sio-subwidget-onboardme.js +0 -243
- package/dist_watch/bundle.js +0 -81694
- package/dist_watch/bundle.js.map +0 -7
- package/dist_watch/index.html +0 -25
- package/npmextra.json +0 -19
- package/ts_web/elements/00colors.ts +0 -164
- package/ts_web/elements/00fonts.ts +0 -145
- package/ts_web/elements/00tokens.ts +0 -197
- package/ts_web/elements/sio-recorder.ts +0 -213
|
@@ -1,27 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DeesElement,
|
|
3
|
-
property,
|
|
4
3
|
html,
|
|
4
|
+
property,
|
|
5
|
+
state,
|
|
5
6
|
customElement,
|
|
6
|
-
type TemplateResult,
|
|
7
|
-
cssManager,
|
|
8
7
|
css,
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
cssManager,
|
|
9
|
+
type TemplateResult,
|
|
11
10
|
} from '@design.estate/dees-element';
|
|
12
11
|
import * as domtools from '@design.estate/dees-domtools';
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
import { colors, bdTheme } from './00colors.js';
|
|
16
|
-
import { spacing, radius, shadows, transitions } from './00tokens.js';
|
|
17
|
-
import { fontFamilies, typography } from './00fonts.js';
|
|
18
|
-
|
|
19
|
-
// Import components
|
|
13
|
+
import { sioElementStyles } from './tokens.js';
|
|
20
14
|
import { SioConversationSelector, type IConversation } from './sio-conversation-selector.js';
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
import {
|
|
16
|
+
SioConversationView,
|
|
17
|
+
type IMessage,
|
|
18
|
+
type IConversationData,
|
|
19
|
+
type IAttachment,
|
|
20
|
+
} from './sio-conversation-view.js';
|
|
21
|
+
import { SioImageLightbox, type ILightboxFile } from './sio-image-lightbox.js';
|
|
25
22
|
SioConversationSelector;
|
|
26
23
|
SioConversationView;
|
|
27
24
|
SioImageLightbox;
|
|
@@ -32,94 +29,100 @@ declare global {
|
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
31
|
|
|
32
|
+
/**
|
|
33
|
+
* sio-combox — the widget panel (v7 SocialIOWidget.jsx SIOWidgetShell).
|
|
34
|
+
*
|
|
35
|
+
* 380×620 panel, radius 20 on --sio-surface, floating shadow with a
|
|
36
|
+
* 0.5px ring, anchored above the sio-fab launcher. Slides between the
|
|
37
|
+
* home/welcome state (sio-conversation-selector) and the conversation
|
|
38
|
+
* state (sio-conversation-view); the away/email-fallback state is the
|
|
39
|
+
* conversation state with `away` set. Every state carries the centered
|
|
40
|
+
* "Powered by social.io" footer with the mini brand glyph.
|
|
41
|
+
*
|
|
42
|
+
* Singleton API: SioCombox.createOnBody() / getInstance(), plus
|
|
43
|
+
* open() / close() / toggle() / getIsOpen(). Full-screen on phablet.
|
|
44
|
+
*/
|
|
35
45
|
@customElement('sio-combox')
|
|
36
46
|
export class SioCombox extends DeesElement {
|
|
37
|
-
public static demo = () => html`
|
|
47
|
+
public static demo = () => html`
|
|
48
|
+
<div style="min-height: 660px; padding: 20px; background: var(--sio-bg);">
|
|
49
|
+
<sio-combox class="open" style="position: relative; bottom: auto; right: auto;"></sio-combox>
|
|
50
|
+
</div>
|
|
51
|
+
`;
|
|
38
52
|
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
// Singleton instance
|
|
54
|
+
private static instance: SioCombox | null = null;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Creates and appends a singleton combox to document.body
|
|
58
|
+
*/
|
|
59
|
+
public static createOnBody(): SioCombox {
|
|
60
|
+
if (!SioCombox.instance) {
|
|
61
|
+
SioCombox.instance = new SioCombox();
|
|
62
|
+
document.body.appendChild(SioCombox.instance);
|
|
63
|
+
}
|
|
64
|
+
return SioCombox.instance;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Gets the singleton instance if it exists
|
|
69
|
+
*/
|
|
70
|
+
public static getInstance(): SioCombox | null {
|
|
71
|
+
return SioCombox.instance;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** team is away — the conversation state falls back to email capture */
|
|
75
|
+
@property({ type: Boolean })
|
|
76
|
+
public accessor away = false;
|
|
41
77
|
|
|
42
78
|
@state()
|
|
43
79
|
private accessor selectedConversationId: string | null = null;
|
|
44
80
|
|
|
81
|
+
@state()
|
|
82
|
+
private accessor isKeyboardVisible: boolean = false;
|
|
83
|
+
|
|
84
|
+
@state()
|
|
85
|
+
private accessor isOpen: boolean = false;
|
|
86
|
+
|
|
87
|
+
private keyboardBlurTimeout?: number;
|
|
88
|
+
|
|
89
|
+
// demo data — the prototype's Lena/Orbit launch-banner thread
|
|
45
90
|
@state()
|
|
46
91
|
private accessor conversations: IConversation[] = [
|
|
47
92
|
{
|
|
48
|
-
id: '
|
|
49
|
-
title: '
|
|
50
|
-
lastMessage: '
|
|
51
|
-
time: '
|
|
52
|
-
|
|
93
|
+
id: 'orbit-launch',
|
|
94
|
+
title: 'Lena · Orbit',
|
|
95
|
+
lastMessage: 'Glad that sorted it — anything else, just write!',
|
|
96
|
+
time: '2d',
|
|
97
|
+
initials: 'LP',
|
|
98
|
+
tint: '#FF2D55',
|
|
99
|
+
status: 'resolved',
|
|
53
100
|
},
|
|
54
|
-
{
|
|
55
|
-
id: '2',
|
|
56
|
-
title: 'Billing Question',
|
|
57
|
-
lastMessage: 'I need help understanding my invoice',
|
|
58
|
-
time: '1 hour ago',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
id: '3',
|
|
62
|
-
title: 'Feature Request',
|
|
63
|
-
lastMessage: 'That would be great! Looking forward to it',
|
|
64
|
-
time: 'Yesterday',
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
id: '4',
|
|
68
|
-
title: 'General Inquiry',
|
|
69
|
-
lastMessage: 'Thank you for the information',
|
|
70
|
-
time: '2 days ago',
|
|
71
|
-
}
|
|
72
101
|
];
|
|
73
102
|
|
|
74
103
|
@state()
|
|
75
104
|
private accessor messages: { [conversationId: string]: IMessage[] } = {
|
|
76
|
-
'
|
|
77
|
-
{
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
id: '5',
|
|
83
|
-
text: 'Here\'s a screenshot of the error',
|
|
84
|
-
sender: 'user',
|
|
85
|
-
time: '10:08 AM',
|
|
86
|
-
attachments: [{
|
|
87
|
-
id: 'att1',
|
|
88
|
-
name: 'error-screenshot.png',
|
|
89
|
-
size: 245780,
|
|
90
|
-
type: 'image/png',
|
|
91
|
-
url: 'https://picsum.photos/400/300?random=1'
|
|
92
|
-
}]
|
|
105
|
+
'orbit-launch': [
|
|
106
|
+
{
|
|
107
|
+
id: '1',
|
|
108
|
+
text: 'Hey! 👋 You wrote about the launch banner — what would you like to change?',
|
|
109
|
+
sender: 'support',
|
|
110
|
+
time: '14:02',
|
|
93
111
|
},
|
|
94
|
-
{
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
time: '10:15 AM',
|
|
100
|
-
attachments: [{
|
|
101
|
-
id: 'att2',
|
|
102
|
-
name: 'user-guide.pdf',
|
|
103
|
-
size: 2457600,
|
|
104
|
-
type: 'application/pdf',
|
|
105
|
-
url: 'data:application/pdf;base64,JVBERi0xLjMKJeLjz9MKMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovT3V0bGluZXMgMiAwIFIKL1BhZ2VzIDMgMCBSCj4+CmVuZG9iagoyIDAgb2JqCjw8Ci9UeXBlIC9PdXRsaW5lcwovQ291bnQgMAo+PgplbmRvYmoKMyAwIG9iago8PAovVHlwZSAvUGFnZXMKL0NvdW50IDEKL0tpZHMgWzQgMCBSXQo+PgplbmRvYmoKNCAwIG9iago8PAovVHlwZSAvUGFnZQovUGFyZW50IDMgMCBSCi9NZWRpYUJveCBbMCAwIDYxMiA3OTJdCi9Db250ZW50cyA1IDAgUgovUmVzb3VyY2VzIDw8Ci9Gb250IDw8Ci9GMSA2IDAgUgo+Pgo+Pgo+PgplbmRvYmoKNSAwIG9iago8PAovTGVuZ3RoIDQ0Cj4+CnN0cmVhbQpCVApxCjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8gV29ybGQpIFRqCkVUClEKZW5kc3RyZWFtCmVuZG9iago2IDAgb2JqCjw8Ci9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMQovQmFzZUZvbnQgL1RpbWVzLVJvbWFuCj4+CmVuZG9iagp4cmVmCjAgNwowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA3NCAwMDAwMCBuIAowMDAwMDAwMTIwIDAwMDAwIG4gCjAwMDAwMDAxNzkgMDAwMDAgbiAKMDAwMDAwMDM2NCAwMDAwMCBuIAowMDAwMDAwNDY2IDAwMDAwIG4gCnRyYWlsZXIKPDwKL1NpemUgNwovUm9vdCAxIDAgUgo+PgpzdGFydHhyZWYKNTY1CiUlRU9G'
|
|
106
|
-
}]
|
|
112
|
+
{
|
|
113
|
+
id: '2',
|
|
114
|
+
text: 'The headline is cut off on tablet. Can we shorten it before Thursday?',
|
|
115
|
+
sender: 'user',
|
|
116
|
+
time: '14:03',
|
|
107
117
|
},
|
|
118
|
+
{
|
|
119
|
+
id: '3',
|
|
120
|
+
text: "Good catch. We can ship the short variant today — I'll send a preview here in ~10 min.",
|
|
121
|
+
sender: 'support',
|
|
122
|
+
time: '14:04',
|
|
123
|
+
},
|
|
124
|
+
{ id: '4', text: 'Perfect, thanks!', sender: 'user', time: '14:04' },
|
|
108
125
|
],
|
|
109
|
-
'2': [
|
|
110
|
-
{ id: '1', text: 'I need help understanding my invoice', sender: 'user', time: '9:00 AM' },
|
|
111
|
-
{ id: '2', text: 'I\'d be happy to help explain your invoice. Which part is unclear?', sender: 'support', time: '9:05 AM' },
|
|
112
|
-
],
|
|
113
|
-
'3': [
|
|
114
|
-
{ id: '1', text: 'I\'d love to see dark mode support in your app!', sender: 'user', time: 'Yesterday' },
|
|
115
|
-
{ id: '2', text: 'Thanks for the suggestion! We\'re actually working on dark mode and it should be available next month.', sender: 'support', time: 'Yesterday' },
|
|
116
|
-
{ id: '3', text: 'That would be great! Looking forward to it', sender: 'user', time: 'Yesterday' },
|
|
117
|
-
],
|
|
118
|
-
'4': [
|
|
119
|
-
{ id: '1', text: 'Can you tell me more about your enterprise plans?', sender: 'user', time: '2 days ago' },
|
|
120
|
-
{ id: '2', text: 'Of course! Our enterprise plans include advanced features like SSO, dedicated support, and custom integrations.', sender: 'support', time: '2 days ago' },
|
|
121
|
-
{ id: '3', text: 'Thank you for the information', sender: 'user', time: '2 days ago' },
|
|
122
|
-
]
|
|
123
126
|
};
|
|
124
127
|
|
|
125
128
|
constructor() {
|
|
@@ -127,131 +130,227 @@ export class SioCombox extends DeesElement {
|
|
|
127
130
|
domtools.DomTools.setupDomTools();
|
|
128
131
|
}
|
|
129
132
|
|
|
133
|
+
async connectedCallback() {
|
|
134
|
+
await super.connectedCallback();
|
|
135
|
+
this.addEventListener('input-focus', this.handleInputFocus as EventListener);
|
|
136
|
+
this.addEventListener('input-blur', this.handleInputBlur as EventListener);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async disconnectedCallback() {
|
|
140
|
+
await super.disconnectedCallback();
|
|
141
|
+
this.removeEventListener('input-focus', this.handleInputFocus as EventListener);
|
|
142
|
+
this.removeEventListener('input-blur', this.handleInputBlur as EventListener);
|
|
143
|
+
if (this.keyboardBlurTimeout) {
|
|
144
|
+
clearTimeout(this.keyboardBlurTimeout);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private handleInputFocus = () => {
|
|
149
|
+
if (this.keyboardBlurTimeout) {
|
|
150
|
+
clearTimeout(this.keyboardBlurTimeout);
|
|
151
|
+
this.keyboardBlurTimeout = undefined;
|
|
152
|
+
}
|
|
153
|
+
this.isKeyboardVisible = true;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
private handleInputBlur = () => {
|
|
157
|
+
if (this.keyboardBlurTimeout) {
|
|
158
|
+
clearTimeout(this.keyboardBlurTimeout);
|
|
159
|
+
}
|
|
160
|
+
this.keyboardBlurTimeout = window.setTimeout(() => {
|
|
161
|
+
this.isKeyboardVisible = false;
|
|
162
|
+
this.keyboardBlurTimeout = undefined;
|
|
163
|
+
}, 150);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
updated(changedProperties: Map<string, any>) {
|
|
167
|
+
super.updated(changedProperties);
|
|
168
|
+
if (changedProperties.has('isKeyboardVisible')) {
|
|
169
|
+
if (this.isKeyboardVisible) {
|
|
170
|
+
this.setAttribute('keyboard-visible', '');
|
|
171
|
+
} else {
|
|
172
|
+
this.removeAttribute('keyboard-visible');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (changedProperties.has('isOpen')) {
|
|
176
|
+
if (this.isOpen) {
|
|
177
|
+
this.classList.add('open');
|
|
178
|
+
this.dispatchEvent(new CustomEvent('opened', { bubbles: true, composed: true }));
|
|
179
|
+
} else {
|
|
180
|
+
this.classList.remove('open');
|
|
181
|
+
this.dispatchEvent(new CustomEvent('closed', { bubbles: true, composed: true }));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Opens the combox
|
|
188
|
+
*/
|
|
189
|
+
public open() {
|
|
190
|
+
this.isOpen = true;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Closes the combox
|
|
195
|
+
*/
|
|
196
|
+
public close() {
|
|
197
|
+
this.isOpen = false;
|
|
198
|
+
this.dispatchEvent(new CustomEvent('close', { bubbles: true, composed: true }));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Toggles the combox open/closed state
|
|
203
|
+
*/
|
|
204
|
+
public toggle() {
|
|
205
|
+
if (this.isOpen) {
|
|
206
|
+
this.close();
|
|
207
|
+
} else {
|
|
208
|
+
this.open();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Returns whether the combox is currently open
|
|
214
|
+
*/
|
|
215
|
+
public getIsOpen(): boolean {
|
|
216
|
+
return this.isOpen;
|
|
217
|
+
}
|
|
218
|
+
|
|
130
219
|
public static styles = [
|
|
131
|
-
|
|
220
|
+
...sioElementStyles,
|
|
132
221
|
css`
|
|
133
222
|
:host {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
223
|
+
position: fixed;
|
|
224
|
+
bottom: 96px;
|
|
225
|
+
right: 24px;
|
|
226
|
+
width: 380px;
|
|
227
|
+
height: 620px;
|
|
228
|
+
display: flex;
|
|
229
|
+
flex-direction: column;
|
|
230
|
+
background: var(--sio-surface);
|
|
231
|
+
border-radius: 20px;
|
|
141
232
|
overflow: hidden;
|
|
142
|
-
|
|
143
|
-
|
|
233
|
+
box-shadow:
|
|
234
|
+
0 24px 64px rgba(0, 0, 0, 0.22),
|
|
235
|
+
0 0 0 0.5px rgba(0, 0, 0, 0.08);
|
|
236
|
+
font-family: var(--sio-font-sf);
|
|
144
237
|
transform-origin: bottom right;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
@keyframes scaleIn {
|
|
152
|
-
from {
|
|
153
|
-
opacity: 0;
|
|
154
|
-
transform: scale(0.9) translateY(10px);
|
|
155
|
-
}
|
|
156
|
-
to {
|
|
157
|
-
opacity: 1;
|
|
158
|
-
transform: scale(1) translateY(0);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
:host::before {
|
|
163
|
-
content: '';
|
|
164
|
-
position: absolute;
|
|
165
|
-
inset: 0;
|
|
166
|
-
border-radius: ${unsafeCSS(radius['2xl'])};
|
|
167
|
-
padding: 1px;
|
|
168
|
-
background: linear-gradient(145deg, ${bdTheme('border')}, transparent 50%);
|
|
169
|
-
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
|
170
|
-
-webkit-mask-composite: exclude;
|
|
171
|
-
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
|
172
|
-
mask-composite: exclude;
|
|
173
|
-
opacity: 0.5;
|
|
238
|
+
z-index: 10001;
|
|
239
|
+
|
|
240
|
+
/* hidden by default */
|
|
241
|
+
opacity: 0;
|
|
174
242
|
pointer-events: none;
|
|
243
|
+
transform: scale(0.95) translateY(10px);
|
|
244
|
+
transition:
|
|
245
|
+
opacity 200ms ease,
|
|
246
|
+
transform 200ms ease;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
:host(.open) {
|
|
250
|
+
opacity: 1;
|
|
251
|
+
pointer-events: all;
|
|
252
|
+
transform: scale(1) translateY(0);
|
|
175
253
|
}
|
|
176
254
|
|
|
177
255
|
.container {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
256
|
+
position: relative;
|
|
257
|
+
flex: 1;
|
|
258
|
+
min-height: 0;
|
|
259
|
+
overflow: hidden;
|
|
182
260
|
}
|
|
183
261
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
262
|
+
sio-conversation-selector,
|
|
263
|
+
sio-conversation-view {
|
|
264
|
+
position: absolute;
|
|
265
|
+
top: 0;
|
|
266
|
+
width: 100%;
|
|
267
|
+
height: 100%;
|
|
268
|
+
transition:
|
|
269
|
+
left 280ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
270
|
+
opacity 200ms ease;
|
|
271
|
+
}
|
|
191
272
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
273
|
+
.container.show-list sio-conversation-selector {
|
|
274
|
+
left: 0;
|
|
275
|
+
opacity: 1;
|
|
276
|
+
}
|
|
195
277
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
278
|
+
.container.show-list sio-conversation-view {
|
|
279
|
+
left: 100%;
|
|
280
|
+
opacity: 0;
|
|
281
|
+
pointer-events: none;
|
|
282
|
+
}
|
|
202
283
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
284
|
+
.container.show-conversation sio-conversation-selector {
|
|
285
|
+
left: -100%;
|
|
286
|
+
opacity: 0;
|
|
287
|
+
pointer-events: none;
|
|
288
|
+
}
|
|
209
289
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
290
|
+
.container.show-conversation sio-conversation-view {
|
|
291
|
+
left: 0;
|
|
292
|
+
opacity: 1;
|
|
293
|
+
}
|
|
215
294
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
295
|
+
/* footer — every state (v7 SIOWidgetShell) */
|
|
296
|
+
.footer {
|
|
297
|
+
flex-shrink: 0;
|
|
298
|
+
padding: 8px 0 10px;
|
|
299
|
+
display: flex;
|
|
300
|
+
align-items: center;
|
|
301
|
+
justify-content: center;
|
|
302
|
+
gap: 5px;
|
|
303
|
+
font-size: 10.5px;
|
|
304
|
+
color: color-mix(in oklab, var(--sio-label-3) 75%, transparent);
|
|
305
|
+
user-select: none;
|
|
306
|
+
}
|
|
220
307
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
308
|
+
.footer svg {
|
|
309
|
+
display: block;
|
|
310
|
+
}
|
|
225
311
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
312
|
+
.footer span {
|
|
313
|
+
font-weight: 500;
|
|
314
|
+
}
|
|
315
|
+
`,
|
|
316
|
+
// phablet: full-screen sheet
|
|
317
|
+
cssManager.cssForPhablet(css`
|
|
318
|
+
:host {
|
|
319
|
+
top: 0;
|
|
320
|
+
left: 0;
|
|
321
|
+
right: 0;
|
|
322
|
+
bottom: 0;
|
|
323
|
+
width: 100vw;
|
|
324
|
+
height: 100vh;
|
|
325
|
+
height: 100dvh;
|
|
326
|
+
border-radius: 0;
|
|
327
|
+
transform-origin: center center;
|
|
230
328
|
}
|
|
231
329
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
flex-shrink: 0;
|
|
236
|
-
}
|
|
330
|
+
:host(.open) {
|
|
331
|
+
transform: scale(1) translateY(0);
|
|
332
|
+
}
|
|
237
333
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
334
|
+
:host([keyboard-visible]) {
|
|
335
|
+
height: 100vh;
|
|
336
|
+
height: 100dvh;
|
|
241
337
|
}
|
|
242
|
-
|
|
338
|
+
`),
|
|
243
339
|
];
|
|
244
340
|
|
|
245
341
|
public render(): TemplateResult {
|
|
246
342
|
const selectedConversation = this.selectedConversationId
|
|
247
|
-
? this.conversations.find(c => c.id === this.selectedConversationId)
|
|
343
|
+
? this.conversations.find((c) => c.id === this.selectedConversationId)
|
|
248
344
|
: null;
|
|
249
345
|
|
|
250
346
|
const conversationData: IConversationData | null = selectedConversation
|
|
251
347
|
? {
|
|
252
348
|
id: selectedConversation.id,
|
|
253
349
|
title: selectedConversation.title,
|
|
254
|
-
|
|
350
|
+
agentInitials: selectedConversation.initials,
|
|
351
|
+
agentTint: selectedConversation.tint,
|
|
352
|
+
dateStamp: 'Today, 14:02',
|
|
353
|
+
messages: this.messages[selectedConversation.id] || [],
|
|
255
354
|
}
|
|
256
355
|
: null;
|
|
257
356
|
|
|
@@ -263,17 +362,30 @@ export class SioCombox extends DeesElement {
|
|
|
263
362
|
.conversations=${this.conversations}
|
|
264
363
|
.selectedConversationId=${this.selectedConversationId}
|
|
265
364
|
@conversation-selected=${this.handleConversationSelected}
|
|
365
|
+
@new-conversation=${this.handleNewConversation}
|
|
366
|
+
@close=${() => this.close()}
|
|
266
367
|
></sio-conversation-selector>
|
|
267
|
-
|
|
368
|
+
|
|
268
369
|
<sio-conversation-view
|
|
269
370
|
.conversation=${conversationData}
|
|
371
|
+
?away=${this.away}
|
|
270
372
|
@back=${this.handleBack}
|
|
271
373
|
@send-message=${this.handleSendMessage}
|
|
272
374
|
@open-image=${this.handleOpenImage}
|
|
273
375
|
@open-file=${this.handleOpenImage}
|
|
274
376
|
></sio-conversation-view>
|
|
275
377
|
</div>
|
|
276
|
-
|
|
378
|
+
|
|
379
|
+
<div class="footer">
|
|
380
|
+
<!-- mini social.io brand glyph -->
|
|
381
|
+
<svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
382
|
+
<path
|
|
383
|
+
d="M12 3C7 3 3 6.6 3 11c0 2.5 1.3 4.7 3.3 6.2-.1 1-.5 2.1-1.3 2.9 1.6-.1 3-.7 4-1.4.9.2 1.9.3 3 .3 5 0 9-3.6 9-8S17 3 12 3z"
|
|
384
|
+
/>
|
|
385
|
+
</svg>
|
|
386
|
+
<span>Powered by social.io</span>
|
|
387
|
+
</div>
|
|
388
|
+
|
|
277
389
|
<sio-image-lightbox></sio-image-lightbox>
|
|
278
390
|
`;
|
|
279
391
|
}
|
|
@@ -281,24 +393,39 @@ export class SioCombox extends DeesElement {
|
|
|
281
393
|
private handleConversationSelected(event: CustomEvent) {
|
|
282
394
|
const conversation = event.detail.conversation as IConversation;
|
|
283
395
|
this.selectedConversationId = conversation.id;
|
|
284
|
-
|
|
396
|
+
|
|
285
397
|
// Mark conversation as read
|
|
286
|
-
const convIndex = this.conversations.findIndex(c => c.id === conversation.id);
|
|
398
|
+
const convIndex = this.conversations.findIndex((c) => c.id === conversation.id);
|
|
287
399
|
if (convIndex !== -1) {
|
|
288
400
|
this.conversations[convIndex] = { ...this.conversations[convIndex], unread: false };
|
|
289
401
|
this.conversations = [...this.conversations];
|
|
290
402
|
}
|
|
291
403
|
}
|
|
292
404
|
|
|
405
|
+
private handleNewConversation = () => {
|
|
406
|
+
const newConversation: IConversation = {
|
|
407
|
+
id: `new-${Date.now()}`,
|
|
408
|
+
title: 'Lena · Orbit',
|
|
409
|
+
lastMessage: '',
|
|
410
|
+
time: 'now',
|
|
411
|
+
initials: 'LP',
|
|
412
|
+
tint: '#FF2D55',
|
|
413
|
+
status: 'new',
|
|
414
|
+
};
|
|
415
|
+
this.conversations = [newConversation, ...this.conversations];
|
|
416
|
+
this.messages = { ...this.messages, [newConversation.id]: [] };
|
|
417
|
+
this.selectedConversationId = newConversation.id;
|
|
418
|
+
};
|
|
419
|
+
|
|
293
420
|
private handleBack() {
|
|
294
|
-
//
|
|
421
|
+
// back to the home / welcome state
|
|
295
422
|
this.selectedConversationId = null;
|
|
296
423
|
}
|
|
297
424
|
|
|
298
425
|
private handleSendMessage(event: CustomEvent) {
|
|
299
426
|
const message = event.detail.message as IMessage;
|
|
300
427
|
const conversationId = this.selectedConversationId;
|
|
301
|
-
|
|
428
|
+
|
|
302
429
|
if (conversationId) {
|
|
303
430
|
// Add message to the conversation
|
|
304
431
|
if (!this.messages[conversationId]) {
|
|
@@ -306,47 +433,43 @@ export class SioCombox extends DeesElement {
|
|
|
306
433
|
}
|
|
307
434
|
this.messages[conversationId] = [...this.messages[conversationId], message];
|
|
308
435
|
this.messages = { ...this.messages };
|
|
309
|
-
|
|
436
|
+
|
|
310
437
|
// Update conversation's last message
|
|
311
|
-
const convIndex = this.conversations.findIndex(c => c.id === conversationId);
|
|
438
|
+
const convIndex = this.conversations.findIndex((c) => c.id === conversationId);
|
|
312
439
|
if (convIndex !== -1) {
|
|
313
440
|
this.conversations[convIndex] = {
|
|
314
441
|
...this.conversations[convIndex],
|
|
315
442
|
lastMessage: message.text,
|
|
316
|
-
time: '
|
|
443
|
+
time: 'now',
|
|
317
444
|
};
|
|
318
445
|
// Move conversation to top
|
|
319
446
|
const [conv] = this.conversations.splice(convIndex, 1);
|
|
320
447
|
this.conversations = [conv, ...this.conversations];
|
|
321
448
|
}
|
|
322
|
-
|
|
323
|
-
// Simulate a response after a delay (remove in production)
|
|
324
|
-
setTimeout(() => {
|
|
325
|
-
const responseMessage: IMessage = {
|
|
326
|
-
id: Date.now().toString(),
|
|
327
|
-
text: 'Thanks for your message! We\'ll get back to you shortly.',
|
|
328
|
-
sender: 'support',
|
|
329
|
-
time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
this.messages[conversationId] = [...this.messages[conversationId], responseMessage];
|
|
333
|
-
this.messages = { ...this.messages };
|
|
334
|
-
}, 3000);
|
|
335
449
|
}
|
|
336
450
|
}
|
|
337
451
|
|
|
452
|
+
/**
|
|
453
|
+
* Append an inbound (support-side) message to a conversation.
|
|
454
|
+
* The host application calls this when a reply arrives.
|
|
455
|
+
*/
|
|
456
|
+
public receiveMessage(conversationId: string, message: IMessage): void {
|
|
457
|
+
this.messages[conversationId] = [...(this.messages[conversationId] ?? []), message];
|
|
458
|
+
this.messages = { ...this.messages };
|
|
459
|
+
}
|
|
460
|
+
|
|
338
461
|
private handleOpenImage(event: CustomEvent) {
|
|
339
462
|
const attachment = event.detail.attachment as IAttachment;
|
|
340
463
|
const lightbox = this.shadowRoot?.querySelector('sio-image-lightbox') as SioImageLightbox;
|
|
341
|
-
|
|
464
|
+
|
|
342
465
|
if (lightbox && attachment) {
|
|
343
|
-
const lightboxFile:
|
|
466
|
+
const lightboxFile: ILightboxFile = {
|
|
344
467
|
url: attachment.url,
|
|
345
468
|
name: attachment.name,
|
|
346
469
|
size: attachment.size,
|
|
347
|
-
type: attachment.type
|
|
470
|
+
type: attachment.type,
|
|
348
471
|
};
|
|
349
472
|
lightbox.open(lightboxFile);
|
|
350
473
|
}
|
|
351
474
|
}
|
|
352
|
-
}
|
|
475
|
+
}
|