|
1 | | -import { Link } from '@tanstack/react-router' |
2 | | -import { ParentSize } from '@visx/responsive' |
3 | 1 | import React from 'react' |
4 | 2 | import { twMerge } from 'tailwind-merge' |
5 | | -import { useResizeObserver } from '~/hooks/useResizeObserver' |
6 | | -import { libraries } from '~/libraries' |
| 3 | +import { Link } from '@tanstack/react-router' |
7 | 4 |
|
8 | 5 | declare global { |
9 | 6 | interface Window { |
@@ -71,51 +68,96 @@ const gamDivs = { |
71 | 68 | incontent_footer: 'incontent_footer', |
72 | 69 | mrec_1: 'mrec_1', |
73 | 70 | mrec_2: 'mrec_2', |
| 71 | + vrec_1: 'vrec_1', |
| 72 | + header: 'header', |
74 | 73 | } as const |
75 | 74 |
|
76 | 75 | function GamAd({ |
77 | 76 | name, |
78 | 77 | children, |
79 | 78 | adClassName, |
| 79 | + className, |
| 80 | + placeholderClassName, |
| 81 | + popupPosition = 'bottom', |
| 82 | + borderClassName, |
| 83 | + style, |
80 | 84 | ...props |
81 | 85 | }: { name: keyof typeof gamDivs } & React.HTMLAttributes<HTMLDivElement> & { |
82 | 86 | adClassName?: string |
| 87 | + placeholderClassName?: string |
| 88 | + popupPosition?: 'top' | 'bottom' |
| 89 | + borderClassName?: string |
83 | 90 | }) { |
84 | 91 | const gamId = gamDivs[name] |
85 | 92 |
|
86 | | - const ref = React.useRef<HTMLDivElement>(null!) |
87 | | - const [size, setSize] = React.useState({ |
88 | | - width: 0, |
89 | | - height: 0, |
90 | | - }) |
| 93 | + const popupClasses = |
| 94 | + popupPosition === 'top' |
| 95 | + ? 'absolute bottom-full right-0 opacity-0 group-hover:opacity-100 transition-all duration-300 z-10' |
| 96 | + : 'absolute top-full right-0 opacity-0 group-hover:opacity-100 transition-all duration-300 z-10' |
91 | 97 |
|
92 | | - useResizeObserver({ |
93 | | - ref, |
94 | | - selector: (el) => el?.querySelector('iframe'), |
95 | | - onResize: (rect) => { |
96 | | - if (rect.width === 0 || rect.height === 0) return |
97 | | - setSize({ |
98 | | - width: rect.width, |
99 | | - height: rect.height, |
100 | | - }) |
101 | | - }, |
102 | | - }) |
| 98 | + borderClassName = twMerge('rounded-xl overflow-hidden', borderClassName) |
103 | 99 |
|
104 | 100 | return ( |
105 | | - <div style={size}> |
106 | | - <div {...props}> |
107 | | - <div data-fuse={gamId} className={adClassName} ref={ref} /> |
| 101 | + <div {...props} className={twMerge('relative group', className)}> |
| 102 | + <div |
| 103 | + className={twMerge( |
| 104 | + 'absolute inset-0 bg-white/50 dark:bg-black/20 shadow-xl shadow-black/2', |
| 105 | + borderClassName, |
| 106 | + placeholderClassName |
| 107 | + )} |
| 108 | + > |
| 109 | + <div className="flex justify-center items-center h-full opacity-50 gap-[1px]"> |
| 110 | + <span className="inline-block w-1 h-1 rounded-full bg-gray-500 animate-bounce [animation-delay:0ms]" /> |
| 111 | + <span className="inline-block w-1 h-1 rounded-full bg-gray-500 animate-bounce [animation-delay:100ms]" /> |
| 112 | + <span className="inline-block w-1 h-1 rounded-full bg-gray-500 animate-bounce [animation-delay:200ms]" /> |
| 113 | + </div> |
| 114 | + <div |
| 115 | + className={twMerge( |
| 116 | + 'absolute -top-px -left-px -right-px -bottom-px border-[2px] border-gray-200 dark:border-gray-900', |
| 117 | + borderClassName |
| 118 | + )} |
| 119 | + /> |
| 120 | + </div> |
| 121 | + <div className="relative overflow-hidden"> |
| 122 | + <div className={twMerge('overflow-hidden', borderClassName)}> |
| 123 | + <div data-fuse={gamId} className={adClassName} /> |
| 124 | + </div> |
| 125 | + <div |
| 126 | + className={twMerge( |
| 127 | + 'absolute -top-px -left-px -right-px -bottom-px border-[2px] border-gray-200 dark:border-gray-900', |
| 128 | + borderClassName |
| 129 | + )} |
| 130 | + /> |
| 131 | + </div> |
| 132 | + <div className={twMerge('flex gap-1', popupClasses)}> |
| 133 | + <Link |
| 134 | + to="/ads" |
| 135 | + className="text-xs text-gray-500 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 px-2 py-1 bg-white/90 dark:bg-gray-700 rounded-lg shadow-lg whitespace-nowrap" |
| 136 | + > |
| 137 | + Learn about TanStack Ads |
| 138 | + </Link> |
| 139 | + <Link |
| 140 | + to="/ads" |
| 141 | + hash="hide-ads" |
| 142 | + className="text-xs text-gray-500 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 px-2 py-1 bg-white/90 dark:bg-gray-700 rounded-lg shadow-lg whitespace-nowrap" |
| 143 | + > |
| 144 | + Hide Ads |
| 145 | + </Link> |
108 | 146 | </div> |
109 | 147 | </div> |
110 | 148 | ) |
111 | 149 | } |
112 | 150 |
|
113 | | -export function GamLeader() { |
114 | | - return null |
115 | | -} |
116 | | - |
117 | | -export function GamFooter() { |
118 | | - return <GamAd name="incontent_footer" style={{ maxWidth: '728px' }} /> |
| 151 | +export function GamFooter( |
| 152 | + props: Omit<React.ComponentProps<typeof GamAd>, 'name'> |
| 153 | +) { |
| 154 | + return ( |
| 155 | + <GamAd |
| 156 | + {...props} |
| 157 | + name="incontent_footer" |
| 158 | + style={{ maxWidth: '728px', ...props.style }} |
| 159 | + /> |
| 160 | + ) |
119 | 161 | } |
120 | 162 |
|
121 | 163 | export function GamRightRailSquare() { |
@@ -166,3 +208,27 @@ export function GamMrec1() { |
166 | 208 | export function GamMrec2() { |
167 | 209 | return <GamAd name="mrec_2" /> |
168 | 210 | } |
| 211 | + |
| 212 | +export function GamVrec1( |
| 213 | + props: Omit<React.ComponentProps<typeof GamAd>, 'name'> |
| 214 | +) { |
| 215 | + return <GamAd {...props} name="vrec_1" /> |
| 216 | +} |
| 217 | + |
| 218 | +export function GamHeader( |
| 219 | + props: React.HTMLAttributes<HTMLDivElement> & { |
| 220 | + adClassName?: string |
| 221 | + } |
| 222 | +) { |
| 223 | + return ( |
| 224 | + <GamAd |
| 225 | + name="header" |
| 226 | + {...props} |
| 227 | + className={twMerge( |
| 228 | + 'w-full max-w-[728px] flex mx-auto justify-center', |
| 229 | + props.className |
| 230 | + )} |
| 231 | + adClassName={twMerge('h-[90px]', props.adClassName)} |
| 232 | + /> |
| 233 | + ) |
| 234 | +} |
0 commit comments