@pushwoosh/dumb-components 1.1.221 → 1.1.222

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.
Files changed (83) hide show
  1. package/InboxPreview/InboxPreview.d.ts +13 -0
  2. package/InboxPreview/InboxPreview.js +82 -0
  3. package/InboxPreview/__tests__/helpers.test.d.ts +1 -0
  4. package/InboxPreview/__tests__/helpers.test.js +201 -0
  5. package/InboxPreview/components/InboxAndroidCell/InboxAndroidCell.d.ts +4 -0
  6. package/InboxPreview/components/InboxAndroidCell/InboxAndroidCell.js +70 -0
  7. package/InboxPreview/components/InboxAndroidCell/index.d.ts +1 -0
  8. package/InboxPreview/components/InboxAndroidCell/index.js +1 -0
  9. package/InboxPreview/components/InboxCellAvatar/InboxCellAvatar.d.ts +4 -0
  10. package/InboxPreview/components/InboxCellAvatar/InboxCellAvatar.js +48 -0
  11. package/InboxPreview/components/InboxCellAvatar/index.d.ts +1 -0
  12. package/InboxPreview/components/InboxCellAvatar/index.js +1 -0
  13. package/InboxPreview/components/InboxCellAvatar/styles.d.ts +1 -0
  14. package/InboxPreview/components/InboxCellAvatar/styles.js +5 -0
  15. package/InboxPreview/components/InboxCellAvatar/types.d.ts +10 -0
  16. package/InboxPreview/components/InboxCellAvatar/types.js +1 -0
  17. package/InboxPreview/components/InboxCellCarousel/InboxCellCarousel.d.ts +4 -0
  18. package/InboxPreview/components/InboxCellCarousel/InboxCellCarousel.js +53 -0
  19. package/InboxPreview/components/InboxCellCarousel/index.d.ts +1 -0
  20. package/InboxPreview/components/InboxCellCarousel/index.js +1 -0
  21. package/InboxPreview/components/InboxCellCarousel/styles.d.ts +29 -0
  22. package/InboxPreview/components/InboxCellCarousel/styles.js +24 -0
  23. package/InboxPreview/components/InboxCellCarousel/types.d.ts +8 -0
  24. package/InboxPreview/components/InboxCellCarousel/types.js +1 -0
  25. package/InboxPreview/components/InboxCellMedia/InboxCellMedia.d.ts +4 -0
  26. package/InboxPreview/components/InboxCellMedia/InboxCellMedia.js +26 -0
  27. package/InboxPreview/components/InboxCellMedia/index.d.ts +1 -0
  28. package/InboxPreview/components/InboxCellMedia/index.js +1 -0
  29. package/InboxPreview/components/InboxCellMedia/types.d.ts +12 -0
  30. package/InboxPreview/components/InboxCellMedia/types.js +1 -0
  31. package/InboxPreview/components/InboxIOSCell/InboxIOSCell.d.ts +4 -0
  32. package/InboxPreview/components/InboxIOSCell/InboxIOSCell.js +125 -0
  33. package/InboxPreview/components/InboxIOSCell/index.d.ts +1 -0
  34. package/InboxPreview/components/InboxIOSCell/index.js +1 -0
  35. package/InboxPreview/components/InboxWebCell/InboxWebCell.d.ts +4 -0
  36. package/InboxPreview/components/InboxWebCell/InboxWebCell.js +83 -0
  37. package/InboxPreview/components/InboxWebCell/index.d.ts +1 -0
  38. package/InboxPreview/components/InboxWebCell/index.js +1 -0
  39. package/InboxPreview/constants.d.ts +14 -0
  40. package/InboxPreview/constants.js +30 -0
  41. package/InboxPreview/helpers.d.ts +29 -0
  42. package/InboxPreview/helpers.js +75 -0
  43. package/InboxPreview/index.d.ts +4 -0
  44. package/InboxPreview/index.js +3 -0
  45. package/InboxPreview/polyglot/index.d.ts +2 -0
  46. package/InboxPreview/polyglot/index.js +34 -0
  47. package/InboxPreview/polyglot/messages_ar.d.ts +3 -0
  48. package/InboxPreview/polyglot/messages_ar.js +4 -0
  49. package/InboxPreview/polyglot/messages_bn.d.ts +3 -0
  50. package/InboxPreview/polyglot/messages_bn.js +4 -0
  51. package/InboxPreview/polyglot/messages_de.d.ts +3 -0
  52. package/InboxPreview/polyglot/messages_de.js +4 -0
  53. package/InboxPreview/polyglot/messages_en.d.ts +3 -0
  54. package/InboxPreview/polyglot/messages_en.js +4 -0
  55. package/InboxPreview/polyglot/messages_es.d.ts +3 -0
  56. package/InboxPreview/polyglot/messages_es.js +4 -0
  57. package/InboxPreview/polyglot/messages_fr.d.ts +3 -0
  58. package/InboxPreview/polyglot/messages_fr.js +4 -0
  59. package/InboxPreview/polyglot/messages_he.d.ts +3 -0
  60. package/InboxPreview/polyglot/messages_he.js +4 -0
  61. package/InboxPreview/polyglot/messages_hi.d.ts +3 -0
  62. package/InboxPreview/polyglot/messages_hi.js +4 -0
  63. package/InboxPreview/polyglot/messages_ja.d.ts +3 -0
  64. package/InboxPreview/polyglot/messages_ja.js +4 -0
  65. package/InboxPreview/polyglot/messages_ko.d.ts +3 -0
  66. package/InboxPreview/polyglot/messages_ko.js +4 -0
  67. package/InboxPreview/polyglot/messages_pt.d.ts +3 -0
  68. package/InboxPreview/polyglot/messages_pt.js +4 -0
  69. package/InboxPreview/polyglot/messages_ru.d.ts +3 -0
  70. package/InboxPreview/polyglot/messages_ru.js +4 -0
  71. package/InboxPreview/polyglot/messages_th.d.ts +3 -0
  72. package/InboxPreview/polyglot/messages_th.js +4 -0
  73. package/InboxPreview/polyglot/messages_zh.d.ts +3 -0
  74. package/InboxPreview/polyglot/messages_zh.js +4 -0
  75. package/InboxPreview/polyglot/types.d.ts +5 -0
  76. package/InboxPreview/polyglot/types.js +1 -0
  77. package/InboxPreview/styles.d.ts +25 -0
  78. package/InboxPreview/styles.js +21 -0
  79. package/InboxPreview/types.d.ts +74 -0
  80. package/InboxPreview/types.js +1 -0
  81. package/index.d.ts +1 -0
  82. package/index.js +1 -0
  83. package/package.json +1 -1
