@pushwoosh/dumb-components 1.1.224 → 1.1.226

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 (78) hide show
  1. package/Switch/Switch.d.ts +1 -1
  2. package/Switch/Switch.js +9 -2
  3. package/Switch/__tests__/Switch.test.d.ts +1 -0
  4. package/Switch/__tests__/Switch.test.js +44 -0
  5. package/Switch/styles.js +4 -2
  6. package/Switch/types.d.ts +2 -1
  7. package/WhatsAppPreview/WhatsAppPreview.d.ts +1 -1
  8. package/WhatsAppPreview/WhatsAppPreview.js +31 -92
  9. package/WhatsAppPreview/__tests__/attachment.test.js +17 -11
  10. package/WhatsAppPreview/components/WhatsAppAttachment/WhatsAppAttachment.js +41 -38
  11. package/WhatsAppPreview/components/WhatsAppAttachment/styles.d.ts +11 -30
  12. package/WhatsAppPreview/components/WhatsAppAttachment/styles.js +23 -30
  13. package/WhatsAppPreview/components/WhatsAppAttachment/types.d.ts +0 -5
  14. package/WhatsAppPreview/components/WhatsAppMessageBubble/WhatsAppMessageBubble.d.ts +1 -1
  15. package/WhatsAppPreview/components/WhatsAppMessageBubble/WhatsAppMessageBubble.js +14 -33
  16. package/WhatsAppPreview/components/WhatsAppMessageBubble/styles.d.ts +2 -16
  17. package/WhatsAppPreview/components/WhatsAppMessageBubble/styles.js +5 -33
  18. package/WhatsAppPreview/constants.d.ts +10 -40
  19. package/WhatsAppPreview/constants.js +11 -41
  20. package/WhatsAppPreview/helpers.d.ts +3 -1
  21. package/WhatsAppPreview/helpers.js +12 -4
  22. package/WhatsAppPreview/icons/index.d.ts +0 -10
  23. package/WhatsAppPreview/icons/index.js +1 -11
  24. package/WhatsAppPreview/index.d.ts +1 -1
  25. package/WhatsAppPreview/polyglot/messages_ar.js +2 -3
  26. package/WhatsAppPreview/polyglot/messages_bn.js +2 -3
  27. package/WhatsAppPreview/polyglot/messages_de.js +2 -3
  28. package/WhatsAppPreview/polyglot/messages_en.js +2 -3
  29. package/WhatsAppPreview/polyglot/messages_es.js +2 -3
  30. package/WhatsAppPreview/polyglot/messages_fr.js +2 -3
  31. package/WhatsAppPreview/polyglot/messages_he.js +2 -3
  32. package/WhatsAppPreview/polyglot/messages_hi.js +2 -3
  33. package/WhatsAppPreview/polyglot/messages_ja.js +2 -3
  34. package/WhatsAppPreview/polyglot/messages_ko.js +2 -3
  35. package/WhatsAppPreview/polyglot/messages_pt.js +2 -3
  36. package/WhatsAppPreview/polyglot/messages_ru.js +2 -3
  37. package/WhatsAppPreview/polyglot/messages_th.js +2 -3
  38. package/WhatsAppPreview/polyglot/messages_zh.js +2 -3
  39. package/WhatsAppPreview/polyglot/types.d.ts +3 -2
  40. package/WhatsAppPreview/styles.d.ts +21 -14
  41. package/WhatsAppPreview/styles.js +22 -19
  42. package/WhatsAppPreview/types.d.ts +11 -35
  43. package/index.d.ts +1 -1
  44. package/package.json +1 -1
  45. package/WhatsAppPreview/components/WhatsAppChatHeader/WhatsAppChatHeader.d.ts +0 -4
  46. package/WhatsAppPreview/components/WhatsAppChatHeader/WhatsAppChatHeader.js +0 -39
  47. package/WhatsAppPreview/components/WhatsAppChatHeader/index.d.ts +0 -1
  48. package/WhatsAppPreview/components/WhatsAppChatHeader/index.js +0 -1
  49. package/WhatsAppPreview/components/WhatsAppChatHeader/styles.d.ts +0 -47
  50. package/WhatsAppPreview/components/WhatsAppChatHeader/styles.js +0 -37
  51. package/WhatsAppPreview/components/WhatsAppChatHeader/types.d.ts +0 -10
  52. package/WhatsAppPreview/components/WhatsAppChatHeader/types.js +0 -1
  53. package/WhatsAppPreview/components/WhatsAppDateChip/WhatsAppDateChip.d.ts +0 -4
  54. package/WhatsAppPreview/components/WhatsAppDateChip/WhatsAppDateChip.js +0 -28
  55. package/WhatsAppPreview/components/WhatsAppDateChip/index.d.ts +0 -1
  56. package/WhatsAppPreview/components/WhatsAppDateChip/index.js +0 -1
  57. package/WhatsAppPreview/components/WhatsAppDateChip/styles.d.ts +0 -6
  58. package/WhatsAppPreview/components/WhatsAppDateChip/styles.js +0 -6
  59. package/WhatsAppPreview/components/WhatsAppDateChip/types.d.ts +0 -6
  60. package/WhatsAppPreview/components/WhatsAppDateChip/types.js +0 -1
  61. package/WhatsAppPreview/components/WhatsAppStatusBar/WhatsAppStatusBar.d.ts +0 -4
  62. package/WhatsAppPreview/components/WhatsAppStatusBar/WhatsAppStatusBar.js +0 -18
  63. package/WhatsAppPreview/components/WhatsAppStatusBar/index.d.ts +0 -1
  64. package/WhatsAppPreview/components/WhatsAppStatusBar/index.js +0 -1
  65. package/WhatsAppPreview/components/WhatsAppStatusBar/styles.d.ts +0 -69
  66. package/WhatsAppPreview/components/WhatsAppStatusBar/styles.js +0 -47
  67. package/WhatsAppPreview/components/WhatsAppStatusBar/types.d.ts +0 -5
  68. package/WhatsAppPreview/components/WhatsAppStatusBar/types.js +0 -1
  69. package/WhatsAppPreview/icons/WhatsAppAvatarIcon.svg +0 -1
  70. package/WhatsAppPreview/icons/WhatsAppBackIcon.svg +0 -1
  71. package/WhatsAppPreview/icons/WhatsAppBatteryIcon.svg +0 -1
  72. package/WhatsAppPreview/icons/WhatsAppCallIcon.svg +0 -1
  73. package/WhatsAppPreview/icons/WhatsAppMenuIcon.svg +0 -1
  74. package/WhatsAppPreview/icons/WhatsAppSignalIcon.svg +0 -1
  75. package/WhatsAppPreview/icons/WhatsAppTickIcon.svg +0 -1
  76. package/WhatsAppPreview/icons/WhatsAppTicksIcon.svg +0 -1
  77. package/WhatsAppPreview/icons/WhatsAppWallpaperPattern.svg +0 -1
  78. package/WhatsAppPreview/icons/WhatsAppWifiIcon.svg +0 -1
