@automattic/social-previews 2.0.1 → 2.1.0-beta.2

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 (109) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +3 -1
  3. package/dist/cjs/helpers.js +8 -1
  4. package/dist/cjs/helpers.js.map +1 -1
  5. package/dist/cjs/index.js +1 -0
  6. package/dist/cjs/index.js.map +1 -1
  7. package/dist/cjs/threads-preview/card.js +16 -0
  8. package/dist/cjs/threads-preview/card.js.map +1 -0
  9. package/dist/cjs/threads-preview/footer.js +9 -0
  10. package/dist/cjs/threads-preview/footer.js.map +1 -0
  11. package/dist/cjs/threads-preview/header.js +12 -0
  12. package/dist/cjs/threads-preview/header.js.map +1 -0
  13. package/dist/cjs/threads-preview/helpers.js +8 -0
  14. package/dist/cjs/threads-preview/helpers.js.map +1 -0
  15. package/dist/cjs/threads-preview/icons/default-avatar.js +9 -0
  16. package/dist/cjs/threads-preview/icons/default-avatar.js.map +1 -0
  17. package/dist/cjs/threads-preview/index.js +7 -0
  18. package/dist/cjs/threads-preview/index.js.map +1 -0
  19. package/dist/cjs/threads-preview/link-preview.js +12 -0
  20. package/dist/cjs/threads-preview/link-preview.js.map +1 -0
  21. package/dist/cjs/threads-preview/media.js +43 -0
  22. package/dist/cjs/threads-preview/media.js.map +1 -0
  23. package/dist/cjs/threads-preview/post-preview.js +20 -0
  24. package/dist/cjs/threads-preview/post-preview.js.map +1 -0
  25. package/dist/cjs/threads-preview/previews.js +25 -0
  26. package/dist/cjs/threads-preview/previews.js.map +1 -0
  27. package/dist/cjs/threads-preview/sidebar.js +11 -0
  28. package/dist/cjs/threads-preview/sidebar.js.map +1 -0
  29. package/dist/cjs/threads-preview/style.scss +203 -0
  30. package/dist/cjs/threads-preview/types.js +3 -0
  31. package/dist/cjs/threads-preview/types.js.map +1 -0
  32. package/dist/cjs/threads-preview/variables.scss +5 -0
  33. package/dist/esm/helpers.js +7 -0
  34. package/dist/esm/helpers.js.map +1 -1
  35. package/dist/esm/index.js +1 -0
  36. package/dist/esm/index.js.map +1 -1
  37. package/dist/esm/threads-preview/card.js +11 -0
  38. package/dist/esm/threads-preview/card.js.map +1 -0
  39. package/dist/esm/threads-preview/footer.js +5 -0
  40. package/dist/esm/threads-preview/footer.js.map +1 -0
  41. package/dist/esm/threads-preview/header.js +8 -0
  42. package/dist/esm/threads-preview/header.js.map +1 -0
  43. package/dist/esm/threads-preview/helpers.js +4 -0
  44. package/dist/esm/threads-preview/helpers.js.map +1 -0
  45. package/dist/esm/threads-preview/icons/default-avatar.js +5 -0
  46. package/dist/esm/threads-preview/icons/default-avatar.js.map +1 -0
  47. package/dist/esm/threads-preview/index.js +4 -0
  48. package/dist/esm/threads-preview/index.js.map +1 -0
  49. package/dist/esm/threads-preview/link-preview.js +8 -0
  50. package/dist/esm/threads-preview/link-preview.js.map +1 -0
  51. package/dist/esm/threads-preview/media.js +38 -0
  52. package/dist/esm/threads-preview/media.js.map +1 -0
  53. package/dist/esm/threads-preview/post-preview.js +16 -0
  54. package/dist/esm/threads-preview/post-preview.js.map +1 -0
  55. package/dist/esm/threads-preview/previews.js +20 -0
  56. package/dist/esm/threads-preview/previews.js.map +1 -0
  57. package/dist/esm/threads-preview/sidebar.js +7 -0
  58. package/dist/esm/threads-preview/sidebar.js.map +1 -0
  59. package/dist/esm/threads-preview/style.scss +203 -0
  60. package/dist/esm/threads-preview/types.js +2 -0
  61. package/dist/esm/threads-preview/types.js.map +1 -0
  62. package/dist/esm/threads-preview/variables.scss +5 -0
  63. package/dist/tsconfig-cjs.tsbuildinfo +1 -1
  64. package/dist/tsconfig.tsbuildinfo +1 -1
  65. package/dist/types/helpers.d.ts +2 -1
  66. package/dist/types/helpers.d.ts.map +1 -1
  67. package/dist/types/index.d.ts +1 -0
  68. package/dist/types/index.d.ts.map +1 -1
  69. package/dist/types/threads-preview/card.d.ts +4 -0
  70. package/dist/types/threads-preview/card.d.ts.map +1 -0
  71. package/dist/types/threads-preview/footer.d.ts +3 -0
  72. package/dist/types/threads-preview/footer.d.ts.map +1 -0
  73. package/dist/types/threads-preview/header.d.ts +4 -0
  74. package/dist/types/threads-preview/header.d.ts.map +1 -0
  75. package/dist/types/threads-preview/helpers.d.ts +3 -0
  76. package/dist/types/threads-preview/helpers.d.ts.map +1 -0
  77. package/dist/types/threads-preview/icons/default-avatar.d.ts +3 -0
  78. package/dist/types/threads-preview/icons/default-avatar.d.ts.map +1 -0
  79. package/dist/types/threads-preview/index.d.ts +4 -0
  80. package/dist/types/threads-preview/index.d.ts.map +1 -0
  81. package/dist/types/threads-preview/link-preview.d.ts +4 -0
  82. package/dist/types/threads-preview/link-preview.d.ts.map +1 -0
  83. package/dist/types/threads-preview/media.d.ts +4 -0
  84. package/dist/types/threads-preview/media.d.ts.map +1 -0
  85. package/dist/types/threads-preview/post-preview.d.ts +5 -0
  86. package/dist/types/threads-preview/post-preview.d.ts.map +1 -0
  87. package/dist/types/threads-preview/previews.d.ts +4 -0
  88. package/dist/types/threads-preview/previews.d.ts.map +1 -0
  89. package/dist/types/threads-preview/sidebar.d.ts +4 -0
  90. package/dist/types/threads-preview/sidebar.d.ts.map +1 -0
  91. package/dist/types/threads-preview/types.d.ts +22 -0
  92. package/dist/types/threads-preview/types.d.ts.map +1 -0
  93. package/package.json +72 -71
  94. package/src/helpers.tsx +16 -1
  95. package/src/index.ts +1 -0
  96. package/src/threads-preview/card.tsx +22 -0
  97. package/src/threads-preview/footer.tsx +43 -0
  98. package/src/threads-preview/header.tsx +18 -0
  99. package/src/threads-preview/helpers.ts +9 -0
  100. package/src/threads-preview/icons/default-avatar.tsx +35 -0
  101. package/src/threads-preview/index.tsx +3 -0
  102. package/src/threads-preview/link-preview.tsx +13 -0
  103. package/src/threads-preview/media.tsx +61 -0
  104. package/src/threads-preview/post-preview.tsx +58 -0
  105. package/src/threads-preview/previews.tsx +77 -0
  106. package/src/threads-preview/sidebar.tsx +18 -0
  107. package/src/threads-preview/style.scss +203 -0
  108. package/src/threads-preview/types.ts +30 -0
  109. package/src/threads-preview/variables.scss +5 -0