@@ -0,0 +1,13 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { InboxPreviewProps } from './types';
3
+ /**
4
+ * Renders an Inbox cell the way the SDK of the chosen platform draws it
5
+ * (`platform`: iOS card, Android flat list row, or Web widget card), with the
6
+ * SDK degradation rules: a layout that cannot render falls back to classic and
7
+ * a carousel shows at most five valid slides. Content without a single filled
8
+ * field renders the dashed placeholder of the requested layout.
9
+ *
10
+ * @example
11
+ * <InboxPreview platform="ios" localizedContent={preset.localizedContent} language="en" />
12
+ */
13
+ export declare function InboxPreview(props: InboxPreviewProps): ReactElement;
@@ -0,0 +1,82 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Color, ShapeRadius } from '@pushwoosh/kit-constants';
3
+ import { Vertical } from '@pushwoosh/kit-helpers';
4
+ import { InboxAndroidCell } from './components/InboxAndroidCell';
5
+ import { InboxIOSCell } from './components/InboxIOSCell';
6
+ import { InboxWebCell } from './components/InboxWebCell';
7
+ import { INBOX_PREVIEW_MAX_WIDTH, INBOX_PREVIEW_MIN_WIDTH, INBOX_PREVIEW_SKELETON_HEIGHT } from './constants';
8
+ import { getEmptyLayout, getPreviewContent, getPreviewTexts, isEmptyContent, resolveInboxLayout } from './helpers';
9
+ import { Lang } from './polyglot';
10
+ import { RichMessageViewer } from '../RichMessageEditor';
11
+ import { LIGHT_ISLAND_PROPS } from '../shared/lightIsland';
12
+ const CELL_BY_PLATFORM = {
13
+ ios: InboxIOSCell,
14
+ android: InboxAndroidCell,
15
+ web: InboxWebCell
16
+ };
17
+ /**
18
+ * Renders an Inbox cell the way the SDK of the chosen platform draws it
19
+ * (`platform`: iOS card, Android flat list row, or Web widget card), with the
20
+ * SDK degradation rules: a layout that cannot render falls back to classic and
21
+ * a carousel shows at most five valid slides. Content without a single filled
22
+ * field renders the dashed placeholder of the requested layout.
23
+ *
24
+ * @example
25
+ * <InboxPreview platform="ios" localizedContent={preset.localizedContent} language="en" />
26
+ */
27
+ export function InboxPreview(props) {
28
+ const {
29
+ platform = 'ios',
30
+ content,
31
+ localizedContent,
32
+ language,
33
+ dateLabel = '12:12',
34
+ unread = true,
35
+ isLoading = false,
36
+ emptyTitle = _jsx(Lang, {
37
+ message: "DUMB.INBOX_PREVIEW.EMPTY_TITLE"
38
+ }),
39
+ emptyDescription = _jsx(Lang, {
40
+ message: "DUMB.INBOX_PREVIEW.EMPTY_DESCRIPTION"
41
+ }),
42
+ width = '100%'
43
+ } = props;
44
+ if (isLoading) {
45
+ return _jsx(Vertical, {
46
+ ...LIGHT_ISLAND_PROPS,
47
+ "$bgColor": Color.SOFT_LIGHT,
48
+ "$borderRadius": ShapeRadius.SECTION,
49
+ "$maxWidth": INBOX_PREVIEW_MAX_WIDTH,
50
+ "$minHeight": INBOX_PREVIEW_SKELETON_HEIGHT,
51
+ "$minWidth": INBOX_PREVIEW_MIN_WIDTH,
52
+ "$width": width
53
+ });
54
+ }
55
+ const picked = getPreviewContent(content, localizedContent, language) || {};
56
+ const isEmpty = isEmptyContent(picked);
57
+ const layout = isEmpty ? getEmptyLayout(picked) : resolveInboxLayout(picked);
58
+ const texts = getPreviewTexts(picked, layout);
59
+ const Cell = CELL_BY_PLATFORM[platform];
60
+ return _jsx(Vertical, {
61
+ ...LIGHT_ISLAND_PROPS,
62
+ "$maxWidth": INBOX_PREVIEW_MAX_WIDTH,
63
+ "$minWidth": INBOX_PREVIEW_MIN_WIDTH,
64
+ "$position": "relative",
65
+ "$width": width,
66
+ children: _jsx(Cell, {
67
+ body: isEmpty ? emptyDescription : texts.body && _jsx(RichMessageViewer, {
68
+ flat: true,
69
+ value: texts.body
70
+ }),
71
+ content: picked,
72
+ dateLabel: dateLabel,
73
+ isEmpty: isEmpty,
74
+ layout: layout,
75
+ title: isEmpty ? emptyTitle : _jsx(RichMessageViewer, {
76
+ flat: true,
77
+ value: texts.title
78
+ }),
79
+ unread: unread
80
+ })
81
+ });
82
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,201 @@
1
+ import { MAX_CAROUSEL_SLIDES } from '../constants';
2
+ import { getEmptyLayout, getPreviewContent, getPreviewTexts, getValidSlides, isEmptyContent, resolveInboxLayout } from '../helpers';
3
+ const HERO = 'https://cdn.example.com/hero.jpg';
4
+ const SLIDE = {
5
+ imageUrl: 'https://cdn.example.com/slide.jpg'
6
+ };
7
+ describe('resolveInboxLayout', () => {
8
+ it('renders the requested layout when it can', () => {
9
+ expect(resolveInboxLayout({
10
+ layoutType: 'classic',
11
+ title: 't',
12
+ body: 'b'
13
+ })).toBe('classic');
14
+ expect(resolveInboxLayout({
15
+ layoutType: 'banner',
16
+ bannerUrl: HERO
17
+ })).toBe('banner');
18
+ expect(resolveInboxLayout({
19
+ layoutType: 'captioned',
20
+ title: 't',
21
+ body: 'b',
22
+ bannerUrl: HERO
23
+ })).toBe('captioned');
24
+ expect(resolveInboxLayout({
25
+ layoutType: 'carousel',
26
+ title: 't',
27
+ body: 'b',
28
+ carousel: [SLIDE]
29
+ })).toBe('carousel');
30
+ });
31
+ it('degrades banner and captioned without a hero image into classic', () => {
32
+ expect(resolveInboxLayout({
33
+ layoutType: 'banner'
34
+ })).toBe('classic');
35
+ expect(resolveInboxLayout({
36
+ layoutType: 'captioned',
37
+ title: 't',
38
+ body: 'b'
39
+ })).toBe('classic');
40
+ });
41
+ it('degrades captioned and carousel without title or body into classic', () => {
42
+ expect(resolveInboxLayout({
43
+ layoutType: 'captioned',
44
+ body: 'b',
45
+ bannerUrl: HERO
46
+ })).toBe('classic');
47
+ expect(resolveInboxLayout({
48
+ layoutType: 'captioned',
49
+ title: 't',
50
+ bannerUrl: HERO
51
+ })).toBe('classic');
52
+ expect(resolveInboxLayout({
53
+ layoutType: 'carousel',
54
+ body: 'b',
55
+ carousel: [SLIDE]
56
+ })).toBe('classic');
57
+ expect(resolveInboxLayout({
58
+ layoutType: 'carousel',
59
+ title: 't',
60
+ carousel: [SLIDE]
61
+ })).toBe('classic');
62
+ });
63
+ it('degrades a carousel without valid slides into classic', () => {
64
+ expect(resolveInboxLayout({
65
+ layoutType: 'carousel',
66
+ title: 't',
67
+ body: 'b'
68
+ })).toBe('classic');
69
+ expect(resolveInboxLayout({
70
+ layoutType: 'carousel',
71
+ title: 't',
72
+ body: 'b',
73
+ carousel: [{
74
+ caption: 'no image'
75
+ }]
76
+ })).toBe('classic');
77
+ });
78
+ it('uses the icon as the hero fallback', () => {
79
+ expect(resolveInboxLayout({
80
+ layoutType: 'banner',
81
+ iconUrl: HERO
82
+ })).toBe('banner');
83
+ });
84
+ it('applies the SDK heuristic to unknown or absent layouts', () => {
85
+ expect(resolveInboxLayout({
86
+ bannerUrl: HERO
87
+ })).toBe('banner');
88
+ expect(resolveInboxLayout({
89
+ title: 't',
90
+ body: 'b',
91
+ bannerUrl: HERO
92
+ })).toBe('captioned');
93
+ expect(resolveInboxLayout({
94
+ title: 't',
95
+ body: 'b'
96
+ })).toBe('classic');
97
+ expect(resolveInboxLayout({
98
+ layoutType: 'video',
99
+ title: 't',
100
+ body: 'b'
101
+ })).toBe('classic');
102
+ });
103
+ });
104
+ describe('getValidSlides', () => {
105
+ it('drops slides without an image and keeps at most the SDK limit', () => {
106
+ const slides = [...Array.from({
107
+ length: MAX_CAROUSEL_SLIDES + 2
108
+ }, (_, index) => ({
109
+ imageUrl: `https://cdn.example.com/${index}.jpg`
110
+ })), {
111
+ caption: 'no image'
112
+ }];
113
+ const valid = getValidSlides(slides);
114
+ expect(valid).toHaveLength(MAX_CAROUSEL_SLIDES);
115
+ expect(valid.every(slide => !!slide.imageUrl)).toBe(true);
116
+ });
117
+ });
118
+ describe('getPreviewContent', () => {
119
+ const en = {
120
+ title: 'en'
121
+ };
122
+ const de = {
123
+ title: 'de'
124
+ };
125
+ it('prefers the explicit content over the localized map', () => {
126
+ expect(getPreviewContent(de, {
127
+ en
128
+ }, 'en')).toBe(de);
129
+ });
130
+ it('picks by language with default/en/first fallbacks', () => {
131
+ expect(getPreviewContent(null, {
132
+ en,
133
+ de
134
+ }, 'de')).toBe(de);
135
+ expect(getPreviewContent(null, {
136
+ en,
137
+ de
138
+ }, 'fr')).toBe(en);
139
+ expect(getPreviewContent(null, {
140
+ de
141
+ }, 'fr')).toBe(de);
142
+ expect(getPreviewContent(null, undefined, 'en')).toBeNull();
143
+ expect(getPreviewContent(null, {}, 'en')).toBeNull();
144
+ });
145
+ });
146
+ describe('empty state', () => {
147
+ it('detects content with nothing to render', () => {
148
+ expect(isEmptyContent({
149
+ layoutType: 'captioned'
150
+ })).toBe(true);
151
+ expect(isEmptyContent({
152
+ carousel: [{
153
+ caption: 'no image'
154
+ }]
155
+ })).toBe(true);
156
+ expect(isEmptyContent({
157
+ title: 't'
158
+ })).toBe(false);
159
+ expect(isEmptyContent({
160
+ bannerUrl: 'https://cdn.example.com/hero.jpg'
161
+ })).toBe(false);
162
+ });
163
+ it('shows the placeholder of the requested layout, classic for unknown', () => {
164
+ expect(getEmptyLayout({
165
+ layoutType: 'banner'
166
+ })).toBe('banner');
167
+ expect(getEmptyLayout({
168
+ layoutType: 'video'
169
+ })).toBe('classic');
170
+ expect(getEmptyLayout({})).toBe('classic');
171
+ });
172
+ });
173
+ describe('getPreviewTexts', () => {
174
+ it('moves the body into the title slot for classic without a title', () => {
175
+ expect(getPreviewTexts({
176
+ body: 'b'
177
+ }, 'classic')).toEqual({
178
+ title: 'b',
179
+ body: ''
180
+ });
181
+ expect(getPreviewTexts({
182
+ title: 't',
183
+ body: 'b'
184
+ }, 'classic')).toEqual({
185
+ title: 't',
186
+ body: 'b'
187
+ });
188
+ });
189
+ it('keeps the fields as-is for media layouts', () => {
190
+ expect(getPreviewTexts({
191
+ body: 'b'
192
+ }, 'captioned')).toEqual({
193
+ title: '',
194
+ body: 'b'
195
+ });
196
+ expect(getPreviewTexts({}, 'classic')).toEqual({
197
+ title: '',
198
+ body: ''
199
+ });
200
+ });
201
+ });
@@ -0,0 +1,4 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { InboxCellProps } from '../../types';
3
+ /** Android inbox cell: a flat list row with the time trailing the title. */
4
+ export declare function InboxAndroidCell(props: InboxCellProps): ReactElement;
@@ -0,0 +1,70 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Color } from '@pushwoosh/kit-constants';
3
+ import { FlexContainer, Vertical } from '@pushwoosh/kit-helpers';
4
+ import { Text } from '@pushwoosh/kit-typography';
5
+ import { ClampText } from '../../styles';
6
+ import { InboxCellAvatar } from '../InboxCellAvatar';
7
+ import { InboxCellMedia } from '../InboxCellMedia';
8
+ /** Android inbox cell: a flat list row with the time trailing the title. */
9
+ export function InboxAndroidCell(props) {
10
+ const {
11
+ content,
12
+ layout,
13
+ isEmpty,
14
+ title,
15
+ body,
16
+ dateLabel
17
+ } = props;
18
+ const texts = _jsxs(Vertical, {
19
+ "$flex": 1,
20
+ "$gap": 8,
21
+ "$minWidth": 0,
22
+ children: [_jsxs(Text, {
23
+ "$color": Color.MAIN,
24
+ "$ellipsis": true,
25
+ "$variant": "footnote",
26
+ children: [title, ' ', _jsx(Text, {
27
+ "$color": Color.LOCKED,
28
+ "$variant": "footnote",
29
+ children: dateLabel
30
+ })]
31
+ }), !!body && _jsx(ClampText, {
32
+ "$clamp": 3,
33
+ "$color": Color.MAIN,
34
+ "$variant": "footnote",
35
+ children: body
36
+ })]
37
+ });
38
+ if (layout === 'classic') {
39
+ return _jsx(Vertical, {
40
+ "$bgColor": Color.CLEAR,
41
+ "$border": {
42
+ bottom: `1px solid ${Color.DIVIDER}`
43
+ },
44
+ "$gap": 16,
45
+ "$padding": 16,
46
+ children: _jsxs(FlexContainer, {
47
+ "$alignItems": "start",
48
+ "$gap": 12,
49
+ children: [_jsx(InboxCellAvatar, {
50
+ content: content,
51
+ isEmpty: isEmpty,
52
+ platform: "android"
53
+ }), texts]
54
+ })
55
+ });
56
+ }
57
+ return _jsxs(Vertical, {
58
+ "$bgColor": Color.CLEAR,
59
+ "$border": {
60
+ bottom: `1px solid ${Color.DIVIDER}`
61
+ },
62
+ "$gap": 16,
63
+ "$padding": 16,
64
+ children: [_jsx(InboxCellMedia, {
65
+ content: content,
66
+ isEmpty: isEmpty,
67
+ layout: layout
68
+ }), layout !== 'banner' && texts]
69
+ });
70
+ }
@@ -0,0 +1 @@
1
+ export { InboxAndroidCell } from './InboxAndroidCell';
@@ -0,0 +1 @@
1
+ export { InboxAndroidCell } from './InboxAndroidCell';
@@ -0,0 +1,4 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { InboxCellAvatarProps } from './types';
3
+ /** Inbox icon of a cell: the uploaded image, the colored initial the SDK falls back to, or the placeholder. */
4
+ export declare function InboxCellAvatar(props: InboxCellAvatarProps): ReactElement;
@@ -0,0 +1,48 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Color } from '@pushwoosh/kit-constants';
3
+ import { Horizontal } from '@pushwoosh/kit-helpers';
4
+ import { Text } from '@pushwoosh/kit-typography';
5
+ import { AvatarImage } from './styles';
6
+ import { INBOX_AVATAR } from '../../constants';
7
+ import { getIconInitial } from '../../helpers';
8
+ /** Inbox icon of a cell: the uploaded image, the colored initial the SDK falls back to, or the placeholder. */
9
+ export function InboxCellAvatar(props) {
10
+ const {
11
+ content,
12
+ isEmpty,
13
+ platform
14
+ } = props;
15
+ const {
16
+ size,
17
+ radius,
18
+ initialVariant
19
+ } = INBOX_AVATAR[platform];
20
+ if (isEmpty) {
21
+ return _jsx(Horizontal, {
22
+ "$bgColor": Color.BRIGHT_LIGHT_HOVER,
23
+ "$border": `1px dashed ${Color.BRIGHT}`,
24
+ "$borderRadius": radius,
25
+ "$height": size,
26
+ "$shrink": 0,
27
+ "$width": size
28
+ });
29
+ }
30
+ return _jsx(Horizontal, {
31
+ "$alignItems": "center",
32
+ "$bgColor": Color.PHANTOM,
33
+ "$borderRadius": radius,
34
+ "$height": size,
35
+ "$justifyContent": "center",
36
+ "$overflow": "hidden",
37
+ "$shrink": 0,
38
+ "$width": size,
39
+ children: content.iconUrl ? _jsx(AvatarImage, {
40
+ alt: content.title || '',
41
+ src: content.iconUrl
42
+ }) : _jsx(Text, {
43
+ "$color": Color.MAIN,
44
+ "$variant": initialVariant,
45
+ children: getIconInitial(content)
46
+ })
47
+ });
48
+ }
@@ -0,0 +1 @@
1
+ export { InboxCellAvatar } from './InboxCellAvatar';
@@ -0,0 +1 @@
1
+ export { InboxCellAvatar } from './InboxCellAvatar';
@@ -0,0 +1 @@
1
+ export declare const AvatarImage: import("styled-components").StyledComponent<"img", any, {}, never>;
@@ -0,0 +1,5 @@
1
+ import styled from 'styled-components';
2
+ export const AvatarImage = styled.img.withConfig({
3
+ displayName: "AvatarImage",
4
+ componentId: "sc-1mitg2x-0"
5
+ })(["width:100%;height:100%;object-fit:cover;"]);
@@ -0,0 +1,10 @@
1
+ import type { InboxPreviewContent, InboxPreviewPlatform } from '../../types';
2
+ /** Props of {@link InboxCellAvatar}. */
3
+ export interface InboxCellAvatarProps {
4
+ /** Content whose icon is drawn. */
5
+ content: InboxPreviewContent;
6
+ /** Draw the dashed placeholder instead of the icon. */
7
+ isEmpty: boolean;
8
+ /** Platform whose icon geometry is used. */
9
+ platform: InboxPreviewPlatform;
10
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { InboxCellCarouselProps } from './types';
3
+ /** Carousel cell: the slides the SDK would keep, switched by a tap on the image or by a pager dot. */
4
+ export declare function InboxCellCarousel(props: InboxCellCarouselProps): ReactElement;
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Horizontal } from '@pushwoosh/kit-helpers';
4
+ import { CarouselViewport, PagerDot, SlideCaption } from './styles';
5
+ import { getValidSlides } from '../../helpers';
6
+ import { HeroImage } from '../../styles';
7
+ /** Carousel cell: the slides the SDK would keep, switched by a tap on the image or by a pager dot. */
8
+ export function InboxCellCarousel(props) {
9
+ const {
10
+ content,
11
+ dotsOnImage = false
12
+ } = props;
13
+ const slides = getValidSlides(content.carousel);
14
+ const [index, setIndex] = useState(0);
15
+ const activeIndex = Math.min(index, slides.length - 1);
16
+ const current = slides[activeIndex];
17
+ const dots = slides.length > 1 && slides.map((_slide, slideIndex) => _jsx(PagerDot, {
18
+ "$active": slideIndex === activeIndex,
19
+ onClick: event => {
20
+ event.stopPropagation();
21
+ setIndex(slideIndex);
22
+ },
23
+ type: "button"
24
+ }, slideIndex));
25
+ return _jsxs(_Fragment, {
26
+ children: [_jsxs(CarouselViewport, {
27
+ onClick: () => setIndex((activeIndex + 1) % slides.length),
28
+ children: [_jsx(HeroImage, {
29
+ alt: current.caption || '',
30
+ src: current.imageUrl
31
+ }), !!current.caption && _jsx(SlideCaption, {
32
+ children: current.caption
33
+ }), dotsOnImage && dots && _jsx(Horizontal, {
34
+ "$alignItems": "center",
35
+ "$bottom": 8,
36
+ "$gap": 6,
37
+ "$justifyContent": "center",
38
+ "$left": 0,
39
+ "$position": "absolute",
40
+ "$right": 0,
41
+ children: dots
42
+ })]
43
+ }), !dotsOnImage && dots && _jsx(Horizontal, {
44
+ "$alignItems": "center",
45
+ "$gap": 6,
46
+ "$justifyContent": "center",
47
+ "$padding": {
48
+ top: 2
49
+ },
50
+ children: dots
51
+ })]
52
+ });
53
+ }
@@ -0,0 +1 @@
1
+ export { InboxCellCarousel } from './InboxCellCarousel';
@@ -0,0 +1 @@
1
+ export { InboxCellCarousel } from './InboxCellCarousel';
@@ -0,0 +1,29 @@
1
+ import { Color } from '@pushwoosh/kit-constants';
2
+ export declare const CarouselViewport: import("styled-components").StyledComponent<"div", any, import("@pushwoosh/kit-helpers/styled-helpers").CommonBoxProps & {
3
+ $alignContent?: import("@pushwoosh/kit-helpers/styled-helpers").AlignContentValue | undefined;
4
+ $alignItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
5
+ $gap?: import("@pushwoosh/kit-helpers/styled-helpers").StrNum | undefined;
6
+ $justifyContent?: import("@pushwoosh/kit-helpers/styled-helpers").JustifyContentValue | undefined;
7
+ } & {
8
+ $gridAutoFlow?: "row" | "column" | "dense" | "row dense" | "column dense" | undefined;
9
+ $justifyItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
10
+ $placeItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
11
+ } & {
12
+ $gridAutoFlow: string;
13
+ } & {
14
+ $position: string;
15
+ }, "$gridAutoFlow" | "$position">;
16
+ export declare const SlideCaption: import("styled-components").StyledComponent<"span", any, {
17
+ $color?: string | undefined;
18
+ $uppercase?: boolean | undefined;
19
+ $ellipsis?: boolean | undefined;
20
+ $variant?: import("@pushwoosh/kit-typography").TypographyVariant | undefined;
21
+ } & {
22
+ $clamp?: number;
23
+ } & {
24
+ $color: Color;
25
+ $variant: "h5";
26
+ }, "$color" | "$variant">;
27
+ export declare const PagerDot: import("styled-components").StyledComponent<"button", any, {
28
+ $active?: boolean;
29
+ }, never>;
@@ -0,0 +1,24 @@
1
+ import styled from 'styled-components';
2
+ import { Color, ShapeRadius } from '@pushwoosh/kit-constants';
3
+ import { Vertical } from '@pushwoosh/kit-helpers';
4
+ import { INBOX_SLIDE_SCRIM, INBOX_UNREAD_DOT_SIZE } from '../../constants';
5
+ import { ClampText } from '../../styles';
6
+ export const CarouselViewport = styled(Vertical).attrs({
7
+ $position: 'relative'
8
+ }).withConfig({
9
+ displayName: "CarouselViewport",
10
+ componentId: "sc-1fw4dgw-0"
11
+ })(["cursor:pointer;"]);
12
+ export const SlideCaption = styled(ClampText).attrs({
13
+ $color: Color.CLEAR,
14
+ $variant: 'h5'
15
+ }).withConfig({
16
+ displayName: "SlideCaption",
17
+ componentId: "sc-1fw4dgw-1"
18
+ })(["position:absolute;left:0;right:0;bottom:0;padding:14px 10px 6px;border-radius:0 0 ", " ", ";background:linear-gradient(transparent,", ");"], ShapeRadius.SECTION, ShapeRadius.SECTION, INBOX_SLIDE_SCRIM);
19
+ export const PagerDot = styled.button.withConfig({
20
+ displayName: "PagerDot",
21
+ componentId: "sc-1fw4dgw-2"
22
+ })(["width:", "px;height:", "px;padding:0;border:none;border-radius:50%;background:", ";cursor:pointer;"], INBOX_UNREAD_DOT_SIZE, INBOX_UNREAD_DOT_SIZE, ({
23
+ $active
24
+ }) => $active ? Color.BRIGHT : Color.DIVIDER);
@@ -0,0 +1,8 @@
1
+ import type { InboxPreviewContent } from '../../types';
2
+ /** Props of {@link InboxCellCarousel}. */
3
+ export interface InboxCellCarouselProps {
4
+ /** Content whose slides are drawn. */
5
+ content: InboxPreviewContent;
6
+ /** Draw the pager dots over the slide instead of under it, the way the web widget does. */
7
+ dotsOnImage?: boolean;
8
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { InboxCellMediaProps } from './types';
3
+ /** Media area of a non-classic cell: the hero image, the carousel, or the placeholder of both. */
4
+ export declare function InboxCellMedia(props: InboxCellMediaProps): ReactElement;
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { getHeroUrl } from '../../helpers';
3
+ import { EmptyHero, HeroImage } from '../../styles';
4
+ import { InboxCellCarousel } from '../InboxCellCarousel';
5
+ /** Media area of a non-classic cell: the hero image, the carousel, or the placeholder of both. */
6
+ export function InboxCellMedia(props) {
7
+ const {
8
+ content,
9
+ layout,
10
+ isEmpty,
11
+ dotsOnImage = false
12
+ } = props;
13
+ if (isEmpty) {
14
+ return _jsx(EmptyHero, {});
15
+ }
16
+ if (layout === 'carousel') {
17
+ return _jsx(InboxCellCarousel, {
18
+ content: content,
19
+ dotsOnImage: dotsOnImage
20
+ });
21
+ }
22
+ return _jsx(HeroImage, {
23
+ alt: content.title || '',
24
+ src: getHeroUrl(content)
25
+ });
26
+ }
@@ -0,0 +1 @@
1
+ export { InboxCellMedia } from './InboxCellMedia';
@@ -0,0 +1 @@
1
+ export { InboxCellMedia } from './InboxCellMedia';
@@ -0,0 +1,12 @@
1
+ import type { InboxLayoutType, InboxPreviewContent } from '../../types';
2
+ /** Props of {@link InboxCellMedia}. */
3
+ export interface InboxCellMediaProps {
4
+ /** Content whose hero image or slides are drawn. */
5
+ content: InboxPreviewContent;
6
+ /** Layout the SDK would draw for this content. */
7
+ layout: InboxLayoutType;
8
+ /** Draw the dashed placeholder instead of the media. */
9
+ isEmpty: boolean;
10
+ /** Draw the carousel pager dots over the slide instead of under it. */
11
+ dotsOnImage?: boolean;
12
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { InboxCellProps } from '../../types';
3
+ /** iOS inbox cell: a rounded card, with the texts on a plate below the media in the media layouts. */
4
+ export declare function InboxIOSCell(props: InboxCellProps): ReactElement;