@@ -1,7 +1,7 @@
1
1
  import { type ReactElement } from 'react';
2
2
  import type { SwitchProps } from './types';
3
3
  /**
4
- * Toggle switch for a boolean value, with an optional label on either side.
4
+ * Toggle switch for a boolean value, with an optional label on either side; a click anywhere flips it.
5
5
  *
6
6
  * @example
7
7
  * <Switch enabled={on} onChange={() => setOn((v) => !v)}>Notifications</Switch>
package/Switch/Switch.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback } from 'react';
2
3
  import { Container, Box, Circle, Label } from './styles';
3
4
  /**
4
- * Toggle switch for a boolean value, with an optional label on either side.
5
+ * Toggle switch for a boolean value, with an optional label on either side; a click anywhere flips it.
5
6
  *
6
7
  * @example
7
8
  * <Switch enabled={on} onChange={() => setOn((v) => !v)}>Notifications</Switch>
@@ -13,12 +14,18 @@ export function Switch({
13
14
  children,
14
15
  onChange
15
16
  }) {
17
+ const handleClick = useCallback(() => {
18
+ if (!isDisabled) {
19
+ onChange();
20
+ }
21
+ }, [isDisabled, onChange]);
16
22
  return _jsxs(Container, {
17
23
  labelPosition: labelPosition,
24
+ isDisabled: isDisabled,
25
+ onClick: handleClick,
18
26
  children: [_jsx(Box, {
19
27
  enabled: enabled,
20
28
  isDisabled: isDisabled,
21
- onClick: onChange,
22
29
  children: _jsx(Circle, {
23
30
  enabled: enabled,
24
31
  isDisabled: isDisabled
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,44 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { fireEvent, render, screen } from '@testing-library/react';
3
+ import { Switch } from '../Switch';
4
+ describe('Switch', () => {
5
+ it('flips on a click on the label, not only on the toggle', () => {
6
+ const onChange = jest.fn();
7
+ render(_jsx(Switch, {
8
+ enabled: false,
9
+ onChange: onChange,
10
+ children: "Save inbox"
11
+ }));
12
+ fireEvent.click(screen.getByText('Save inbox'));
13
+ expect(onChange).toHaveBeenCalledTimes(1);
14
+ });
15
+ it('flips on a click on the toggle', () => {
16
+ const onChange = jest.fn();
17
+ const {
18
+ container
19
+ } = render(_jsx(Switch, {
20
+ enabled: true,
21
+ onChange: onChange,
22
+ children: "Save inbox"
23
+ }));
24
+ const box = container.querySelector('[tabindex="0"]');
25
+ if (!box) {
26
+ throw new Error('toggle not rendered');
27
+ }
28
+ fireEvent.click(box);
29
+ expect(onChange).toHaveBeenCalledTimes(1);
30
+ });
31
+ it('stays silent while disabled, label and toggle alike', () => {
32
+ const onChange = jest.fn();
33
+ const {
34
+ container
35
+ } = render(_jsx(Switch, {
36
+ isDisabled: true,
37
+ onChange: onChange,
38
+ children: "Save inbox"
39
+ }));
40
+ fireEvent.click(screen.getByText('Save inbox'));
41
+ fireEvent.click(container.querySelector('[tabindex="0"]'));
42
+ expect(onChange).not.toHaveBeenCalled();
43
+ });
44
+ });
package/Switch/styles.js CHANGED
@@ -37,9 +37,11 @@ const cssActive = css(["&:active{background:", ";border:2px solid ", ";}"], Colo
37
37
  export const Container = styled.div.withConfig({
38
38
  displayName: "Container",
39
39
  componentId: "sc-csdrg2-0"
40
- })(["display:flex;align-items:center;flex-direction:", ";"], ({
40
+ })(["display:flex;align-items:center;flex-direction:", ";cursor:", ";"], ({
41
41
  labelPosition
42
- }) => labelPosition === 'left' ? 'row-reverse' : 'row');
42
+ }) => labelPosition === 'left' ? 'row-reverse' : 'row', ({
43
+ isDisabled
44
+ }) => isDisabled ? 'not-allowed' : 'pointer');
43
45
  export const Box = styled.div.attrs({
44
46
  tabIndex: '0'
45
47
  }).withConfig({
package/Switch/types.d.ts CHANGED
@@ -12,9 +12,10 @@ export interface SwitchProps {
12
12
  /** Fires when the toggle is clicked; flip `enabled` in the handler. */