@@ -0,0 +1,58 @@
1
+ import { preparePreviewText } from '../helpers';
2
+ import { Card } from './card';
3
+ import { Footer } from './footer';
4
+ import { Header } from './header';
5
+ import { Media } from './media';
6
+ import { Sidebar } from './sidebar';
7
+ import { ThreadsPreviewProps } from './types';
8
+
9
+ import './style.scss';
10
+
11
+ export const ThreadsPostPreview: React.FC< ThreadsPreviewProps > = ( {
12
+ date,
13
+ description,
14
+ image,
15
+ media,
16
+ name,
17
+ profileImage,
18
+ showThreadConnector,
19
+ text,
20
+ title,
21
+ url,
22
+ } ) => {
23
+ const hasMedia = !! media?.length;
24
+
25
+ const displayAsCard = url && image && ! hasMedia;
26
+
27
+ // Attach the URL to the text if not displaying as a card and it's not already in the text.
28
+ const textToDisplay =
29
+ ! displayAsCard && text && url && ! text.includes( url ) ? `${ text } ${ url }` : text;
30
+
31
+ return (
32
+ <div className="threads-preview__wrapper">
33
+ <div className="threads-preview__container">
34
+ <Sidebar profileImage={ profileImage } showThreadConnector={ showThreadConnector } />
35
+ <div className="threads-preview__main">
36
+ <Header name={ name } date={ date } />
37
+ <div className="threads-preview__content">
38
+ { textToDisplay ? (
39
+ <div className="threads-preview__text">
40
+ { preparePreviewText( textToDisplay, { platform: 'threads' } ) }
41
+ </div>
42
+ ) : null }
43
+ { hasMedia ? <Media media={ media } /> : null }
44
+ { displayAsCard ? (
45
+ <Card
46
+ description={ description || '' }
47
+ image={ image }
48
+ title={ title || '' }
49
+ url={ url }
50
+ />
51
+ ) : null }
52
+ </div>
53
+ <Footer />
54
+ </div>
55
+ </div>
56
+ </div>
57
+ );
58
+ };
@@ -0,0 +1,77 @@
1
+ import { ExternalLink } from '@wordpress/components';
2
+ import { __ } from '@wordpress/i18n';
3
+ import SectionHeading from '../shared/section-heading';
4
+ import { ThreadsLinkPreview } from './link-preview';
5
+ import { ThreadsPostPreview } from './post-preview';
6
+ import type { ThreadsPreviewsProps } from './types';
7
+
8
+ export const ThreadsPreviews: React.FC< ThreadsPreviewsProps > = ( {
9
+ headingLevel,
10
+ hideLinkPreview,
11
+ hidePostPreview,
12
+ posts,
13
+ } ) => {
14
+ if ( ! posts?.length ) {
15
+ return null;
16
+ }
17
+
18
+ return (
19
+ <div className="social-preview threads-preview">
20
+ { ! hidePostPreview && (
21
+ <section className="social-preview__section threads-preview__section">
22
+ <SectionHeading level={ headingLevel }>
23
+ {
24
+ // translators: refers to a social post on Threads
25
+ __( 'Your post', 'social-previews' )
26
+ }
27
+ </SectionHeading>
28
+ <p className="social-preview__section-desc">
29
+ { __( 'This is what your social post will look like on Threads:', 'social-previews' ) }
30
+ </p>
31
+ { posts.map( ( post, index ) => {
32
+ const isLast = index + 1 === posts.length;
33
+ return (
34
+ <ThreadsPostPreview
35
+ key={ `threads-preview__post-${ index }` }
36
+ { ...post }
37
+ showThreadConnector={ ! isLast }
38
+ />
39
+ );
40
+ } ) }
41
+ </section>
42
+ ) }
43
+ { ! hideLinkPreview ? (
44
+ <section className="social-preview__section threads-preview__section">
45
+ <SectionHeading level={ headingLevel }>
46
+ {
47
+ // translators: refers to a link to a Threads post
48
+ __( 'Link preview', 'social-previews' )
49
+ }
50
+ </SectionHeading>
51
+ { posts[ 0 ].image ? (
52
+ <>
53
+ <p className="social-preview__section-desc">
54
+ { __(
55
+ 'This is what it will look like when someone shares the link to your WordPress post on Threads.',
56
+ 'social-previews'
57
+ ) }
58
+ &nbsp;
59
+ <ExternalLink href="https://jetpack.com/support/jetpack-social-image-generator">
60
+ { __( 'Learn more about links', 'social-previews' ) }
61
+ </ExternalLink>
62
+ </p>
63
+ <ThreadsLinkPreview { ...posts[ 0 ] } name="" profileImage="" />
64
+ </>
65
+ ) : (
66
+ <p className="social-preview__section-desc">
67
+ { __(
68
+ 'Threads link preview requires an image to be set for the post. Please add an image to see the preview.',
69
+ 'social-previews'
70
+ ) }
71
+ </p>
72
+ ) }
73
+ </section>
74
+ ) : null }
75
+ </div>
76
+ );
77
+ };
@@ -0,0 +1,18 @@
1
+ import { __ } from '@wordpress/i18n';
2
+ import { DefaultAvatar } from './icons/default-avatar';
3
+ import { SidebarProps } from './types';
4
+
5
+ export const Sidebar: React.FC< SidebarProps > = ( { profileImage, showThreadConnector } ) => {
6
+ return (
7
+ <div className="threads-preview__sidebar">
8
+ <div className="threads-preview__profile-image">
9
+ { profileImage ? (
10
+ <img alt={ __( 'Threads profile image', 'social-previews' ) } src={ profileImage } />
11
+ ) : (
12
+ <DefaultAvatar />
13
+ ) }
14
+ </div>
15
+ { showThreadConnector && <div className="threads-preview__connector" /> }
16
+ </div>
17
+ );
18
+ };
@@ -0,0 +1,203 @@
1
+ /* stylelint-disable scales/radii */
2
+ /* stylelint-disable declaration-property-unit-allowed-list */
3
+ @import "./variables.scss";
4
+
5
+ .threads-preview {
6
+ padding: 20px;
7
+ }
8
+
9
+ .threads-preview__wrapper {
10
+ background-color: #fff;
11
+ max-width: clamp(200px, 100%, 635px);
12
+ margin-inline: auto;
13
+ padding-top: 1rem;
14
+ border-radius: 4px;
15
+ padding-inline-end: 1rem;
16
+ }
17
+
18
+ .threads-preview__section.social-preview__section {
19
+ width: clamp(200px, 100%, 635px);
20
+
21
+ // To compensate for the padding for profile picture in threads threads
22
+ .social-preview__section-heading,
23
+ .social-preview__section-desc {
24
+ padding-inline-start: 17px;
25
+ }
26
+ }
27
+
28
+ .threads-preview__container {
29
+ display: grid;
30
+ grid-template-columns: 50px auto;
31
+ margin-bottom: 5px;
32
+ font-size: $threads-font-size;
33
+ line-height: $threads-line-height;
34
+ color: $threads-text-primary-color;
35
+
36
+ .threads-preview__sidebar {
37
+ display: grid;
38
+ grid-template-rows: 35px auto;
39
+ justify-items: center;
40
+
41
+ .threads-preview__profile-image {
42
+ display: flex;
43
+ align-items: center;
44
+ max-width: 36px;
45
+ max-height: 36px;
46
+ border-radius: 50%;
47
+ overflow: hidden;
48
+
49
+ img {
50
+ object-fit: cover;
51
+ width: 100%;
52
+ }
53
+ }
54
+
55
+ .threads-preview__connector {
56
+ width: 2px;
57
+ background-color: #8c8f94;
58
+ }
59
+ }
60
+
61
+ .threads-preview__main {
62
+ padding-bottom: 1rem;
63
+ overflow: hidden;
64
+ }
65
+
66
+ .threads-preview__header {
67
+ display: flex;
68
+ gap: 6px;
69
+ font-size: 16px;
70
+ line-height: 18px;
71
+ margin-bottom: 2px;
72
+ }
73
+
74
+ .threads-preview__name {
75
+ font-weight: 600;
76
+ font-size: 15px;
77
+ }
78
+
79
+ .threads-preview__date {
80
+ color: $threads-text-secondary-color;
81
+ }
82
+
83
+ .threads-preview__content {
84
+
85
+ .threads-preview__text {
86
+ white-space: pre-wrap;
87
+ word-break: break-word;
88
+ }
89
+
90
+ .threads-preview__media {
91
+ border-radius: 15px;
92
+ overflow: hidden;
93
+ display: grid;
94
+ grid-gap: 2px;
95
+ grid-template-areas: "a";
96
+ height: 300px;
97
+ margin-top: 12px;
98
+
99
+ img,
100
+ video {
101
+ width: 100%;
102
+ height: 100%;
103
+ object-fit: cover;
104
+
105
+ &:nth-child(1) {
106
+ grid-area: a;
107
+ }
108
+
109
+ &:nth-child(2) {
110
+ grid-area: b;
111
+ }
112
+
113
+ &:nth-child(3) {
114
+ grid-area: c;
115
+ }
116
+
117
+ &:nth-child(4) {
118
+ grid-area: d;
119
+ }
120
+ }
121
+
122
+ &.threads-preview__media-children-2 {
123
+ grid-template-areas: "a b";
124
+ }
125
+
126
+ &.threads-preview__media-children-3 {
127
+ grid-template-areas:
128
+ "a b"
129
+ "a c";
130
+ }
131
+
132
+ &.threads-preview__media-children-4 {
133
+ grid-template-areas:
134
+ "a b"
135
+ "c d";
136
+ }
137
+ }
138
+
139
+ .threads-preview__card {
140
+ margin-top: 12px;
141
+ margin-bottom: 12px;
142
+ overflow: hidden;
143
+ border: 1px solid #e1e8ed;
144
+ border-radius: 8px;
145
+
146
+ .threads-preview__card-image {
147
+ width: 100%;
148
+ height: 100%;
149
+ object-fit: cover;
150
+ aspect-ratio: 16/9;
151
+ }
152
+
153
+ .threads-preview__card-body {
154
+ padding: 0.75em;
155
+ text-decoration: none;
156
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
157
+ color: var(--studio-black);
158
+ text-align: left;
159
+ overflow: hidden;
160
+ display: flex;
161
+ flex-direction: column;
162
+ gap: 2px;
163
+ }
164
+
165
+ .threads-preview__card-title {
166
+ text-overflow: ellipsis;
167
+ }
168
+
169
+ .threads-preview__card-url {
170
+ font-size: 12px;
171
+ text-transform: lowercase;
172
+ color: $threads-text-secondary-color;
173
+ white-space: nowrap;
174
+ overflow-inline: hidden;
175
+ text-overflow: ellipsis;
176
+ }
177
+ }
178
+ }
179
+
180
+ .threads-preview__footer {
181
+ display: flex;
182
+ gap: 2.5rem;
183
+ margin-top: 1rem;
184
+
185
+ svg {
186
+ height: 19px;
187
+ width: 19px;
188
+ fill: $threads-actions-icon-color;
189
+ }
190
+ }
191
+
192
+ .threads-preview__icon {
193
+
194
+ &--like,
195
+ &--reply,
196
+ &--share {
197
+ svg {
198
+ fill: transparent;
199
+ stroke: $threads-actions-icon-color;
200
+ }
201
+ }
202
+ }
203
+ }
@@ -0,0 +1,30 @@
1
+ import { MediaItem, SocialPreviewBaseProps, SocialPreviewsBaseProps } from '../types';
2
+
3
+ export type ThreadsPreviewsProps = SocialPreviewsBaseProps & {
4
+ posts: Array< ThreadsPreviewProps >;
5
+ };
6
+
7
+ export type ThreadsCardProps = SocialPreviewBaseProps;
8
+
9
+ export type SidebarProps = {
10
+ showThreadConnector?: boolean;
11
+ profileImage?: string;
12
+ };
13
+
14
+ export type HeaderProps = {
15
+ name?: string;
16
+ date?: Date;
17
+ };
18
+
19
+ export type MediaProps = {
20
+ media: Array< MediaItem >;
21
+ };
22
+
23
+ export type TextProps = {
24
+ text: string;
25
+ url: string;
26
+ };
27
+
28
+ export type ThreadsPreviewProps = SidebarProps &
29
+ HeaderProps &
30
+ Partial< ThreadsCardProps & Pick< TextProps, 'text' > >;
@@ -0,0 +1,5 @@
1
+ $threads-font-size: 15px !default;
2
+ $threads-line-height: 21px !default;
3
+ $threads-text-primary-color: rgb(0, 0, 0) !default;
4
+ $threads-text-secondary-color: rgb(153, 153, 153) !default;
5
+ $threads-actions-icon-color: rgb(66, 66, 66) !default;