@pushwoosh/websdk-common 6.18.0 → 6.19.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.
@@ -0,0 +1,228 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { INBOX_WIDGET_CSS } from './constants';
4
+ import { formatInboxMessageTime, getInboxHeroUrl, getInboxIconInitial, getInboxValidSlides, inboxWidgetStyleVariables, resolveInboxLayout, resolveInboxWidgetAppearance } from './helpers';
5
+ function stop(handler) {
6
+ return event => {
7
+ event.stopPropagation();
8
+ handler?.();
9
+ };
10
+ }
11
+ function Carousel({
12
+ slides,
13
+ alt,
14
+ onSlideLinkClick
15
+ }) {
16
+ const [index, setIndex] = useState(0);
17
+ const active = Math.min(index, slides.length - 1);
18
+ const slide = slides[active];
19
+ const onSlideClick = slide.link ? stop(() => onSlideLinkClick?.(slide.link)) : undefined;
20
+ return _jsxs("div", {
21
+ className: "pw-inbox_media",
22
+ children: [_jsxs("div", {
23
+ className: "pw-inbox_slide",
24
+ onClick: onSlideClick,
25
+ children: [_jsx("img", {
26
+ alt: slide.caption || alt,
27
+ className: "pw-inbox_hero",
28
+ src: slide.imageUrl
29
+ }), !!slide.caption && _jsx("span", {
30
+ className: "pw-inbox_slide-caption",
31
+ children: slide.caption
32
+ })]
33
+ }), slides.length > 1 && _jsx("div", {
34
+ className: "pw-inbox_pager",
35
+ children: slides.map((_slide, slideIndex) => _jsx("button", {
36
+ className: slideIndex === active ? 'pw-inbox_dot pw-active' : 'pw-inbox_dot',
37
+ onClick: stop(() => setIndex(slideIndex)),
38
+ type: "button"
39
+ }, slideIndex))
40
+ })]
41
+ });
42
+ }
43
+ function Hero({
44
+ url,
45
+ alt,
46
+ placeholder
47
+ }) {
48
+ return _jsx("div", {
49
+ className: "pw-inbox_media",
50
+ children: placeholder ? _jsx("div", {
51
+ className: "pw-inbox_hero pw-inbox_hero--placeholder"
52
+ }) : _jsx("img", {
53
+ alt: alt,
54
+ className: "pw-inbox_hero",
55
+ src: url
56
+ })
57
+ });
58
+ }
59
+ /** One cell of the web inbox widget, the `li.pw-inbox_item` the WebSDK draws. */
60
+ export function InboxWebCell(props) {
61
+ const {
62
+ content,
63
+ layout,
64
+ title,
65
+ body,
66
+ timeLabel,
67
+ isRead,
68
+ isActionPerformed,
69
+ code,
70
+ placeholder,
71
+ onClick,
72
+ onRemove,
73
+ onSlideLinkClick
74
+ } = props;
75
+ const alt = content.title || content.body || '';
76
+ const texts = _jsxs("div", {
77
+ className: "pw-inbox_content",
78
+ children: [_jsxs("div", {
79
+ className: "pw-inbox_item-title",
80
+ children: [title, !isRead && _jsx("span", {
81
+ className: "pw-inbox_unread-dot"
82
+ })]
83
+ }), _jsx("div", {
84
+ className: "pw-inbox_item-body",
85
+ children: body
86
+ }), _jsx("div", {
87
+ className: "pw-inbox_item-time",
88
+ children: timeLabel
89
+ })]
90
+ });
91
+ let media;
92
+ if (layout === 'carousel' && !placeholder) {
93
+ media = _jsx(Carousel, {
94
+ alt: alt,
95
+ onSlideLinkClick: onSlideLinkClick,
96
+ slides: getInboxValidSlides(content.carousel)
97
+ });
98
+ } else if (layout !== 'classic') {
99
+ media = _jsx(Hero, {
100
+ alt: alt,
101
+ placeholder: placeholder,
102
+ url: getInboxHeroUrl(content)
103
+ });
104
+ }
105
+ let icon;
106
+ if (placeholder) {
107
+ icon = _jsx("div", {
108
+ className: "pw-inbox_icon pw-inbox_icon--placeholder"
109
+ });
110
+ } else {
111
+ icon = _jsx("div", {
112
+ className: "pw-inbox_icon",
113
+ children: content.iconUrl ? _jsx("img", {
114
+ alt: alt,
115
+ className: "pw-inbox_message-image",
116
+ src: content.iconUrl
117
+ }) : _jsx("span", {
118
+ className: "pw-inbox_icon-initial",
119
+ children: getInboxIconInitial(content)
120
+ })
121
+ });
122
+ }
123
+ const className = ['pw-inbox_item', !isRead && 'pw-new', !isActionPerformed && 'pw-unread'].filter(Boolean).join(' ');
124
+ return _jsxs("li", {
125
+ className: className,
126
+ "data-pw-inbox-message-id": code,
127
+ onClick: onClick,
128
+ children: [_jsxs("div", {
129
+ className: `pw-inbox_item-inner pw-inbox_item--${layout}`,
130
+ children: [layout === 'classic' ? icon : media, layout !== 'banner' && texts]
131
+ }), _jsx("span", {
132
+ className: "pw-inbox_item-remove",
133
+ onClick: stop(onRemove)
134
+ })]
135
+ });
136
+ }
137
+ function WidgetBody({
138
+ messages,
139
+ appearance,
140
+ now,
141
+ onMessageClick,
142
+ onMessageRemove,
143
+ onSlideLinkClick
144
+ }) {
145
+ if (messages.length === 0) {
146
+ return _jsxs("div", {
147
+ className: "pw-inbox_list--empty",
148
+ children: [_jsx("div", {
149
+ className: "pw-inbox_list-icon",
150
+ children: _jsx("img", {
151
+ alt: appearance.emptyInboxTitle,
152
+ src: appearance.emptyInboxIconUrl
153
+ })
154
+ }), _jsx("div", {
155
+ className: "pw-inbox_list-title",
156
+ children: appearance.emptyInboxTitle
157
+ }), _jsx("div", {
158
+ className: "ipw-inbox_list-body",
159
+ children: appearance.emptyInboxText
160
+ })]
161
+ });
162
+ }
163
+ return _jsxs("div", {
164
+ className: "pw-inbox_inner",
165
+ children: [_jsx("div", {
166
+ className: "pw-inbox_title",
167
+ children: appearance.title
168
+ }), _jsx("ul", {
169
+ className: "pw-inbox_list",
170
+ children: messages.map(message => _jsx(InboxWebCell, {
171
+ body: message.body,
172
+ code: message.code,
173
+ content: message,
174
+ isActionPerformed: message.isActionPerformed,
175
+ isRead: message.isRead,
176
+ layout: resolveInboxLayout(message),
177
+ onClick: () => onMessageClick?.(message.code),
178
+ onRemove: () => onMessageRemove?.(message.code),
179
+ onSlideLinkClick: link => onSlideLinkClick?.(message.code, link),
180
+ timeLabel: formatInboxMessageTime(message.sendDate, now),
181
+ title: message.title
182
+ }, message.code))
183
+ })]
184
+ });
185
+ }
186
+ /** Classes and custom properties of a preview widget box; a live host sets them on its own element. */
187
+ export function inboxWidgetPreviewFrame(appearance, extraClass) {
188
+ const className = ['pw-inbox-widget pw-inbox-widget--preview', extraClass, appearance.legacyClassicCell && 'pw-inbox-widget--legacy-cell'].filter(Boolean).join(' ');
189
+ return {
190
+ className,
191
+ style: inboxWidgetStyleVariables(appearance)
192
+ };
193
+ }
194
+ /** The web inbox widget: message list or empty state. `live` fills the host's `.pw-inbox-widget` element, `preview` draws the box inline. */
195
+ export function InboxWidgetReader(props) {
196
+ const {
197
+ mode,
198
+ messages,
199
+ now,
200
+ onMessageClick,
201
+ onMessageRemove,
202
+ onSlideLinkClick
203
+ } = props;
204
+ const appearance = resolveInboxWidgetAppearance(props.appearance);
205
+ const content = _jsxs(_Fragment, {
206
+ children: [_jsx("style", {
207
+ children: INBOX_WIDGET_CSS
208
+ }), _jsx("div", {
209
+ className: "pw-inbox__arrow"
210
+ }), _jsx(WidgetBody, {
211
+ appearance: appearance,
212
+ messages: messages,
213
+ now: now,
214
+ onMessageClick: onMessageClick,
215
+ onMessageRemove: onMessageRemove,
216
+ onSlideLinkClick: onSlideLinkClick
217
+ })]
218
+ });
219
+ if (mode === 'live') {
220
+ return content;
221
+ }
222
+ const frame = inboxWidgetPreviewFrame(appearance, messages.length === 0 ? 'pw-inbox-widget--empty' : undefined);
223
+ return _jsx("div", {
224
+ className: frame.className,
225
+ style: frame.style,
226
+ children: content
227
+ });
228
+ }
@@ -0,0 +1,15 @@
1
+ import { type InboxLayout, type InboxWidgetAppearance, type InboxWidgetStyleVariable } from './types';
2
+ /** The sending pipeline and the editor keep at most this many carousel slides. */
3
+ export declare const INBOX_MAX_CAROUSEL_SLIDES = 5;
4
+ /** Layouts a cell can draw; anything else falls back to the heuristic. */
5
+ export declare const INBOX_KNOWN_LAYOUTS: readonly InboxLayout[];
6
+ /** Prefix of the widget's CSS custom properties: `--pw-inbox-<name>`, a public API customers override from their CSS. */
7
+ export declare const INBOX_WIDGET_STYLE_PREFIX = "pw-inbox";
8
+ /** Month labels of the absolute message dates. */
9
+ export declare const INBOX_MONTHS: string[];
10
+ /** Appearance values exposed as CSS custom properties, with their formatting. */
11
+ export declare const INBOX_WIDGET_STYLE_VARIABLES: readonly InboxWidgetStyleVariable[];
12
+ /** Default appearance of the web inbox widget. */
13
+ export declare const INBOX_WIDGET_DEFAULT_APPEARANCE: InboxWidgetAppearance;
14
+ /** Stylesheet of the web inbox widget and its trigger badge; class names and custom properties are public API. */
15
+ export declare const INBOX_WIDGET_CSS = "\n.pw-inbox-trigger {\n position: relative;\n cursor: pointer;\n}\n\n.pw-inbox-trigger:after {\n content: attr(data-pw-count);\n display: block;\n position: absolute;\n right: 0;\n top: 0;\n background: var(--pw-inbox-badgeBgColor, #ff4c00);\n border-radius: 8px;\n color: var(--pw-inbox-badgeTextColor, #ffffff);\n font-size: 10px;\n font-weight: normal;\n line-height: 16px;\n width: 16px;\n padding: 0 2px;\n box-sizing: border-box;\n text-align: center;\n}\n\n.pw-inbox-trigger.pw-empty:after {\n display: none;\n}\n\n.pw-inbox-widget * {\n position: static;\n box-sizing: border-box;\n font-size: 1em;\n outline: none;\n font-family: var(--pw-inbox-fontFamily, inherit);\n}\n.pw-inbox-widget {\n font-size: 14px;\n position: absolute;\n top: 0;\n left: -1000px;\n background: var(--pw-inbox-bgColor, #ffffff);\n border: solid 1px var(--pw-inbox-borderColor, transparent);\n border-radius: var(--pw-inbox-borderRadius, 4px);\n width: var(--pw-inbox-widgetWidth, 350px);\n box-shadow: 0 1px 4px 0 rgba(0,0,0,.25);\n z-index: var(--pw-inbox-zIndex, 100);\n opacity: 0;\n transition: opacity .6s ease;\n transition-delay: 100ms;\n}\n.pw-inbox-widget.pw-open {\n opacity: 1;\n transition-delay: 0ms;\n}\n.pw-inbox-widget.pw-inbox-widget--inset {\n top: auto;\n left: auto;\n display: none;\n}\n.pw-inbox-widget.pw-inbox-widget--inset.pw-open {\n display: block;\n}\n.pw-inbox-widget.pw-inbox-widget--inset.pw-bottom {\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n}\n.pw-inbox-widget.pw-inbox-widget--inset.pw-top {\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n}\n.pw-inbox-widget.pw-inbox-widget--inset.pw-right {\n left: 100%;\n top: 50%;\n transform: translateY(-50%);\n}\n.pw-inbox-widget.pw-inbox-widget--inset.pw-left {\n right: 100%;\n top: 50%;\n transform: translateY(-50%);\n}\n.pw-inbox-widget.pw-inbox-widget--empty {\n max-height: none;\n}\n.pw-inbox-widget .pw-inbox__arrow {\n display: block;\n width: 0;\n height: 0;\n border-width: 10px;\n border-style: solid;\n border-color: transparent;\n position: absolute;\n}\n.pw-inbox-widget .pw-inbox__arrow:before {\n content: \"\";\n display: block;\n width: 0;\n height: 0;\n border-width: 10px;\n border-style: solid;\n border-color: transparent;\n position: absolute;\n}\n.pw-inbox-widget.pw-top {\n margin-top: -12px;\n}\n.pw-inbox-widget.pw-top .pw-inbox__arrow {\n border-top-color: var(--pw-inbox-arrowBorderColor, rgba(0,0,0,.1));\n bottom: -21px;\n left: 50%;\n transform: translateX(-50%);\n}\n.pw-inbox-widget.pw-top .pw-inbox__arrow:before {\n border-top-color: var(--pw-inbox-bgColor, #ffffff);\n top: -11px;\n left: -10px;\n}\n.pw-inbox-widget.pw-bottom {\n margin-top: 12px;\n}\n.pw-inbox-widget.pw-bottom .pw-inbox__arrow {\n border-bottom-color: var(--pw-inbox-arrowBorderColor, rgba(0,0,0,.1));\n top: -21px;\n left: 50%;\n transform: translateX(-50%);\n}\n.pw-inbox-widget.pw-bottom .pw-inbox__arrow:before {\n border-bottom-color: var(--pw-inbox-bgColor, #ffffff);\n bottom: -11px;\n left: -10px;\n}\n.pw-inbox-widget.pw-left {\n margin-left: -12px;\n}\n.pw-inbox-widget.pw-left .pw-inbox__arrow {\n border-left-color: var(--pw-inbox-arrowBorderColor, rgba(0,0,0,.1));\n right: -21px;\n top: 50%;\n transform: translateY(-50%);\n}\n.pw-inbox-widget.pw-left .pw-inbox__arrow:before {\n border-left-color: var(--pw-inbox-bgColor, #ffffff);\n left: -11px;\n top: -10px;\n}\n.pw-inbox-widget.pw-right {\n margin-left: 12px;\n}\n.pw-inbox-widget.pw-right .pw-inbox__arrow {\n border-right-color: var(--pw-inbox-arrowBorderColor, rgba(0,0,0,.1));\n left: -21px;\n top: 50%;\n transform: translateY(-50%);\n}\n.pw-inbox-widget.pw-right .pw-inbox__arrow:before {\n border-right-color: var(--pw-inbox-bgColor, #ffffff);\n right: -11px;\n top: -10px;\n}\n.pw-inbox_inner {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.pw-inbox_title {\n color: var(--pw-inbox-textColor, #333333);\n margin: 0;\n padding: 28px 32px 12px;\n font-size: 24px;\n font-weight: 500;\n line-height: 1.1;\n text-align: left;\n flex: 0 0 66px;\n}\n.pw-inbox_list {\n overflow-x: hidden;\n overflow-y: auto;\n min-width: 200px;\n max-height: 300px;\n padding: 0;\n margin: 0;\n list-style: none;\n position: relative;\n flex: 1 1 auto;\n}\n\n.pw-inbox_item {\n position: relative;\n padding: 8px 32px;\n margin: 0;\n text-align: left;\n}\n.pw-inbox_item-inner {\n display: flex;\n cursor: pointer;\n}\n.pw-inbox_icon {\n flex: 0 0 auto;\n width: var(--pw-inbox-avatarSize, 52px);\n height: var(--pw-inbox-avatarSize, 52px);\n margin-right: 14px;\n overflow: hidden;\n border-radius: var(--pw-inbox-mediaRadius, 8px);\n background: var(--pw-inbox-avatarBgColor, #c4c8cc);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.pw-inbox_message-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n.pw-inbox_icon-initial {\n color: var(--pw-inbox-avatarTextColor, #4b5057);\n font-size: 22px;\n line-height: 1;\n font-weight: 700;\n}\n.pw-inbox_content {\n flex: 1 1 auto;\n min-width: 0;\n}\n.pw-inbox_item-title {\n color: var(--pw-inbox-messageTitleColor, #7a7a7a);\n font-size: 14px;\n line-height: 20px;\n margin-bottom: 4px;\n display: flex;\n align-items: center;\n gap: 6px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.pw-inbox_unread-dot {\n flex: 0 0 auto;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--pw-inbox-unreadDotColor, #00a2ff);\n}\n.pw-inbox_item-body {\n color: var(--pw-inbox-textColor, #333333);\n font-size: 14px;\n line-height: 20px;\n margin-bottom: 4px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.pw-inbox_item-time {\n color: var(--pw-inbox-timeTextColor, #c4c4c4);\n font-size: 12px;\n line-height: 17px;\n}\n.pw-inbox_item-remove {\n position: absolute;\n z-index: 2;\n top: 8px;\n right: 8px;\n display: none;\n width: 10px;\n height: 10px;\n background: transparent url('https://cdn.pushwoosh.com/webpush/img/iconClose.svg') 50% no-repeat;\n cursor: pointer;\n}\n.pw-inbox_item:hover .pw-inbox_item-remove {\n display: block;\n}\n\n.pw-inbox_item.pw-new .pw-inbox_item-title {\n color: var(--pw-inbox-textColor, #333333);\n font-weight: 700;\n}\n\n.pw-inbox_item.pw-new .pw-inbox_item-body {\n font-weight: 700;\n}\n\n.pw-inbox_list--empty {\n padding: 50px 16px;\n text-align: center;\n max-height: 100%;\n overflow: auto;\n}\n\n.pw-inbox_list--empty .pw-inbox_list-icon {\n text-align: center;\n margin-bottom: 30px;\n}\n.pw-inbox_list--empty .pw-inbox_list-icon img {\n max-width: 100%;\n}\n\n.pw-inbox_list--empty .pw-inbox_list-title {\n font-size: 28px;\n line-height: 36px;\n color: var(--pw-inbox-emptyInboxTitleColor, #333333);\n margin-bottom: 20px;\n}\n\n.pw-inbox_list--empty .ipw-inbox_list-body {\n font-size: 14px;\n line-height: 18px;\n color: var(--pw-inbox-emptyInboxTextColor, #7a7a7a);\n}\n\n/* Cell layouts: banner, captioned and carousel stack their media above the\n texts, so the flex row of the classic cell becomes a column. */\n.pw-inbox_item--banner,\n.pw-inbox_item--captioned,\n.pw-inbox_item--carousel {\n flex-direction: column;\n gap: 12px;\n}\n\n.pw-inbox_media {\n position: relative;\n width: 100%;\n}\n.pw-inbox_hero {\n display: block;\n width: 100%;\n max-width: 100%;\n aspect-ratio: 2 / 1;\n object-fit: cover;\n border-radius: var(--pw-inbox-mediaRadius, 8px);\n}\n\n.pw-inbox_slide {\n position: relative;\n display: block;\n cursor: pointer;\n}\n.pw-inbox_slide-caption {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n padding: 14px 10px 6px;\n color: var(--pw-inbox-slideCaptionColor, #ffffff);\n font-size: 14px;\n line-height: 20px;\n border-radius: 0 0 var(--pw-inbox-mediaRadius, 8px) var(--pw-inbox-mediaRadius, 8px);\n background: linear-gradient(transparent, var(--pw-inbox-slideScrimColor, rgba(0,0,0,.45)));\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.pw-inbox_pager {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n}\n.pw-inbox_dot {\n width: 6px;\n height: 6px;\n padding: 0;\n border: none;\n border-radius: 50%;\n background: var(--pw-inbox-pagerDotColor, #ebf0f5);\n cursor: pointer;\n}\n.pw-inbox_dot.pw-active {\n background: var(--pw-inbox-pagerDotActiveColor, #00a2ff);\n}\n\n/* `legacyClassicCell` restores the pre-3.75 classic cell. Scoped to classic on\n purpose: the three new layouts have no older look to go back to. */\n.pw-inbox-widget--legacy-cell .pw-inbox_item--classic .pw-inbox_icon {\n display: block;\n flex: 0 0 40px;\n width: auto;\n height: auto;\n margin-right: 0;\n border-radius: 0;\n background: none;\n}\n.pw-inbox-widget--legacy-cell .pw-inbox_item--classic .pw-inbox_message-image {\n width: 28px;\n height: auto;\n object-fit: fill;\n}\n.pw-inbox-widget--legacy-cell .pw-inbox_item--classic .pw-inbox_content {\n flex: 0 1 100%;\n}\n.pw-inbox-widget--legacy-cell .pw-inbox_item--classic .pw-inbox_item-title {\n display: block;\n overflow: visible;\n text-overflow: clip;\n white-space: normal;\n}\n.pw-inbox-widget--legacy-cell .pw-inbox_item--classic .pw-inbox_unread-dot {\n display: none;\n}\n.pw-inbox-widget--legacy-cell .pw-inbox_item--classic .pw-inbox_item-body {\n display: block;\n overflow: visible;\n}\n\n.pw-inbox-widget.pw-inbox-widget--preview {\n position: relative;\n top: auto;\n left: auto;\n max-width: 100%;\n opacity: 1;\n transition: none;\n}\n.pw-inbox-widget--preview .pw-inbox__arrow {\n display: none;\n}\n.pw-inbox-widget--cell .pw-inbox_item {\n padding: 16px;\n}\n.pw-inbox_icon--placeholder {\n border: 1px dashed #00a2ff;\n background: #80b7ff33;\n}\n.pw-inbox_hero--placeholder {\n border: 1px dashed #00a2ff;\n background: #80b7ff33;\n}\n";