@flamingo-stack/openframe-frontend-core 0.0.287 → 0.0.288

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.
@@ -0,0 +1,619 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
+
3
+
4
+
5
+ var _chunkOXC72UIPcjs = require('./chunk-OXC72UIP.cjs');
6
+
7
+
8
+
9
+
10
+
11
+
12
+ var _chunkD6RK5YXXcjs = require('./chunk-D6RK5YXX.cjs');
13
+
14
+
15
+ var _chunkKBKZYJRIcjs = require('./chunk-KBKZYJRI.cjs');
16
+
17
+
18
+ var _chunkXL4V2PYGcjs = require('./chunk-XL4V2PYG.cjs');
19
+
20
+
21
+ var _chunkXXI7BNB6cjs = require('./chunk-XXI7BNB6.cjs');
22
+
23
+
24
+
25
+
26
+ var _chunkZS2SBWBRcjs = require('./chunk-ZS2SBWBR.cjs');
27
+
28
+ // src/components/embeds/embed-iframe.tsx
29
+ var _react = require('react');
30
+ var _jsxruntime = require('react/jsx-runtime');
31
+ function EmbedLoadingSkeleton({ height }) {
32
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
33
+ "div",
34
+ {
35
+ className: "w-full rounded-lg border border-ods-border overflow-hidden bg-ods-skeleton animate-pulse",
36
+ style: { height: height || "calc(100vh - 250px)" },
37
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center justify-center h-full gap-4", children: [
38
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-12 h-12 rounded-lg bg-ods-card" }),
39
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-4 w-48 rounded bg-ods-card" }),
40
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-3 w-32 rounded bg-ods-card" })
41
+ ] })
42
+ }
43
+ );
44
+ }
45
+ function EmbedIframe({
46
+ src,
47
+ title,
48
+ className,
49
+ height,
50
+ allow,
51
+ referrerPolicy,
52
+ loading,
53
+ allowFullScreen
54
+ }) {
55
+ const [isLoaded, setIsLoaded] = _react.useState.call(void 0, false);
56
+ const iframeRef = _react.useRef.call(void 0, null);
57
+ const handleLoad = _react.useCallback.call(void 0, () => setIsLoaded(true), []);
58
+ _react.useEffect.call(void 0, () => {
59
+ setIsLoaded(false);
60
+ }, [src]);
61
+ _react.useEffect.call(void 0, () => {
62
+ const iframe = iframeRef.current;
63
+ return () => {
64
+ if (iframe) {
65
+ try {
66
+ iframe.src = "about:blank";
67
+ } catch (e2) {
68
+ }
69
+ }
70
+ };
71
+ }, [src]);
72
+ const resolvedHeight = height || "calc(100vh - 250px)";
73
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
74
+ !isLoaded && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmbedLoadingSkeleton, { height: resolvedHeight }),
75
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
76
+ "div",
77
+ {
78
+ className: `w-full rounded-lg border border-ods-border overflow-hidden ${!isLoaded ? "h-0 overflow-hidden" : ""} ${className || ""}`,
79
+ style: isLoaded ? { height: resolvedHeight } : void 0,
80
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
81
+ "iframe",
82
+ {
83
+ ref: iframeRef,
84
+ src,
85
+ className: "w-full h-full border-0",
86
+ title,
87
+ onLoad: handleLoad,
88
+ allow,
89
+ referrerPolicy,
90
+ loading,
91
+ allowFullScreen: _optionalChain([allow, 'optionalAccess', _ => _.includes, 'call', _2 => _2("fullscreen")]) ? void 0 : allowFullScreen
92
+ },
93
+ src
94
+ )
95
+ }
96
+ )
97
+ ] });
98
+ }
99
+
100
+ // src/components/embeds/pdf-viewer.tsx
101
+ var _lucidereact = require('lucide-react');
102
+
103
+ function PdfViewer({ src, fileName, onPreview, onDownload, height }) {
104
+ const displayName = fileName || "PDF Document";
105
+ if (!src) {
106
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [
107
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZS2SBWBRcjs.AdobePdfIcon, { className: "w-16 h-16 text-ods-text-secondary mb-4" }),
108
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-text-secondary", children: "PDF file not available" })
109
+ ] });
110
+ }
111
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-4", children: [
112
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
113
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 min-w-0", children: [
114
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZS2SBWBRcjs.AdobePdfIcon, { className: "w-5 h-5 shrink-0" }),
115
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "text-xl font-semibold text-ods-text-primary truncate", children: displayName })
116
+ ] }),
117
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 w-full sm:w-auto", children: [
118
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
119
+ _chunkXXI7BNB6cjs.Button,
120
+ {
121
+ variant: "outline",
122
+ size: "small-legacy",
123
+ href: onPreview ? void 0 : src,
124
+ openInNewTab: !onPreview,
125
+ onClick: onPreview,
126
+ leftIcon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Eye, { className: "w-4 h-4" }),
127
+ className: "flex-1 sm:flex-initial",
128
+ children: "Preview"
129
+ }
130
+ ),
131
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
132
+ _chunkXXI7BNB6cjs.Button,
133
+ {
134
+ variant: "outline",
135
+ size: "small-legacy",
136
+ href: onDownload ? void 0 : src,
137
+ openInNewTab: !onDownload,
138
+ onClick: onDownload,
139
+ leftIcon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Download, { className: "w-4 h-4" }),
140
+ className: "flex-1 sm:flex-initial",
141
+ children: "Download"
142
+ }
143
+ )
144
+ ] })
145
+ ] }),
146
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmbedIframe, { src, title: displayName, height })
147
+ ] });
148
+ }
149
+
150
+ // src/components/embeds/google-sheets-viewer.tsx
151
+
152
+
153
+ function GoogleSheetsViewer({ externalUrl, fileName, height }) {
154
+ const displayName = fileName || "Google Sheet";
155
+ if (!externalUrl) {
156
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [
157
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZS2SBWBRcjs.GoogleSheetsIcon, { className: "w-16 h-16 text-ods-text-secondary mb-4" }),
158
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-text-secondary", children: "Google Sheet URL not configured" })
159
+ ] });
160
+ }
161
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-4", children: [
162
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
163
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 min-w-0", children: [
164
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZS2SBWBRcjs.GoogleSheetsIcon, { className: "w-5 h-5 shrink-0" }),
165
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "text-xl font-semibold text-ods-text-primary truncate", children: displayName })
166
+ ] }),
167
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
168
+ _chunkXXI7BNB6cjs.Button,
169
+ {
170
+ variant: "outline",
171
+ size: "small-legacy",
172
+ href: _chunkD6RK5YXXcjs.toGoogleSheetsOriginalUrl.call(void 0, externalUrl),
173
+ openInNewTab: true,
174
+ leftIcon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZS2SBWBRcjs.GoogleSheetsIcon, { className: "w-4 h-4" }),
175
+ rightIcon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ExternalLink, { className: "w-4 h-4" }),
176
+ className: "w-full sm:w-auto",
177
+ children: "Open in Google Sheets"
178
+ }
179
+ )
180
+ ] }),
181
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
182
+ EmbedIframe,
183
+ {
184
+ src: _chunkD6RK5YXXcjs.toGoogleSheetsEmbedUrl.call(void 0, externalUrl),
185
+ title: displayName,
186
+ height
187
+ }
188
+ )
189
+ ] });
190
+ }
191
+
192
+ // src/components/embeds/figma-embed.tsx
193
+
194
+
195
+
196
+ function SlidesViewToggle({
197
+ view,
198
+ onChange
199
+ }) {
200
+ const options = [
201
+ { key: "present", label: "Present", Icon: _lucidereact.Play },
202
+ { key: "browse", label: "Browse", Icon: _lucidereact.LayoutGrid }
203
+ ];
204
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
205
+ _chunkOXC72UIPcjs.ToggleGroup,
206
+ {
207
+ type: "single",
208
+ value: view,
209
+ onValueChange: (v) => {
210
+ if (v && v !== view) onChange(v);
211
+ },
212
+ "aria-label": "Figma slides view mode",
213
+ className: "flex shrink-0 items-center gap-0.5 rounded-lg border border-ods-border bg-ods-card p-0.5",
214
+ children: options.map(({ key, label, Icon }) => {
215
+ const active = view === key;
216
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
217
+ _chunkOXC72UIPcjs.ToggleGroupItem,
218
+ {
219
+ value: key,
220
+ "aria-label": label,
221
+ className: `flex items-center gap-1.5 rounded-md px-2.5 py-1 text-sm font-medium transition-colors ${active ? "bg-ods-accent text-ods-text-on-accent" : "text-ods-text-secondary hover:text-ods-text-primary hover:bg-ods-bg-hover"}`,
222
+ children: [
223
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Icon, { className: "h-4 w-4 shrink-0" }),
224
+ label
225
+ ]
226
+ },
227
+ key
228
+ );
229
+ })
230
+ }
231
+ );
232
+ }
233
+ function FigmaEmbed({ url, title, height, loading = "lazy" }) {
234
+ const [view, setView] = _react.useState.call(void 0, "present");
235
+ const isSlides = url ? _chunkD6RK5YXXcjs.isFigmaSlidesUrl.call(void 0, url) : false;
236
+ const embedSrc = url ? _chunkD6RK5YXXcjs.toFigmaEmbedUrl.call(void 0, url, { slidesView: view }) : null;
237
+ const originalUrl = (() => {
238
+ if (!url) return null;
239
+ try {
240
+ const parsed = new URL(_chunkD6RK5YXXcjs.toFigmaOriginalUrl.call(void 0, url));
241
+ const host = parsed.hostname.toLowerCase();
242
+ const okHost = host === "figma.com" || host.endsWith(".figma.com");
243
+ const okProtocol = parsed.protocol === "https:" || parsed.protocol === "http:";
244
+ return okHost && okProtocol ? parsed.toString() : null;
245
+ } catch (e3) {
246
+ return null;
247
+ }
248
+ })();
249
+ const heading = title || "Figma Design";
250
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "my-6 space-y-3", children: [
251
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
252
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 min-w-0", children: [
253
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZS2SBWBRcjs.FigmaIcon, { className: "w-5 h-5 shrink-0" }),
254
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-sans text-base font-semibold text-ods-text-primary truncate", children: heading })
255
+ ] }),
256
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center", children: [
257
+ isSlides && embedSrc && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SlidesViewToggle, { view, onChange: setView }),
258
+ originalUrl && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
259
+ _chunkXXI7BNB6cjs.Button,
260
+ {
261
+ variant: "outline",
262
+ size: "small-legacy",
263
+ href: originalUrl,
264
+ openInNewTab: true,
265
+ leftIcon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZS2SBWBRcjs.FigmaIcon, { className: "w-4 h-4" }),
266
+ rightIcon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ExternalLink, { className: "w-4 h-4" }),
267
+ className: "w-full sm:w-auto",
268
+ children: "Open in Figma"
269
+ }
270
+ )
271
+ ] })
272
+ ] }),
273
+ embedSrc ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
274
+ EmbedIframe,
275
+ {
276
+ src: embedSrc,
277
+ title: heading,
278
+ allow: "clipboard-write; clipboard-read; fullscreen",
279
+ loading,
280
+ height,
281
+ allowFullScreen: true
282
+ }
283
+ ) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [
284
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZS2SBWBRcjs.FigmaIcon, { className: "w-16 h-16 text-ods-text-secondary mb-4" }),
285
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-text-secondary", children: "Figma URL not configured" })
286
+ ] })
287
+ ] });
288
+ }
289
+
290
+ // src/components/embeds/og-link-preview.tsx
291
+
292
+
293
+ var OGLinkErrorBoundary = class extends _react.Component {
294
+ constructor(props) {
295
+ super(props);
296
+ this.state = { hasError: false };
297
+ }
298
+ static getDerivedStateFromError() {
299
+ return { hasError: true };
300
+ }
301
+ componentDidCatch(error, errorInfo) {
302
+ console.warn("Link preview error caught by boundary:", error, errorInfo);
303
+ }
304
+ render() {
305
+ if (this.state.hasError) return this.props.fallback;
306
+ return this.props.children;
307
+ }
308
+ };
309
+ function getDomain(urlStr) {
310
+ try {
311
+ return new URL(urlStr).hostname.replace("www.", "");
312
+ } catch (e4) {
313
+ return "External Link";
314
+ }
315
+ }
316
+ function domainToTitle(domain) {
317
+ return domain.split(".")[0].replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
318
+ }
319
+ var ExternalLinkIcon = ({ size = 16 }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "svg", { width: size, height: size, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", className: "text-ods-text-secondary group-hover:text-ods-accent transition-colors flex-shrink-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" }) });
320
+ var Favicon = ({ src, size = "w-6 h-6" }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src, alt: "", className: size, onError: (e) => {
321
+ e.target.style.display = "none";
322
+ } });
323
+ var OGLinkPreview = ({
324
+ url,
325
+ apiBaseUrl,
326
+ ogEndpointPath = "/api/blog/og-scraper",
327
+ buildPlaceholderUrl,
328
+ fallbackTitle,
329
+ fallbackDescription,
330
+ fallbackImage,
331
+ publicationName,
332
+ publicationLogo,
333
+ variant = "default",
334
+ enablePlaceholder = true
335
+ }) => {
336
+ const [ogData, setOgData] = _react.useState.call(void 0, null);
337
+ const [loading, setLoading] = _react.useState.call(void 0, true);
338
+ const [error, setError] = _react.useState.call(void 0, false);
339
+ const [imageError, setImageError] = _react.useState.call(void 0, false);
340
+ const [originalImageError, setOriginalImageError] = _react.useState.call(void 0, false);
341
+ const [fallbackImageError, setFallbackImageError] = _react.useState.call(void 0, false);
342
+ let isValidUrl = true;
343
+ let isLocalhost = false;
344
+ try {
345
+ if (url && typeof url === "string") {
346
+ const urlObj = new URL(url);
347
+ if (["localhost", "127.0.0.1", "0.0.0.0"].includes(urlObj.hostname) || urlObj.hostname.startsWith("192.168.") || urlObj.hostname.startsWith("10.") || urlObj.hostname.startsWith("172.")) {
348
+ isLocalhost = true;
349
+ }
350
+ } else {
351
+ isValidUrl = false;
352
+ }
353
+ } catch (e5) {
354
+ isValidUrl = false;
355
+ }
356
+ _react.useEffect.call(void 0, () => {
357
+ if (!isValidUrl || isLocalhost) return;
358
+ const fetchOGData = async () => {
359
+ try {
360
+ new URL(url);
361
+ setLoading(true);
362
+ const endpoint = `${_nullishCoalesce(apiBaseUrl, () => ( ""))}${ogEndpointPath}?url=${encodeURIComponent(url)}`;
363
+ const response = await fetch(endpoint);
364
+ if (response.ok) {
365
+ const data = await response.json();
366
+ if (_optionalChain([data, 'optionalAccess', _3 => _3.title]) && data.title !== "Link Preview Unavailable") {
367
+ setOgData(data);
368
+ } else {
369
+ setError(true);
370
+ }
371
+ } else {
372
+ setError(true);
373
+ }
374
+ } catch (e6) {
375
+ setError(true);
376
+ } finally {
377
+ setLoading(false);
378
+ }
379
+ };
380
+ fetchOGData();
381
+ }, [url, isValidUrl, isLocalhost, apiBaseUrl, ogEndpointPath]);
382
+ const isCompact = variant === "compact";
383
+ const domain = getDomain(url);
384
+ const effectiveData = _nullishCoalesce(ogData, () => ( (error ? {
385
+ title: fallbackTitle || domainToTitle(domain),
386
+ description: fallbackDescription || domain,
387
+ image: "",
388
+ url,
389
+ siteName: publicationName || domain,
390
+ type: "website",
391
+ favicon: `https://www.google.com/s2/favicons?domain=${domain}&sz=32`
392
+ } : null)));
393
+ const placeholderImageUrl = enablePlaceholder && buildPlaceholderUrl && _optionalChain([effectiveData, 'optionalAccess', _4 => _4.title]) ? buildPlaceholderUrl(effectiveData.title, effectiveData.siteName || domain) : null;
394
+ const resolvedImageUrl = _optionalChain([effectiveData, 'optionalAccess', _5 => _5.image]) && !imageError ? effectiveData.image : _optionalChain([effectiveData, 'optionalAccess', _6 => _6.originalImage]) && !originalImageError ? effectiveData.originalImage : fallbackImage && !fallbackImageError ? fallbackImage : placeholderImageUrl;
395
+ const hasImage = !!resolvedImageUrl;
396
+ const isFallbackImage = resolvedImageUrl === fallbackImage;
397
+ const isPlaceholder = resolvedImageUrl === placeholderImageUrl && !isFallbackImage;
398
+ const bgColor = _chunkKBKZYJRIcjs.useImageEdgeColor.call(void 0, _nullishCoalesce(resolvedImageUrl, () => ( null)), "var(--ods-bg-secondary)");
399
+ const renderSkeleton = () => isCompact ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-4", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-row border border-ods-border rounded-lg overflow-hidden bg-ods-card h-[120px]", children: [
400
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-[200px] h-full flex-shrink-0 bg-ods-skeleton animate-pulse" }),
401
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 p-3 flex flex-col justify-center", children: [
402
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-skeleton rounded animate-pulse h-4 w-3/4 mb-2" }),
403
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-skeleton rounded animate-pulse h-3 w-full mb-1" }),
404
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-skeleton rounded animate-pulse h-3 w-2/3 mb-2" }),
405
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-skeleton rounded animate-pulse h-3 w-1/3" })
406
+ ] })
407
+ ] }) }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-6", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "block border border-ods-border rounded-lg overflow-hidden bg-ods-card", children: [
408
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "aspect-video w-full bg-ods-skeleton overflow-hidden relative animate-pulse" }),
409
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "p-4", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-start gap-3", children: [
410
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-6 h-6 bg-ods-skeleton rounded flex-shrink-0 mt-0.5 animate-pulse" }),
411
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [
412
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "h-[2.5rem] leading-[1.25rem] mb-2 overflow-hidden", children: [
413
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-skeleton rounded animate-pulse", style: { height: "1.25rem", marginBottom: "0.25rem" } }),
414
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-skeleton rounded animate-pulse w-3/4", style: { height: "1.25rem" } })
415
+ ] }),
416
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "h-[2.5rem] leading-[1.25rem] mb-2 overflow-hidden", children: [
417
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-skeleton rounded animate-pulse", style: { height: "1.25rem", marginBottom: "0.25rem" } }),
418
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-skeleton rounded animate-pulse w-5/6", style: { height: "1.25rem" } })
419
+ ] }),
420
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [
421
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-skeleton rounded animate-pulse", style: { height: "0.75rem", width: "6rem" } }),
422
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-ods-skeleton rounded animate-pulse", style: { height: "0.75rem", width: "5rem" } })
423
+ ] })
424
+ ] })
425
+ ] }) })
426
+ ] }) });
427
+ if (!url || typeof url !== "string" || !isValidUrl) return renderSkeleton();
428
+ if (isLocalhost) {
429
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-6", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
430
+ "a",
431
+ {
432
+ href: url,
433
+ target: "_blank",
434
+ rel: "noopener noreferrer",
435
+ className: "inline-flex items-center gap-2 text-ods-accent hover:text-ods-accent-hover transition-colors",
436
+ children: [
437
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "underline", children: url }),
438
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ExternalLinkIcon, { size: 14 })
439
+ ]
440
+ }
441
+ ) });
442
+ }
443
+ if (loading) return renderSkeleton();
444
+ if (!effectiveData) return renderSkeleton();
445
+ const title = fallbackTitle || effectiveData.title;
446
+ const description = fallbackDescription || effectiveData.description || "";
447
+ const ogDomain = getDomain(effectiveData.url);
448
+ const faviconSrc = effectiveData.favicon || `https://www.google.com/s2/favicons?domain=${ogDomain}&sz=32`;
449
+ const logoSrc = publicationLogo || faviconSrc;
450
+ const handleImageError = () => {
451
+ if (effectiveData.image && !imageError) setImageError(true);
452
+ else if (effectiveData.originalImage && !originalImageError) setOriginalImageError(true);
453
+ else setFallbackImageError(true);
454
+ };
455
+ const renderImage = () => {
456
+ if (!resolvedImageUrl) return null;
457
+ if (isPlaceholder) {
458
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
459
+ "img",
460
+ {
461
+ src: resolvedImageUrl,
462
+ alt: title,
463
+ className: "absolute inset-0 w-full h-full object-cover rounded-md"
464
+ }
465
+ );
466
+ }
467
+ if (isFallbackImage) {
468
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
469
+ _chunkXL4V2PYGcjs.next_image_default,
470
+ {
471
+ src: resolvedImageUrl,
472
+ alt: title,
473
+ fill: true,
474
+ className: "object-contain rounded-md group-hover:scale-105 transition-transform duration-300",
475
+ onError: handleImageError,
476
+ unoptimized: resolvedImageUrl.includes("/render/image/")
477
+ }
478
+ );
479
+ }
480
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
481
+ "img",
482
+ {
483
+ src: resolvedImageUrl,
484
+ alt: title,
485
+ className: "absolute inset-0 w-full h-full object-contain rounded-md group-hover:scale-105 transition-transform duration-300",
486
+ onError: handleImageError
487
+ }
488
+ );
489
+ };
490
+ if (isCompact) {
491
+ if (!hasImage) {
492
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-4", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
493
+ "a",
494
+ {
495
+ href: effectiveData.url,
496
+ target: "_blank",
497
+ rel: "noopener noreferrer",
498
+ className: "flex flex-row items-center gap-3 border border-ods-border rounded-lg overflow-hidden bg-ods-card hover:border-ods-accent transition-all duration-200 group px-4 py-3",
499
+ children: [
500
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-8 h-8 bg-ods-bg-secondary rounded-lg flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Favicon, { src: faviconSrc, size: "w-5 h-5" }) }),
501
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [
502
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "font-sans text-sm font-semibold text-ods-text-primary group-hover:text-ods-accent transition-colors truncate", children: title }),
503
+ description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "font-sans text-xs text-ods-text-secondary truncate", children: description })
504
+ ] }),
505
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ExternalLinkIcon, { size: 14 })
506
+ ]
507
+ }
508
+ ) });
509
+ }
510
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-4", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
511
+ "a",
512
+ {
513
+ href: effectiveData.url,
514
+ target: "_blank",
515
+ rel: "noopener noreferrer",
516
+ className: "flex flex-row border border-ods-border rounded-lg overflow-hidden bg-ods-card hover:border-ods-accent transition-colors group h-[120px]",
517
+ children: [
518
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-[200px] h-full flex-shrink-0 overflow-hidden relative flex items-center justify-center rounded-lg transition-colors duration-300", style: { backgroundColor: bgColor }, children: renderImage() }),
519
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 p-3 flex flex-col justify-center min-w-0", children: [
520
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
521
+ "h3",
522
+ {
523
+ className: "font-sans text-sm font-semibold text-ods-text-primary overflow-hidden group-hover:text-ods-accent transition-colors",
524
+ style: { display: "-webkit-box", WebkitLineClamp: 1, WebkitBoxOrient: "vertical" },
525
+ children: title
526
+ }
527
+ ),
528
+ description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
529
+ "p",
530
+ {
531
+ className: "font-sans text-xs text-ods-text-secondary overflow-hidden mt-1",
532
+ style: { display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical" },
533
+ children: description
534
+ }
535
+ ),
536
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-xs text-ods-text-secondary mt-1 truncate", children: effectiveData.siteName || ogDomain })
537
+ ] })
538
+ ]
539
+ }
540
+ ) });
541
+ }
542
+ if (!hasImage) {
543
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-6", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
544
+ "a",
545
+ {
546
+ href: effectiveData.url,
547
+ target: "_blank",
548
+ rel: "noopener noreferrer",
549
+ className: "flex items-center gap-3 border border-ods-border rounded-lg overflow-hidden bg-ods-card hover:border-ods-accent transition-all duration-200 group px-4 py-3",
550
+ children: [
551
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-10 h-10 bg-ods-bg-secondary rounded-lg flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Favicon, { src: faviconSrc }) }),
552
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [
553
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "font-sans font-semibold text-ods-text-primary text-base group-hover:text-ods-accent transition-colors truncate", children: title }),
554
+ description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "font-sans text-sm text-ods-text-secondary truncate", children: description })
555
+ ] }),
556
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ExternalLinkIcon, {})
557
+ ]
558
+ }
559
+ ) });
560
+ }
561
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "my-6", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
562
+ "a",
563
+ {
564
+ href: effectiveData.url,
565
+ target: "_blank",
566
+ rel: "noopener noreferrer",
567
+ className: "block border border-ods-border rounded-lg overflow-hidden bg-ods-card hover:border-ods-accent transition-colors group",
568
+ children: [
569
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "aspect-video w-full overflow-hidden relative flex items-center justify-center rounded-lg transition-colors duration-300", style: { backgroundColor: bgColor }, children: renderImage() }),
570
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "p-4", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-start gap-3", children: [
571
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
572
+ "img",
573
+ {
574
+ src: logoSrc,
575
+ alt: publicationName || "",
576
+ className: "w-6 h-6 rounded object-contain flex-shrink-0 mt-0.5",
577
+ onError: (e) => {
578
+ e.target.style.display = "none";
579
+ }
580
+ }
581
+ ),
582
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [
583
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
584
+ "h3",
585
+ {
586
+ className: "font-sans font-semibold text-ods-text-primary text-base overflow-hidden group-hover:text-ods-accent transition-colors h-[2.5rem] leading-[1.25rem] mb-2",
587
+ style: { display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical" },
588
+ children: title
589
+ }
590
+ ),
591
+ description && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
592
+ "p",
593
+ {
594
+ className: "font-sans text-sm text-ods-text-secondary overflow-hidden h-[2.5rem] leading-[1.25rem] mb-2",
595
+ style: { display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical" },
596
+ children: description
597
+ }
598
+ ),
599
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 text-xs text-ods-text-secondary", children: [
600
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium", children: effectiveData.siteName }),
601
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "\u2022" }),
602
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "truncate", children: ogDomain })
603
+ ] })
604
+ ] })
605
+ ] }) })
606
+ ]
607
+ }
608
+ ) });
609
+ };
610
+
611
+
612
+
613
+
614
+
615
+
616
+
617
+
618
+ exports.EmbedIframe = EmbedIframe; exports.PdfViewer = PdfViewer; exports.GoogleSheetsViewer = GoogleSheetsViewer; exports.FigmaEmbed = FigmaEmbed; exports.OGLinkErrorBoundary = OGLinkErrorBoundary; exports.OGLinkPreview = OGLinkPreview;
619
+ //# sourceMappingURL=chunk-DVUFNTI2.cjs.map