@lovett/ui 0.0.1

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 (102) hide show
  1. package/README.md +28 -0
  2. package/package.json +53 -0
  3. package/src/accordion.tsx +153 -0
  4. package/src/atoms.tsx +197 -0
  5. package/src/badge.tsx +91 -0
  6. package/src/brand-logo-tile.tsx +200 -0
  7. package/src/bulk-action-bar.tsx +104 -0
  8. package/src/button-group.tsx +46 -0
  9. package/src/button.tsx +93 -0
  10. package/src/calculator-shell-v2.tsx +380 -0
  11. package/src/calculator-shell.tsx +310 -0
  12. package/src/card.tsx +369 -0
  13. package/src/checkbox.tsx +114 -0
  14. package/src/chip-nav.tsx +347 -0
  15. package/src/choropleth.tsx +62 -0
  16. package/src/code-block.tsx +235 -0
  17. package/src/completion-ring.tsx +119 -0
  18. package/src/copy-field.tsx +169 -0
  19. package/src/data-grid/column-options-menu.tsx +127 -0
  20. package/src/data-grid/data-grid.tsx +391 -0
  21. package/src/data-grid/drawer-panel.tsx +146 -0
  22. package/src/data-grid/index.ts +29 -0
  23. package/src/data-grid/sortable-parts.tsx +215 -0
  24. package/src/data-grid/table-body.tsx +238 -0
  25. package/src/data-grid/table-elements.tsx +135 -0
  26. package/src/data-grid/table-header.tsx +95 -0
  27. package/src/data-grid/table-overlays.tsx +78 -0
  28. package/src/data-grid/table-parts.tsx +15 -0
  29. package/src/data-grid/table-summary-footer.tsx +101 -0
  30. package/src/data-grid/table-view.tsx +176 -0
  31. package/src/data-grid/types.ts +141 -0
  32. package/src/data-grid/use-grid-columns.ts +311 -0
  33. package/src/data-grid/use-grid-editing.ts +154 -0
  34. package/src/device-frame.tsx +274 -0
  35. package/src/dropdown-button.tsx +221 -0
  36. package/src/dropdown-menu.tsx +450 -0
  37. package/src/empty-state.tsx +85 -0
  38. package/src/file-upload/file-drop-zone.tsx +156 -0
  39. package/src/file-upload/file-preview-grid.tsx +39 -0
  40. package/src/file-upload/file-preview-item.tsx +175 -0
  41. package/src/file-upload/file-thumbnail.tsx +98 -0
  42. package/src/file-upload/file-upload-button.tsx +95 -0
  43. package/src/file-upload/index.ts +13 -0
  44. package/src/file-upload/use-file-upload.ts +371 -0
  45. package/src/filter-bar.tsx +125 -0
  46. package/src/filter-dropdown.tsx +289 -0
  47. package/src/floating-drawer.tsx +420 -0
  48. package/src/folder-card.tsx +188 -0
  49. package/src/folder-tree-picker.tsx +511 -0
  50. package/src/format.ts +117 -0
  51. package/src/frame-stack.tsx +73 -0
  52. package/src/hero-form-card.tsx +471 -0
  53. package/src/index.ts +372 -0
  54. package/src/input.tsx +130 -0
  55. package/src/kbd.tsx +41 -0
  56. package/src/lib/layout.ts +22 -0
  57. package/src/lib/utils.ts +6 -0
  58. package/src/markdown.tsx +214 -0
  59. package/src/menu-button.tsx +142 -0
  60. package/src/meta-previews/CreativeMedia.tsx +119 -0
  61. package/src/meta-previews/InstagramExplorePreview.tsx +340 -0
  62. package/src/meta-previews/InstagramFeedCarousel.tsx +245 -0
  63. package/src/meta-previews/InstagramFeedPreview.tsx +259 -0
  64. package/src/meta-previews/MetaFeedCarousel.tsx +228 -0
  65. package/src/meta-previews/MetaFeedPreview.tsx +294 -0
  66. package/src/meta-previews/MetaInstreamPreview.tsx +135 -0
  67. package/src/meta-previews/MetaMessengerPreview.tsx +795 -0
  68. package/src/meta-previews/MetaReelPreview.tsx +750 -0
  69. package/src/meta-previews/MetaRightColumnPreview.tsx +245 -0
  70. package/src/meta-previews/MetaSearchPreview.tsx +113 -0
  71. package/src/meta-previews/MetaStoryPreview.tsx +1132 -0
  72. package/src/meta-previews/ProfileAvatar.tsx +79 -0
  73. package/src/meta-previews/defaults.ts +27 -0
  74. package/src/meta-previews/index.ts +37 -0
  75. package/src/meta-previews/types.ts +219 -0
  76. package/src/metric-card.tsx +117 -0
  77. package/src/modal.tsx +131 -0
  78. package/src/option-tile.tsx +252 -0
  79. package/src/page-hero.tsx +78 -0
  80. package/src/page-shell.tsx +440 -0
  81. package/src/pagination.tsx +86 -0
  82. package/src/pill-button.tsx +103 -0
  83. package/src/profile-section.tsx +389 -0
  84. package/src/progress-bar.tsx +84 -0
  85. package/src/radio.tsx +172 -0
  86. package/src/range-slider.tsx +161 -0
  87. package/src/resizable.tsx +282 -0
  88. package/src/search-bar.tsx +81 -0
  89. package/src/segmented-pill.tsx +143 -0
  90. package/src/shell.tsx +464 -0
  91. package/src/slider.tsx +107 -0
  92. package/src/sortable-table.tsx +198 -0
  93. package/src/sortable.tsx +137 -0
  94. package/src/stat-row.tsx +132 -0
  95. package/src/stats-grid.tsx +38 -0
  96. package/src/step-loader.tsx +141 -0
  97. package/src/styles.css +562 -0
  98. package/src/tabs.tsx +143 -0
  99. package/src/tag-chip-input.tsx +394 -0
  100. package/src/textarea.tsx +39 -0
  101. package/src/toast.tsx +59 -0
  102. package/src/tokens.css +579 -0