13
13
  onChange: () => void;
14
14
  }
15
- /** Internal style prop carrying the label side. */
15
+ /** Internal style props carrying the label side and the disabled state. */
16
16
  export interface AlignProps {
17
17
  labelPosition?: string;
18
+ isDisabled?: boolean;
18
19
  }
19
20
  /** Internal style prop carrying the toggle state. */
20
21
  export interface ComponentProps {
@@ -1,4 +1,4 @@
1
1
  import { type ReactElement } from 'react';
2
2
  import type { WhatsAppPreviewProps } from './types';
3
- /** Renders a WhatsApp conversation the way the recipient sees it, WhatsApp markup included. */
3
+ /** Renders a WhatsApp message the way the recipient sees it, WhatsApp markup and attachments included. */
4
4
  export declare function WhatsAppPreview(props: WhatsAppPreviewProps): ReactElement;
@@ -1,105 +1,44 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Color } from '@pushwoosh/kit-constants';
3
- import { Horizontal, Rows, Vertical } from '@pushwoosh/kit-helpers';
4
- import { Text } from '@pushwoosh/kit-typography';
5
- import { WhatsAppChatHeader } from './components/WhatsAppChatHeader';
6
- import { WhatsAppDateChip } from './components/WhatsAppDateChip';
2
+ import { Color, ShapeRadius } from '@pushwoosh/kit-constants';
3
+ import { Horizontal } from '@pushwoosh/kit-helpers';
7
4
  import { WhatsAppMessageBubble } from './components/WhatsAppMessageBubble';
8
- import { WhatsAppStatusBar } from './components/WhatsAppStatusBar';
9
- import { WHATSAPP_COLOR, WHATSAPP_PREVIEW_HEIGHT, WHATSAPP_PREVIEW_WIDTH, WHATSAPP_STATUS_BAR_TIME } from './constants';
5
+ import { WHATSAPP_BACKDROP_PADDING, WHATSAPP_BACKDROP_WIDTH, WHATSAPP_BUBBLE_PADDING } from './constants';
10
6
  import { isMessageDrawable } from './helpers';
11
- import { WhatsAppWallpaperPattern } from './icons';
12
7
  import { Lang } from './polyglot';
13
- import { DeviceBox, WallpaperImage, WallpaperLayer } from './styles';
8
+ import { Backdrop, Bubble, PreviewText } from './styles';
14
9
  import { Spinner } from '../Spinner';