@@ -0,0 +1,795 @@
1
+ import React, { useState } from 'react';
2
+ import { ChevronLeft, MoreHorizontal } from 'lucide-react';
3
+ import type { PreviewAdData } from './types';
4
+ import { ProfileAvatar } from './ProfileAvatar';
5
+ import { CreativeMedia } from './CreativeMedia';
6
+
7
+ interface MetaMessengerPreviewProps {
8
+ adData: PreviewAdData;
9
+ }
10
+
11
+ /**
12
+ * Facebook Messenger Inbox Preview
13
+ * Exact styling extracted from Facebook Creative Hub
14
+ * Reference: creative-spec/references/META_DESIGN_TOKENS.md
15
+ * Source: singleimage-facebook-messenger-inbox.html
16
+ * Container: 250x444px (outer), 375x142px (inner - Ad view)
17
+ */
18
+ export const MetaMessengerPreview: React.FC<MetaMessengerPreviewProps> = ({
19
+ adData,
20
+ }) => {
21
+ const [view, setView] = useState<'ad' | 'expanded'>('ad');
22
+
23
+ // Messenger Inbox exact design tokens - extracted from Creative Hub
24
+ const mi = {
25
+ // Outer container
26
+ outerContainerWidth: 250,
27
+ outerContainerHeight: 444,
28
+ outerContainerBg: 'rgba(0, 0, 0, 0.03)',
29
+ outerContainerRadius: 8,
30
+ outerContainerBorder: 'none',
31
+ outerContainerShadow: 'rgba(0, 0, 0, 0.1) 0px 0px 5px 0px, rgba(0, 0, 0, 0.1) 0px 0px 1px 0px',
32
+ fontFamily: 'Roboto, Arial, sans-serif',
33
+ baseColor: 'rgb(28, 30, 33)',
34
+ baseFontSize: 12,
35
+ baseLineHeight: '15.36px',
36
+
37
+ // Inner container (Ad view)
38
+ innerContainerWidth: 375,
39
+ innerContainerHeight: 142,
40
+ innerContainerBg: 'rgb(255, 255, 255)',
41
+ transformScale: 0.666667,
42
+
43
+ // Toggle buttons
44
+ toggleContainerWidth: 190,
45
+ toggleContainerHeight: 28,
46
+ toggleMarginTop: 12,
47
+ toggleMarginBottom: 16,
48
+ toggleMarginHorizontal: 92.5,
49
+
50
+ // Active button
51
+ activeButtonBg: 'rgb(24, 119, 242)',
52
+ activeButtonColor: 'rgb(255, 255, 255)',
53
+ activeButtonBorder: '1px solid rgb(24, 119, 242)',
54
+
55
+ // Inactive button
56
+ inactiveButtonBg: 'rgb(245, 246, 247)',
57
+ inactiveButtonColor: 'rgb(68, 73, 80)',
58
+ inactiveButtonBorder: '1px solid rgb(218, 221, 225)',
59
+
60
+ // Button common styles
61
+ buttonFontSize: 12,
62
+ buttonFontWeight: 700,
63
+ buttonLineHeight: '26px',
64
+ buttonHeight: 28,
65
+ adViewButtonWidth: 71.0547,
66
+ expandedViewButtonWidth: 113.445,
67
+ buttonRadius: 2,
68
+ buttonPadding: '0px 11px',
69
+
70
+ // Divider
71
+ dividerBg: 'rgba(0, 0, 0, 0.1)',
72
+ dividerHeight: 1,
73
+
74
+ // Content row
75
+ contentRowHeight: 76,
76
+ contentRowPadding: '0px 20px',
77
+ contentRowBg: 'rgb(255, 255, 255)',
78
+
79
+ // Profile image (large)
80
+ profileSize: 60,
81
+ profileRadius: 30,
82
+ profileMarginTop: 8,
83
+
84
+ // Text content
85
+ textContentWidth: 191,
86
+ textContentMargin: '10px 12px 8px',
87
+
88
+ // Brand name row
89
+ brandNameHeight: 20,
90
+ brandNameWidth: 191,
91
+ brandNameMaxWidth: 169,
92
+ brandNameFontSize: 17,
93
+ brandNameFontWeight: 600,
94
+ brandNameLineHeight: '20px',
95
+ brandNameColor: 'rgb(0, 0, 0)',
96
+
97
+ // Ad badge
98
+ adBadgeBg: 'rgb(218, 220, 222)',
99
+ adBadgeHeight: 17,
100
+ adBadgeWidth: 20.1641,
101
+ adBadgeRadius: 4,
102
+ adBadgeMargin: '2px 0px 1px 4px',
103
+ adBadgeTextSize: 10,
104
+ adBadgeTextColor: 'rgb(255, 255, 255)',
105
+ adBadgeTextLineHeight: '16px',
106
+
107
+ // Description text
108
+ descriptionSize: 14,
109
+ descriptionWeight: 400,
110
+ descriptionLineHeight: '18px',
111
+ descriptionColor: 'rgba(0, 0, 0, 0.5)',
112
+ descriptionMaxHeight: 18,
113
+
114
+ // View more link
115
+ viewMoreColor: 'rgb(31, 135, 255)',
116
+ viewMoreSize: 14,
117
+ viewMoreLineHeight: '18px',
118
+
119
+ // Thumbnail image (right side)
120
+ thumbnailSize: 60,
121
+ thumbnailRadius: 12,
122
+ thumbnailMargin: '8px 0px',
123
+ thumbnailShadow: 'rgba(0, 0, 0, 0.2) 0px 0px 0px 0.666667px',
124
+ };
125
+
126
+ // Truncate text helper
127
+ const truncateText = (text: string, limit: number) => {
128
+ if (!text || text.length <= limit) return text;
129
+ return text.substring(0, limit);
130
+ };
131
+
132
+ return (
133
+ <div
134
+ className="meta-preview"
135
+ style={{
136
+ display: 'flex',
137
+ alignItems: 'center',
138
+ justifyContent: 'center',
139
+ width: '100%',
140
+ height: '100%',
141
+ fontFamily: mi.fontFamily,
142
+ fontSize: `${mi.baseFontSize}px`,
143
+ color: mi.baseColor,
144
+ lineHeight: mi.baseLineHeight,
145
+ }}
146
+ >
147
+ <div
148
+ style={{
149
+ display: 'flex',
150
+ flexDirection: 'column',
151
+ alignItems: 'center',
152
+ justifyContent: view === 'expanded' ? 'flex-start' : 'center',
153
+ width: `${mi.outerContainerWidth}px`, maxWidth: '100%',
154
+ height: view === 'expanded' ? '540px' : `${mi.outerContainerHeight}px`,
155
+ backgroundColor: mi.outerContainerBg,
156
+ borderRadius: `${mi.outerContainerRadius}px`,
157
+ boxShadow: mi.outerContainerShadow,
158
+ overflow: 'hidden',
159
+ }}
160
+ >
161
+ {/* Inner container with transform scale */}
162
+ <div
163
+ style={{
164
+ width: `${mi.innerContainerWidth}px`,
165
+ height: view === 'expanded' ? 'auto' : `${mi.innerContainerHeight}px`,
166
+ transform: `matrix(${mi.transformScale}, 0, 0, ${mi.transformScale}, 0, 0)`,
167
+ transformOrigin: view === 'expanded' ? 'top center' : 'center center',
168
+ }}
169
+ >
170
+ <div
171
+ style={{
172
+ display: 'flex',
173
+ flexDirection: 'row',
174
+ width: `${mi.innerContainerWidth}px`,
175
+ height: `${mi.innerContainerHeight}px`,
176
+ backgroundColor: mi.innerContainerBg,
177
+ }}
178
+ >
179
+ <div
180
+ data-ad-preview="previewContainer"
181
+ style={{
182
+ width: `${mi.innerContainerWidth}px`,
183
+ height: `${mi.innerContainerHeight}px`,
184
+ }}
185
+ >
186
+ <div
187
+ style={{
188
+ width: `${mi.innerContainerWidth}px`,
189
+ height: '122px',
190
+ }}
191
+ >
192
+ <div
193
+ style={{
194
+ margin: `${mi.toggleMarginTop}px 0px 8px`,
195
+ width: `${mi.innerContainerWidth}px`,
196
+ }}
197
+ >
198
+ {/* Toggle Buttons */}
199
+ <div
200
+ style={{
201
+ display: 'block',
202
+ alignItems: 'center',
203
+ width: `${mi.toggleContainerWidth}px`,
204
+ height: `${mi.toggleContainerHeight}px`,
205
+ margin: `0px ${mi.toggleMarginHorizontal}px ${mi.toggleMarginBottom}px`,
206
+ }}
207
+ >
208
+ <div style={{ transform: 'matrix(1, 0, 0, 1, 0, 0)' }}>
209
+ {/* Ad View Button */}
210
+ <button
211
+ type="button"
212
+ onClick={() => setView('ad')}
213
+ style={{
214
+ display: 'inline-block',
215
+ position: 'relative',
216
+ width: `${mi.adViewButtonWidth}px`,
217
+ height: `${mi.buttonHeight}px`,
218
+ maxWidth: '242px',
219
+ padding: mi.buttonPadding,
220
+ backgroundColor: view === 'ad' ? mi.activeButtonBg : mi.inactiveButtonBg,
221
+ color: view === 'ad' ? mi.activeButtonColor : mi.inactiveButtonColor,
222
+ fontFamily: '-apple-system, system-ui, "system-ui", Arial, sans-serif',
223
+ fontSize: `${mi.buttonFontSize}px`,
224
+ fontWeight: mi.buttonFontWeight,
225
+ lineHeight: mi.buttonLineHeight,
226
+ textAlign: 'center',
227
+ border: view === 'ad' ? mi.activeButtonBorder : mi.inactiveButtonBorder,
228
+ borderRadius: `${mi.buttonRadius}px 0px 0px ${mi.buttonRadius}px`,
229
+ cursor: 'pointer',
230
+ }}
231
+ >
232
+ <div
233
+ style={{
234
+ display: 'flex',
235
+ alignItems: 'center',
236
+ justifyContent: 'center',
237
+ height: '26px',
238
+ }}
239
+ >
240
+ <div
241
+ style={{
242
+ textOverflow: 'ellipsis',
243
+ overflow: 'hidden',
244
+ }}
245
+ >
246
+ Ad view
247
+ </div>
248
+ </div>
249
+ </button>
250
+
251
+ {/* Expanded View Button */}
252
+ <button
253
+ type="button"
254
+ onClick={() => setView('expanded')}
255
+ style={{
256
+ display: 'inline-block',
257
+ position: 'relative',
258
+ width: `${mi.expandedViewButtonWidth}px`,
259
+ height: `${mi.buttonHeight}px`,
260
+ maxWidth: '242px',
261
+ padding: mi.buttonPadding,
262
+ backgroundColor: view === 'expanded' ? mi.activeButtonBg : mi.inactiveButtonBg,
263
+ color: view === 'expanded' ? mi.activeButtonColor : mi.inactiveButtonColor,
264
+ fontFamily: '-apple-system, system-ui, "system-ui", Arial, sans-serif',
265
+ fontSize: `${mi.buttonFontSize}px`,
266
+ fontWeight: mi.buttonFontWeight,
267
+ lineHeight: mi.buttonLineHeight,
268
+ textAlign: 'center',
269
+ borderRadius: `0px ${mi.buttonRadius}px ${mi.buttonRadius}px 0px`,
270
+ borderWidth: '1px 1px 1px 0px',
271
+ borderStyle: 'solid',
272
+ borderColor: view === 'expanded' ? 'rgb(24, 119, 242)' : 'rgb(218, 221, 225)',
273
+ cursor: 'pointer',
274
+ }}
275
+ >
276
+ <div
277
+ style={{
278
+ display: 'flex',
279
+ alignItems: 'center',
280
+ justifyContent: 'center',
281
+ height: '26px',
282
+ }}
283
+ >
284
+ <div
285
+ style={{
286
+ textOverflow: 'ellipsis',
287
+ overflow: 'hidden',
288
+ }}
289
+ >
290
+ Expanded view
291
+ </div>
292
+ </div>
293
+ </button>
294
+ </div>
295
+ </div>
296
+
297
+ {view === 'ad' ? (
298
+ // Ad View
299
+ <div>
300
+ {/* Top divider */}
301
+ <hr
302
+ style={{
303
+ width: `${mi.innerContainerWidth}px`,
304
+ height: `${mi.dividerHeight}px`,
305
+ backgroundColor: mi.dividerBg,
306
+ border: '0px inset',
307
+ margin: 0,
308
+ }}
309
+ />
310
+
311
+ {/* Main content row */}
312
+ <div
313
+ style={{
314
+ display: 'flex',
315
+ flexDirection: 'row',
316
+ width: '335px',
317
+ height: `${mi.contentRowHeight}px`,
318
+ padding: mi.contentRowPadding,
319
+ backgroundColor: mi.contentRowBg,
320
+ overflow: 'hidden',
321
+ }}
322
+ >
323
+ {/* Profile Image */}
324
+ <div style={{ width: `${mi.profileSize}px`, height: `${mi.contentRowHeight}px` }}>
325
+ <ProfileAvatar
326
+ src={adData.profileImage}
327
+ name={adData.brandName}
328
+ fontSize={18}
329
+ background={mi.adBadgeBg}
330
+ style={{
331
+ width: `${mi.profileSize}px`,
332
+ height: `${mi.profileSize}px`,
333
+ marginTop: `${mi.profileMarginTop}px`,
334
+ borderRadius: `${mi.profileRadius}px`,
335
+ }}
336
+ />
337
+ </div>
338
+
339
+ {/* Text Content */}
340
+ <div
341
+ style={{
342
+ width: `${mi.textContentWidth}px`,
343
+ height: '58px',
344
+ margin: mi.textContentMargin,
345
+ overflow: 'hidden',
346
+ }}
347
+ >
348
+ {/* Brand Name and Ad Badge */}
349
+ <div
350
+ style={{
351
+ display: 'flex',
352
+ flexDirection: 'row',
353
+ height: `${mi.brandNameHeight}px`,
354
+ maxWidth: `${mi.textContentWidth}px`,
355
+ }}
356
+ >
357
+ <h2
358
+ style={{
359
+ width: `${mi.brandNameMaxWidth}px`,
360
+ maxWidth: `${mi.brandNameMaxWidth}px`,
361
+ height: '19px',
362
+ padding: '1px 0px 0px',
363
+ fontSize: `${mi.brandNameFontSize}px`,
364
+ fontWeight: mi.brandNameFontWeight,
365
+ lineHeight: mi.brandNameLineHeight,
366
+ color: mi.brandNameColor,
367
+ overflow: 'hidden',
368
+ textOverflow: 'ellipsis',
369
+ whiteSpace: 'nowrap',
370
+ margin: 0,
371
+ }}
372
+ >
373
+ {truncateText(adData.brandName, 25)}
374
+ </h2>
375
+ <div
376
+ style={{
377
+ width: `${mi.adBadgeWidth}px`,
378
+ height: `${mi.adBadgeHeight}px`,
379
+ margin: mi.adBadgeMargin,
380
+ backgroundColor: mi.adBadgeBg,
381
+ borderRadius: `${mi.adBadgeRadius}px`,
382
+ }}
383
+ >
384
+ <div
385
+ style={{
386
+ width: '12.1641px',
387
+ height: '16px',
388
+ margin: '1px 4px 0px',
389
+ fontSize: `${mi.adBadgeTextSize}px`,
390
+ fontWeight: 400,
391
+ lineHeight: mi.adBadgeTextLineHeight,
392
+ color: mi.adBadgeTextColor,
393
+ textAlign: 'center',
394
+ }}
395
+ >
396
+ Ad
397
+ </div>
398
+ </div>
399
+ </div>
400
+
401
+ {/* Description */}
402
+ <p
403
+ style={{
404
+ width: `${mi.textContentWidth}px`,
405
+ maxWidth: `${mi.textContentWidth}px`,
406
+ height: '18px',
407
+ maxHeight: `${mi.descriptionMaxHeight}px`,
408
+ padding: '1px 0px 0px',
409
+ fontSize: `${mi.descriptionSize}px`,
410
+ fontWeight: mi.descriptionWeight,
411
+ lineHeight: mi.descriptionLineHeight,
412
+ color: mi.descriptionColor,
413
+ overflow: 'hidden',
414
+ textOverflow: 'ellipsis',
415
+ whiteSpace: 'nowrap',
416
+ margin: 0,
417
+ }}
418
+ >
419
+ {truncateText(adData.description || adData.primaryText || '', 60)}
420
+ </p>
421
+
422
+ {/* View more link */}
423
+ <div
424
+ style={{
425
+ width: `${mi.textContentWidth}px`,
426
+ height: '18px',
427
+ fontSize: `${mi.viewMoreSize}px`,
428
+ fontWeight: 400,
429
+ lineHeight: mi.viewMoreLineHeight,
430
+ color: mi.viewMoreColor,
431
+ }}
432
+ >
433
+ View more
434
+ </div>
435
+ </div>
436
+
437
+ {/* Thumbnail Image */}
438
+ <div
439
+ style={{
440
+ display: 'flex',
441
+ position: 'relative',
442
+ width: `${mi.thumbnailSize}px`,
443
+ height: `${mi.thumbnailSize}px`,
444
+ margin: mi.thumbnailMargin,
445
+ }}
446
+ >
447
+ {adData.creativeImage ? (
448
+ <CreativeMedia
449
+ src={adData.creativeImage}
450
+ mediaType={adData.creativeMediaType}
451
+ alt="Ad creative"
452
+ style={{
453
+ position: 'relative',
454
+ zIndex: 1,
455
+ width: `${mi.thumbnailSize}px`,
456
+ height: `${mi.thumbnailSize}px`,
457
+ objectFit: 'cover',
458
+ borderRadius: `${mi.thumbnailRadius}px`,
459
+ boxShadow: mi.thumbnailShadow,
460
+ display: 'block',
461
+ }}
462
+ />
463
+ ) : (
464
+ <div
465
+ style={{
466
+ width: `${mi.thumbnailSize}px`,
467
+ height: `${mi.thumbnailSize}px`,
468
+ backgroundColor: mi.adBadgeBg,
469
+ borderRadius: `${mi.thumbnailRadius}px`,
470
+ }}
471
+ />
472
+ )}
473
+ </div>
474
+ </div>
475
+
476
+ {/* Bottom divider */}
477
+ <hr
478
+ style={{
479
+ width: `${mi.innerContainerWidth}px`,
480
+ height: `${mi.dividerHeight}px`,
481
+ backgroundColor: mi.dividerBg,
482
+ border: '0px inset',
483
+ margin: 0,
484
+ }}
485
+ />
486
+ </div>
487
+ ) : (
488
+ // Expanded View (simplified - would need more reference HTML)
489
+ <div>
490
+ {/* Top divider */}
491
+ <hr
492
+ style={{
493
+ width: `${mi.innerContainerWidth}px`,
494
+ height: `${mi.dividerHeight}px`,
495
+ backgroundColor: mi.dividerBg,
496
+ border: '0px inset',
497
+ margin: 0,
498
+ }}
499
+ />
500
+
501
+ <div
502
+ style={{
503
+ display: 'flex',
504
+ flexDirection: 'column',
505
+ maxHeight: '720px',
506
+ paddingTop: '12px',
507
+ paddingBottom: '10px',
508
+ }}
509
+ >
510
+ {/* Header with back button, profile, and menu */}
511
+ <div
512
+ style={{
513
+ display: 'flex',
514
+ flexDirection: 'column',
515
+ width: `${mi.innerContainerWidth}px`,
516
+ }}
517
+ >
518
+ <div
519
+ style={{
520
+ display: 'flex',
521
+ height: '72px',
522
+ marginLeft: '20px',
523
+ marginRight: '8px',
524
+ marginTop: '16px',
525
+ width: `${mi.innerContainerWidth}px`,
526
+ }}
527
+ >
528
+ <ChevronLeft
529
+ style={{
530
+ height: '24px',
531
+ width: '24px',
532
+ color: mi.baseColor,
533
+ }}
534
+ />
535
+ <ProfileAvatar
536
+ src={adData.profileImage}
537
+ name={adData.brandName}
538
+ fontSize={18}
539
+ background={mi.adBadgeBg}
540
+ style={{
541
+ height: '60px',
542
+ width: '60px',
543
+ marginLeft: '114px',
544
+ marginRight: '114px',
545
+ marginTop: '-8px',
546
+ marginBottom: '12px',
547
+ borderRadius: '30px',
548
+ }}
549
+ />
550
+ <MoreHorizontal
551
+ style={{
552
+ height: '24px',
553
+ width: '24px',
554
+ color: mi.baseColor,
555
+ }}
556
+ />
557
+ </div>
558
+
559
+ {/* Brand Name and Ad Badge */}
560
+ <div
561
+ style={{
562
+ display: 'flex',
563
+ height: '20px',
564
+ maxWidth: '344px',
565
+ marginLeft: '92px',
566
+ marginRight: '92px',
567
+ justifyContent: 'center',
568
+ }}
569
+ >
570
+ <div
571
+ style={{
572
+ fontSize: '18px',
573
+ fontWeight: 700,
574
+ height: '20px',
575
+ lineHeight: '20px',
576
+ overflow: 'hidden',
577
+ textAlign: 'center',
578
+ textOverflow: 'ellipsis',
579
+ }}
580
+ >
581
+ {truncateText(adData.brandName, 25)}
582
+ </div>
583
+ <div
584
+ style={{
585
+ height: '16px',
586
+ width: '24px',
587
+ marginLeft: '6px',
588
+ marginTop: '2px',
589
+ marginBottom: '4px',
590
+ borderRadius: '4px',
591
+ backgroundColor: mi.adBadgeBg,
592
+ }}
593
+ >
594
+ <div
595
+ style={{
596
+ color: 'rgb(255, 255, 255)',
597
+ fontSize: '10px',
598
+ height: '18px',
599
+ marginLeft: '4px',
600
+ marginRight: '4px',
601
+ marginTop: '2px',
602
+ textAlign: 'center',
603
+ width: '16px',
604
+ }}
605
+ >
606
+ Ad
607
+ </div>
608
+ </div>
609
+ </div>
610
+
611
+ {/* Like count */}
612
+ <div
613
+ style={{
614
+ color: mi.descriptionColor,
615
+ fontSize: '16px',
616
+ height: '20px',
617
+ lineHeight: '20px',
618
+ marginLeft: '66px',
619
+ marginRight: '66px',
620
+ marginTop: '2px',
621
+ maxWidth: '344px',
622
+ overflow: 'hidden',
623
+ textAlign: 'center',
624
+ }}
625
+ >
626
+ 615 people like {adData.brandName}
627
+ </div>
628
+ </div>
629
+
630
+ {/* Primary Text */}
631
+ <div
632
+ style={{
633
+ fontSize: '18px',
634
+ lineHeight: '22px',
635
+ marginLeft: '16px',
636
+ marginRight: '16px',
637
+ marginTop: '8px',
638
+ maxHeight: '66px',
639
+ overflow: 'hidden',
640
+ WebkitLineClamp: 3,
641
+ }}
642
+ >
643
+ {adData.primaryText}
644
+ </div>
645
+
646
+ {/* Image and Card */}
647
+ <div
648
+ style={{
649
+ display: 'flex',
650
+ marginLeft: '16px',
651
+ marginRight: '16px',
652
+ marginTop: '12px',
653
+ width: '344px',
654
+ }}
655
+ >
656
+ <div style={{ width: '344px' }}>
657
+ {/* Creative Image */}
658
+ {adData.creativeImage ? (
659
+ <CreativeMedia
660
+ src={adData.creativeImage}
661
+ mediaType={adData.creativeMediaType}
662
+ alt="Ad creative"
663
+ style={{
664
+ borderTopLeftRadius: '18px',
665
+ borderTopRightRadius: '18px',
666
+ height: '344px',
667
+ width: '344px',
668
+ objectFit: 'cover',
669
+ }}
670
+ />
671
+ ) : (
672
+ <div
673
+ style={{
674
+ borderTopLeftRadius: '18px',
675
+ borderTopRightRadius: '18px',
676
+ height: '344px',
677
+ width: '344px',
678
+ backgroundColor: mi.adBadgeBg,
679
+ }}
680
+ />
681
+ )}
682
+
683
+ {/* Card with CTA */}
684
+ <div
685
+ style={{
686
+ backgroundColor: 'rgba(0, 0, 0, 0.05)',
687
+ borderBottomLeftRadius: '18px',
688
+ borderBottomRightRadius: '18px',
689
+ display: 'flex',
690
+ flexDirection: 'column',
691
+ marginTop: '-4px',
692
+ width: '344px',
693
+ }}
694
+ >
695
+ <div style={{ width: '344px' }}>
696
+ {/* Headline */}
697
+ <div
698
+ style={{
699
+ fontSize: '18px',
700
+ fontWeight: 700,
701
+ lineHeight: '22px',
702
+ marginLeft: '16px',
703
+ marginRight: '16px',
704
+ marginTop: '12px',
705
+ maxHeight: '22px',
706
+ overflow: 'hidden',
707
+ WebkitLineClamp: 1,
708
+ }}
709
+ >
710
+ {truncateText(adData.headline || '', 30)}
711
+ </div>
712
+
713
+ {/* Description */}
714
+ <div
715
+ style={{
716
+ color: mi.descriptionColor,
717
+ fontSize: '16px',
718
+ lineHeight: '20px',
719
+ marginLeft: '16px',
720
+ marginRight: '16px',
721
+ marginTop: '4px',
722
+ maxHeight: '20px',
723
+ overflow: 'hidden',
724
+ WebkitLineClamp: 1,
725
+ }}
726
+ >
727
+ {truncateText(adData.description || '', 40)}
728
+ </div>
729
+
730
+ {/* Display Link */}
731
+ <div
732
+ style={{
733
+ color: mi.descriptionColor,
734
+ fontSize: '16px',
735
+ lineHeight: '20px',
736
+ marginLeft: '16px',
737
+ marginRight: '16px',
738
+ maxHeight: '20px',
739
+ overflow: 'hidden',
740
+ textOverflow: 'ellipsis',
741
+ WebkitLineClamp: 1,
742
+ }}
743
+ >
744
+ {adData.displayLink}
745
+ </div>
746
+ </div>
747
+
748
+ {/* CTA Button */}
749
+ <div
750
+ style={{
751
+ backgroundColor: 'rgb(10, 124, 255)',
752
+ borderRadius: '12px',
753
+ margin: '12px',
754
+ padding: '8px',
755
+ textAlign: 'center',
756
+ }}
757
+ >
758
+ <div
759
+ style={{
760
+ color: 'rgb(255, 255, 255)',
761
+ height: '20px',
762
+ lineHeight: '20px',
763
+ }}
764
+ >
765
+ {adData.callToAction}
766
+ </div>
767
+ </div>
768
+ </div>
769
+ </div>
770
+ </div>
771
+ </div>
772
+
773
+ {/* Bottom divider */}
774
+ <hr
775
+ style={{
776
+ width: `${mi.innerContainerWidth}px`,
777
+ height: `${mi.dividerHeight}px`,
778
+ backgroundColor: mi.dividerBg,
779
+ border: '0px inset',
780
+ margin: 0,
781
+ }}
782
+ />
783
+ </div>
784
+ )}
785
+ </div>
786
+ </div>
787
+ </div>
788
+ </div>
789
+ </div>
790
+ </div>
791
+ </div>
792
+ );
793
+ };
794
+
795
+ MetaMessengerPreview.displayName = 'MetaMessengerPreview';