15
- /** Renders a WhatsApp conversation the way the recipient sees it, WhatsApp markup included. */
10
+ /** Renders a WhatsApp message the way the recipient sees it, WhatsApp markup and attachments included. */
16
11
  export function WhatsAppPreview(props) {
17
12
  const {
18
- messages = [],
19
- contactName = '',
20
- contactSubtitle,
21
- avatarUrl,
22
- dateLabel,
23
- statusBarTime = WHATSAPP_STATUS_BAR_TIME,
24
- wallpaperUrl,
13
+ message,
25
14
  emptyText,
26
- width = WHATSAPP_PREVIEW_WIDTH,
27
- height = WHATSAPP_PREVIEW_HEIGHT,
28
15
  isLoading = false
29
16
  } = props;
30
- const drawnMessages = messages.filter(isMessageDrawable);
31
- const separator = dateLabel === undefined ? _jsx(Lang, {
32
- message: "DUMB.WHATSAPP_PREVIEW.TODAY"
33
- }) : dateLabel;
34
- return _jsx(DeviceBox, {
35
- "$height": height,
36
- "$width": width,
37
- children: _jsxs(Rows, {
38
- "$bgColor": WHATSAPP_COLOR.HEADER,
39
- "$borderRadius": 39,
40
- "$overflow": "hidden",
41
- "$sizes": "auto auto minmax(0, 1fr)",
42
- children: [_jsx(WhatsAppStatusBar, {
43
- time: statusBarTime
44
- }), _jsx(WhatsAppChatHeader, {
45
- avatarUrl: avatarUrl,
46
- name: contactName,
47
- subtitle: contactSubtitle ?? _jsx(Lang, {
48
- message: "DUMB.WHATSAPP_PREVIEW.BUSINESS_ACCOUNT"
17
+ const isDrawable = message !== undefined && isMessageDrawable(message);
18
+ return _jsxs(Backdrop, {
19
+ "$alignContent": "start",
20
+ "$bgColor": Color.SOFT_LIGHT,
21
+ "$borderRadius": ShapeRadius.SECTION,
22
+ "$padding": WHATSAPP_BACKDROP_PADDING,
23
+ "$width": WHATSAPP_BACKDROP_WIDTH,
24
+ children: [isLoading && _jsx(Horizontal, {
25
+ "$alignItems": "center",
26
+ "$justifyContent": "center",
27
+ "$padding": WHATSAPP_BUBBLE_PADDING,
28
+ children: _jsx(Spinner, {
29
+ color: Color.LOCKED,
30
+ size: "medium"
31
+ })
32
+ }), !isLoading && !isDrawable && _jsx(Bubble, {
33
+ children: _jsx(PreviewText, {
34
+ "$color": Color.LOCKED,
35
+ "$ellipsis": true,
36
+ children: emptyText ?? _jsx(Lang, {
37
+ message: "DUMB.WHATSAPP_PREVIEW.EMPTY"
49
38
  })
50
- }), _jsxs(Vertical, {
51
- "$bgColor": WHATSAPP_COLOR.SCREEN,
52
- "$overflow": "hidden",
53
- "$position": "relative",
54
- children: [_jsx(WallpaperLayer, {
55
- children: wallpaperUrl ? _jsx(WallpaperImage, {
56
- alt: "",
57
- src: wallpaperUrl
58
- }) : _jsx(WhatsAppWallpaperPattern, {})
59
- }), isLoading && _jsx(Horizontal, {
60
- "$alignItems": "center",
61
- "$inset": 0,
62
- "$justifyContent": "center",
63
- "$position": "absolute",
64
- children: _jsx(Spinner, {
65
- color: Color.LOCKED,
66
- size: "medium"
67
- })
68
- }), !isLoading && drawnMessages.length === 0 && _jsx(Horizontal, {
69
- "$alignItems": "center",
70
- "$inset": 0,
71
- "$justifyContent": "center",
72
- "$padding": 24,
73
- "$position": "absolute",
74
- children: _jsx(Text, {
75
- "$color": WHATSAPP_COLOR.SUBTITLE,
76
- "$variant": "footnote",
77
- children: emptyText ?? _jsx(Lang, {
78
- message: "DUMB.WHATSAPP_PREVIEW.EMPTY"
79
- })
80
- })
81
- }), !isLoading && drawnMessages.length > 0 && _jsx(Vertical, {
82
- "$inset": 0,
83
- "$overflowY": "auto",
84
- "$position": "absolute",
85
- children: _jsxs(Vertical, {
86
- "$alignContent": "start",
87
- "$gap": 8,
88
- "$minHeight": "100%",
89
- "$padding": {
90
- top: 12,
91
- right: 9,
92
- bottom: 16,
93
- left: 9
94
- },
95
- children: [separator && _jsx(WhatsAppDateChip, {
96
- children: separator
97
- }), drawnMessages.map((message, index) => _jsx(WhatsAppMessageBubble, {
98
- message: message
99
- }, message.id ?? index))]
100
- })
101
- })]
102
- })]
103
- })
39
+ })
40
+ }), !isLoading && isDrawable && _jsx(WhatsAppMessageBubble, {
41
+ message: message
42
+ })]
104
43
  });
105
44
  }
@@ -53,6 +53,18 @@ describe('attachment meta', () => {
53
53
  source: SOURCE
54
54
  })).toBe('');
55
55
  });
56
+ it('falls back to the MIME subtype when the name has no extension', () => {
57
+ expect(getAttachmentExtension({
58
+ name: 'Title',
59
+ source: SOURCE,
60
+ mimeType: 'application/PDF'
61
+ })).toBe('pdf');
62
+ expect(getAttachmentExtension({
63
+ name: 'Title.docx',
64
+ source: SOURCE,
65
+ mimeType: 'application/pdf'
66
+ })).toBe('docx');
67
+ });
56
68
  it('writes sizes the way WhatsApp does', () => {
57
69
  expect(formatAttachmentSize(912)).toBe('912 B');
58
70
  expect(formatAttachmentSize(69_632)).toBe('68 kB');
@@ -70,28 +82,22 @@ describe('attachment meta', () => {
70
82
  describe('isMessageDrawable', () => {
71
83
  it('keeps a message that has a body or a file', () => {
72
84
  expect(isMessageDrawable({
73
- direction: 'incoming',
74
85
  text: 'hi'
75
86
  })).toBe(true);
76
87
  expect(isMessageDrawable({
77
- direction: 'incoming',
78
- attachment: {
88
+ attachments: [{
79
89
  name: 'a.jpg',
80
90
  source: SOURCE
81
- }
91
+ }]
82
92
  })).toBe(true);
83
93
  });
84
94
  it('drops a message with nothing to show', () => {
95
+ expect(isMessageDrawable({})).toBe(false);
85
96
  expect(isMessageDrawable({
86
- direction: 'incoming',
87
- time: '11:06'
88
- })).toBe(false);
89
- expect(isMessageDrawable({
90
- direction: 'incoming',
91
- attachment: {
97
+ attachments: [{
92
98
  name: 'a.jpg',
93
99
  source: ''
94
- }
100
+ }]
95
101
  })).toBe(false);
96
102
  });
97
103
  });
@@ -1,29 +1,26 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useState } from 'react';
3
- import { Vertical } from '@pushwoosh/kit-helpers';
4
- import { Text } from '@pushwoosh/kit-typography';
5
- import { DocumentBox, DocumentGlyph, MediaBox, MediaDuration, MediaMeta, MediaOverlay, PlayButton, PlayGlyph } from './styles';
6
- import { WHATSAPP_COLOR } from '../../constants';
3
+ import { Color } from '@pushwoosh/kit-constants';
4
+ import { Columns, Vertical } from '@pushwoosh/kit-helpers';
5
+ import { DocumentBox, DocumentGlyph, DocumentThumbnail, MediaBox, MediaDuration, MediaOverlay, PlayButton, PlayGlyph } from './styles';
7
6
  import { formatAttachmentDuration, formatAttachmentSize, getAttachmentExtension, resolveAttachmentKind, toVideoPosterSource } from '../../helpers';
8
7
  import { WhatsAppDocumentIcon, WhatsAppPlayIcon, WhatsAppVideoIcon } from '../../icons';
9
- const DOCUMENT_GLYPH_COLOR = {
10
- pdf: WHATSAPP_COLOR.DOCUMENT_PDF,
11
- doc: WHATSAPP_COLOR.DOCUMENT_TEXT,
12
- docx: WHATSAPP_COLOR.DOCUMENT_TEXT
13
- };
8
+ import { useLang } from '../../polyglot';
9
+ import { PreviewText } from '../../styles';
14
10
  /** Draws an attached file inside a chat bubble: image, video with its play badge, or a document card. */
15
11
  export function WhatsAppAttachment(props) {
16
12
  const {
17
- attachment,
18
- meta,
19
- hasCaption = false
13
+ attachment
20
14
  } = props;
21
15
  const {
22
16
  name,
23
17
  source,
24
18
  size,
25
- duration
19
+ duration,
20
+ thumbnailSource,
21
+ pageCount
26
22
  } = attachment;
23
+ const lang = useLang();
27
24
  const [readDuration, setReadDuration] = useState(null);
28
25
  const kind = resolveAttachmentKind(attachment);
29
26
  const extension = getAttachmentExtension(attachment);
@@ -34,24 +31,32 @@ export function WhatsAppAttachment(props) {
34
31
  setReadDuration(Number.isFinite(length) ? length : null);
35
32
  }, []);
36
33
  if (kind === 'document') {
37
- const meaning = [size === undefined ? '' : formatAttachmentSize(size), extension].filter(Boolean);
34
+ const meaning = [pageCount === undefined ? '' : lang({
35
+ message: 'DUMB.WHATSAPP_PREVIEW.DOCUMENT_PAGES',
36
+ count: pageCount
37
+ }), size === undefined ? '' : formatAttachmentSize(size), extension].filter(Boolean);
38
38
  return _jsxs(DocumentBox, {
39
- "$hasCaption": hasCaption,
40
- children: [_jsx(DocumentGlyph, {
41
- "$color": DOCUMENT_GLYPH_COLOR[extension] ?? WHATSAPP_COLOR.DOCUMENT_GENERIC,
42
- children: _jsx(WhatsAppDocumentIcon, {})
43
- }), _jsxs(Vertical, {
44
- "$gap": 1,
45
- "$minWidth": 0,
46
- children: [_jsx(Text, {
47
- "$color": WHATSAPP_COLOR.BUBBLE_TEXT,
48
- "$ellipsis": true,
49
- "$variant": "standard",
50
- children: name
51
- }), meaning.length > 0 && _jsx(Text, {
52
- "$color": WHATSAPP_COLOR.BUBBLE_META,
53
- "$variant": "footnote",
54
- children: meaning.join(' · ')
39
+ children: [thumbnailSource && _jsx(DocumentThumbnail, {
40
+ alt: name,
41
+ src: thumbnailSource
42
+ }), _jsxs(Columns, {
43
+ "$alignItems": "center",
44
+ "$gap": 10,
45
+ "$padding": "8px 10px",
46
+ "$sizes": "auto minmax(0, 1fr)",
47
+ "$width": "100%",
48
+ children: [_jsx(DocumentGlyph, {
49
+ children: _jsx(WhatsAppDocumentIcon, {})
50
+ }), _jsxs(Vertical, {
51
+ "$gap": 1,
52
+ "$minWidth": 0,
53
+ children: [_jsx(PreviewText, {
54
+ "$ellipsis": true,
55
+ children: name
56
+ }), meaning.length > 0 && _jsx(PreviewText, {
57
+ "$color": Color.LOCKED,
58
+ children: meaning.join(' • ')
59
+ })]
55
60
  })]
56
61
  })]
57
62
  });
@@ -59,8 +64,8 @@ export function WhatsAppAttachment(props) {
59
64
  const length = duration ?? readDuration;
60
65
  const isVideo = kind === 'video';
61
66
  return _jsxs(MediaBox, {
62
- "$hasCaption": hasCaption,
63
- children: [isVideo ? _jsx("video", {
67
+ "$hasOverlay": isVideo,
68
+ children: [isVideo && !thumbnailSource ? _jsx("video", {
64
69
  muted: true,
65
70
  playsInline: true,
66
71
  onLoadedMetadata: handleLoadedMetadata,
@@ -68,17 +73,15 @@ export function WhatsAppAttachment(props) {
68
73
  src: toVideoPosterSource(source)
69
74
  }) : _jsx("img", {
70
75
  alt: name,
71
- src: source
76
+ src: thumbnailSource ?? source
72
77
  }), isVideo && _jsx(PlayButton, {
73
78
  children: _jsx(PlayGlyph, {
74
79
  children: _jsx(WhatsAppPlayIcon, {})
75
80
  })
76
- }), (isVideo || meta) && _jsxs(MediaOverlay, {
77
- children: [isVideo ? _jsxs(MediaDuration, {
81
+ }), isVideo && _jsx(MediaOverlay, {
82
+ children: _jsxs(MediaDuration, {
78
83
  children: [_jsx(WhatsAppVideoIcon, {}), length === null ? null : formatAttachmentDuration(length)]
79
- }) : _jsx("span", {}), _jsx(MediaMeta, {
80
- children: meta
81
- })]
84
+ })
82
85
  })]
83
86
  });
84
87
  }
@@ -12,9 +12,11 @@ export declare const MediaBox: import("styled-components").StyledComponent<"div"
12
12
  } & {
13
13
  $position: string;
14
14
  $bgColor: "#0B141A";
15
+ $borderRadius: number;
16
+ $justifyItems: string;
15
17
  } & {
16
- $hasCaption: boolean;
17
- }, "$gridAutoFlow" | "$bgColor" | "$position">;
18
+ $hasOverlay: boolean;
19
+ }, "$gridAutoFlow" | "$bgColor" | "$borderRadius" | "$position" | "$justifyItems">;
18
20
  export declare const PlayButton: import("styled-components").StyledComponent<"div", any, import("@pushwoosh/kit-helpers/styled-helpers").CommonBoxProps & {
19
21
  $alignContent?: import("@pushwoosh/kit-helpers/styled-helpers").AlignContentValue | undefined;
20
22
  $alignItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
@@ -61,18 +63,16 @@ export declare const MediaOverlay: import("styled-components").StyledComponent<"
61
63
  $justifyItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
62
64
  $placeItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
63
65
  } & {
64
- $sizes: import("@pushwoosh/kit-helpers/styled-helpers").StrNum;
66
+ $gridAutoFlow: string;
65
67
  } & {
66
68
  $alignItems: string;
67
- $gap: number;
68
- $sizes: string;
69
69
  $padding: {
70
70
  top: number;
71
71
  right: number;
72
72
  bottom: number;
73
73
  left: number;
74
74
  };
75
- }, "$padding" | "$alignItems" | "$gap" | "$sizes">;
75
+ }, "$gridAutoFlow" | "$padding" | "$alignItems">;
76
76
  export declare const MediaDuration: import("styled-components").StyledComponent<"span", any, {
77
77
  $color?: string | undefined;
78
78
  $uppercase?: boolean | undefined;
@@ -82,20 +82,6 @@ export declare const MediaDuration: import("styled-components").StyledComponent<
82
82
  $variant: "footnote";
83
83
  $color: "#FFFFFF";
84
84
  }, "$color" | "$variant">;
85
- export declare const MediaMeta: import("styled-components").StyledComponent<"div", any, import("@pushwoosh/kit-helpers/styled-helpers").CommonBoxProps & {
86
- $alignContent?: import("@pushwoosh/kit-helpers/styled-helpers").AlignContentValue | undefined;
87
- $alignItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
88
- $gap?: import("@pushwoosh/kit-helpers/styled-helpers").StrNum | undefined;
89
- $justifyContent?: import("@pushwoosh/kit-helpers/styled-helpers").JustifyContentValue | undefined;
90
- } & {
91
- $gridAutoFlow?: "row" | "column" | "dense" | "row dense" | "column dense" | undefined;
92
- $justifyItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
93
- $placeItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
94
- } & {
95
- $gridAutoFlow: string;
96
- } & {
97
- $justifyContent: string;
98
- }, "$gridAutoFlow" | "$justifyContent">;
99
85
  export declare const DocumentBox: import("styled-components").StyledComponent<"div", any, import("@pushwoosh/kit-helpers/styled-helpers").CommonBoxProps & {
100
86
  $alignContent?: import("@pushwoosh/kit-helpers/styled-helpers").AlignContentValue | undefined;
101
87
  $alignItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
@@ -106,16 +92,13 @@ export declare const DocumentBox: import("styled-components").StyledComponent<"d
106
92
  $justifyItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
107
93
  $placeItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
108
94
  } & {
109
- $sizes: import("@pushwoosh/kit-helpers/styled-helpers").StrNum;
95
+ $gridAutoFlow: string;
110
96
  } & {
111
- $alignItems: string;
112
- $gap: number;
113
- $sizes: string;
114
- $padding: string;
115
97
  $bgColor: "#F5F6F6";
116
- } & {
117
- $hasCaption: boolean;
118
- }, "$bgColor" | "$padding" | "$alignItems" | "$gap" | "$sizes">;
98
+ $borderRadius: number;
99
+ $width: string;
100
+ }, "$gridAutoFlow" | "$bgColor" | "$borderRadius" | "$width">;
101
+ export declare const DocumentThumbnail: import("styled-components").StyledComponent<"img", any, {}, never>;
119
102
  export declare const DocumentGlyph: import("styled-components").StyledComponent<"div", any, import("@pushwoosh/kit-helpers/styled-helpers").CommonBoxProps & {
120
103
  $alignContent?: import("@pushwoosh/kit-helpers/styled-helpers").AlignContentValue | undefined;
121
104
  $alignItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
@@ -127,6 +110,4 @@ export declare const DocumentGlyph: import("styled-components").StyledComponent<
127
110
  $placeItems?: import("@pushwoosh/kit-helpers/styled-helpers").ItemAlignmentValue | undefined;
128
111
  } & {
129
112
  $gridAutoFlow: string;
130
- } & {
131
- $color: string;
132
113
  }, "$gridAutoFlow">;
@@ -1,17 +1,18 @@
1
- import styled, { css } from 'styled-components';
2
- import { Columns, Horizontal, Vertical } from '@pushwoosh/kit-helpers';
1
+ import styled from 'styled-components';
2
+ import { Horizontal, Vertical } from '@pushwoosh/kit-helpers';
3
3
  import { Text } from '@pushwoosh/kit-typography';
4
- import { WHATSAPP_COLOR, WHATSAPP_MEDIA_MAX_HEIGHT } from '../../constants';
5
- const bubbleInset = css(["margin:-3px -5px ", ";border-radius:6px;overflow:hidden;"], ({
6
- $hasCaption
7
- }) => $hasCaption ? '5px' : '-4px');
4
+ import { WHATSAPP_COLOR, WHATSAPP_MEDIA_MAX_HEIGHT, WHATSAPP_MEDIA_MIN_HEIGHT, WHATSAPP_MEDIA_RADIUS } from '../../constants';
8
5
  export const MediaBox = styled(Vertical).attrs({
9
6
  $position: 'relative',
10
- $bgColor: WHATSAPP_COLOR.MEDIA_BACKDROP
7
+ $bgColor: WHATSAPP_COLOR.MEDIA_BACKDROP,
8
+ $borderRadius: WHATSAPP_MEDIA_RADIUS,
9
+ $justifyItems: 'start'
11
10
  }).withConfig({
12
11
  displayName: "MediaBox",
13
12
  componentId: "sc-1uezfps-0"
14
- })(["", " img,video{display:block;width:100%;max-height:", "px;object-fit:cover;}"], bubbleInset, WHATSAPP_MEDIA_MAX_HEIGHT);
13
+ })(["overflow:hidden;width:fit-content;max-width:100%;img,video{display:block;width:auto;max-width:100%;max-height:", "px;", "}"], WHATSAPP_MEDIA_MAX_HEIGHT, ({
14
+ $hasOverlay
15
+ }) => $hasOverlay ? `min-height: ${WHATSAPP_MEDIA_MIN_HEIGHT}px;` : '');
15
16
  export const PlayButton = styled(Horizontal).attrs({
16
17
  $alignItems: 'center',
17
18
  $justifyContent: 'center',
@@ -32,20 +33,18 @@ export const PlayGlyph = styled(Horizontal).attrs({
32
33
  displayName: "PlayGlyph",
33
34
  componentId: "sc-1uezfps-2"
34
35
  })(["color:", ";svg{display:block;margin-left:3px;}"], WHATSAPP_COLOR.PLAY_GLYPH);
35
- export const MediaOverlay = styled(Columns).attrs({
36
+ export const MediaOverlay = styled(Horizontal).attrs({
36
37
  $alignItems: 'end',
37
- $gap: 8,
38
- $sizes: 'auto minmax(0, 1fr)',
39
38
  $padding: {
40
- top: 24,
39
+ top: 12,
41
40
  right: 8,
42
- bottom: 5,
41
+ bottom: 4,
43
42
  left: 8
44
43
  }
45
44
  }).withConfig({
46
45
  displayName: "MediaOverlay",
47
46
  componentId: "sc-1uezfps-3"
48
- })(["position:absolute;right:0;bottom:0;left:0;background:linear-gradient(to top,", ",transparent);pointer-events:none;"], WHATSAPP_COLOR.MEDIA_SCRIM);
47
+ })(["position:absolute;right:0;bottom:0;left:0;max-height:100%;overflow:hidden;background:linear-gradient(to top,", ",transparent);pointer-events:none;"], WHATSAPP_COLOR.MEDIA_SCRIM);
49
48
  export const MediaDuration = styled(Text).attrs({
50
49
  $variant: 'footnote',
51
50
  $color: WHATSAPP_COLOR.MEDIA_META
@@ -53,25 +52,19 @@ export const MediaDuration = styled(Text).attrs({
53
52
  displayName: "MediaDuration",
54
53
  componentId: "sc-1uezfps-4"
55
54
  })(["display:inline-flex;align-items:center;gap:4px;svg{display:block;}"]);
56
- export const MediaMeta = styled(Horizontal).attrs({
57
- $justifyContent: 'end'
58
- }).withConfig({
59
- displayName: "MediaMeta",
60
- componentId: "sc-1uezfps-5"
61
- })(["color:", ";svg{color:", ";}"], WHATSAPP_COLOR.MEDIA_META, WHATSAPP_COLOR.MEDIA_META);
62
- export const DocumentBox = styled(Columns).attrs({
63
- $alignItems: 'center',
64
- $gap: 10,
65
- $sizes: 'auto minmax(0, 1fr)',
66
- $padding: '8px 10px',
67
- $bgColor: WHATSAPP_COLOR.DOCUMENT_CARD
55
+ export const DocumentBox = styled(Vertical).attrs({
56
+ $bgColor: WHATSAPP_COLOR.DOCUMENT_CARD,
57
+ $borderRadius: WHATSAPP_MEDIA_RADIUS,
58
+ $width: '100%'
68
59
  }).withConfig({
69
60
  displayName: "DocumentBox",
61
+ componentId: "sc-1uezfps-5"
62
+ })(["overflow:hidden;"]);
63
+ export const DocumentThumbnail = styled.img.withConfig({
64
+ displayName: "DocumentThumbnail",
70
65
  componentId: "sc-1uezfps-6"
71
- })(["", ""], bubbleInset);
66
+ })(["display:block;width:100%;max-height:", "px;object-fit:cover;"], WHATSAPP_MEDIA_MAX_HEIGHT);
72
67
  export const DocumentGlyph = styled(Horizontal).withConfig({
73
68
  displayName: "DocumentGlyph",
74
69
  componentId: "sc-1uezfps-7"
75
- })(["color:", ";svg{display:block;}"], ({
76
- $color
77
- }) => $color);
70
+ })(["color:", ";svg{display:block;}"], WHATSAPP_COLOR.DOCUMENT_GLYPH);
@@ -1,11 +1,6 @@
1
- import type { ReactNode } from 'react';
2
1
  import type { WhatsAppAttachment } from '../../types';
3
2
  /** Props of {@link WhatsAppAttachment}. */
4
3
  export interface WhatsAppAttachmentProps {
5
4
  /** File to draw. */
6
5
  attachment: WhatsAppAttachment;
7
- /** Time and ticks overlaid on the media; pass it only when the bubble has no caption below. */
8
- meta?: ReactNode;
9
- /** Keep the bottom inset of the bubble instead of hugging its padding. */
10
- hasCaption?: boolean;
11
6
  }
@@ -1,4 +1,4 @@
1
1
  import { type ReactElement } from 'react';
2
2
  import type { WhatsAppMessageBubbleProps } from './types';
3
- /** Single chat bubble: attachment, body, time and — for outgoing messages — the delivery ticks. */
3
+ /** Single chat bubble: attachments on top, message body underneath. */
4
4
  export declare function WhatsAppMessageBubble(props: WhatsAppMessageBubbleProps): ReactElement;