@flamingo-stack/openframe-frontend-core 0.0.472 → 0.0.473-snapshot.20260724114839
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.
- package/dist/{chunk-4BUX2F5P.cjs → chunk-2R5NM3FC.cjs} +40 -40
- package/dist/{chunk-4BUX2F5P.cjs.map → chunk-2R5NM3FC.cjs.map} +1 -1
- package/dist/{chunk-BY6TZ6KA.js → chunk-3NNCBZEM.js} +6 -6
- package/dist/{chunk-WD7SE532.cjs → chunk-464NJS2W.cjs} +73 -73
- package/dist/{chunk-WD7SE532.cjs.map → chunk-464NJS2W.cjs.map} +1 -1
- package/dist/{chunk-KZZCBQDU.cjs → chunk-5TQQ3CPE.cjs} +29 -29
- package/dist/{chunk-KZZCBQDU.cjs.map → chunk-5TQQ3CPE.cjs.map} +1 -1
- package/dist/{chunk-ONK4D4LG.cjs → chunk-6KD6KVAI.cjs} +5 -5
- package/dist/{chunk-ONK4D4LG.cjs.map → chunk-6KD6KVAI.cjs.map} +1 -1
- package/dist/{chunk-73CH4CZL.cjs → chunk-7VBGYCXG.cjs} +7 -7
- package/dist/{chunk-73CH4CZL.cjs.map → chunk-7VBGYCXG.cjs.map} +1 -1
- package/dist/{chunk-FPOHUGEK.js → chunk-AGX565ZT.js} +2 -2
- package/dist/{chunk-RIEAXUJX.cjs → chunk-BOPLMNSN.cjs} +135 -174
- package/dist/chunk-BOPLMNSN.cjs.map +1 -0
- package/dist/{chunk-PJYGEXWM.js → chunk-FBUIZTAI.js} +2 -2
- package/dist/{chunk-HQL5GJ35.cjs → chunk-FM5KWLKU.cjs} +3 -3
- package/dist/{chunk-HQL5GJ35.cjs.map → chunk-FM5KWLKU.cjs.map} +1 -1
- package/dist/{chunk-YTLINJRR.cjs → chunk-GELW7JOQ.cjs} +32 -32
- package/dist/{chunk-YTLINJRR.cjs.map → chunk-GELW7JOQ.cjs.map} +1 -1
- package/dist/{chunk-TVMARS74.js → chunk-IIOHHNMI.js} +54 -93
- package/dist/chunk-IIOHHNMI.js.map +1 -0
- package/dist/{chunk-XNJ2LZH2.js → chunk-K52S6LZ5.js} +3 -3
- package/dist/{chunk-JO7XJQ6G.cjs → chunk-KPVKZ5ML.cjs} +15 -15
- package/dist/{chunk-JO7XJQ6G.cjs.map → chunk-KPVKZ5ML.cjs.map} +1 -1
- package/dist/{chunk-DWQ4L3IB.cjs → chunk-KXKTXAGN.cjs} +40 -40
- package/dist/{chunk-DWQ4L3IB.cjs.map → chunk-KXKTXAGN.cjs.map} +1 -1
- package/dist/{chunk-VC4FOIY7.cjs → chunk-LFXUFFDZ.cjs} +73 -73
- package/dist/{chunk-VC4FOIY7.cjs.map → chunk-LFXUFFDZ.cjs.map} +1 -1
- package/dist/{chunk-ZPUT2BB4.js → chunk-OKRUL7YV.js} +4 -4
- package/dist/{chunk-U5FNZ2TL.cjs → chunk-PFD2VRZI.cjs} +18 -18
- package/dist/{chunk-U5FNZ2TL.cjs.map → chunk-PFD2VRZI.cjs.map} +1 -1
- package/dist/{chunk-W6RDDT3S.js → chunk-PTFSF3UP.js} +6 -6
- package/dist/{chunk-74ZFCTRZ.js → chunk-R4OGP4OV.js} +3 -3
- package/dist/{chunk-7D5KOJMF.js → chunk-RIPWRVA3.js} +5 -5
- package/dist/{chunk-EK2VQXUN.js → chunk-S6IB3BZK.js} +2 -2
- package/dist/{chunk-OUHLWOPJ.js → chunk-SAH4FR36.js} +5 -5
- package/dist/{chunk-TONMD7QX.cjs → chunk-VCOL4C2W.cjs} +86 -20
- package/dist/chunk-VCOL4C2W.cjs.map +1 -0
- package/dist/{chunk-XDBNMB5K.js → chunk-VNDAMVMI.js} +2 -2
- package/dist/{chunk-CUBNUQPZ.cjs → chunk-YJWISFIK.cjs} +12 -12
- package/dist/{chunk-CUBNUQPZ.cjs.map → chunk-YJWISFIK.cjs.map} +1 -1
- package/dist/{chunk-NY4WLKNU.js → chunk-Z4LAZ4ZZ.js} +3 -3
- package/dist/{chunk-OTV4A6NA.js → chunk-ZPUZPJDV.js} +80 -14
- package/dist/chunk-ZPUZPJDV.js.map +1 -0
- package/dist/components/announcement-bar.d.ts +1 -1
- package/dist/components/announcement-bar.d.ts.map +1 -1
- package/dist/components/case-studies/index.cjs +9 -9
- package/dist/components/case-studies/index.js +3 -3
- package/dist/components/chat/index.cjs +3 -3
- package/dist/components/chat/index.js +2 -2
- package/dist/components/contact/index.cjs +4 -4
- package/dist/components/contact/index.js +3 -3
- package/dist/components/docs/index.cjs +6 -6
- package/dist/components/docs/index.js +5 -5
- package/dist/components/embeds/index.cjs +4 -4
- package/dist/components/embeds/index.js +3 -3
- package/dist/components/faq/index.cjs +5 -5
- package/dist/components/faq/index.js +4 -4
- package/dist/components/features/index.cjs +3 -3
- package/dist/components/features/index.js +2 -2
- package/dist/components/help-center-pages/index.cjs +22 -22
- package/dist/components/help-center-pages/index.js +13 -13
- package/dist/components/index.cjs +174 -162
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +49 -37
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/index.cjs +3 -3
- package/dist/components/navigation/index.js +2 -2
- package/dist/components/navigation/mobile-burger-menu.d.ts.map +1 -1
- package/dist/components/onboarding-guides/index.cjs +7 -7
- package/dist/components/onboarding-guides/index.js +6 -6
- package/dist/components/related-content/index.cjs +5 -5
- package/dist/components/related-content/index.js +4 -4
- package/dist/components/tickets/index.cjs +6 -6
- package/dist/components/tickets/index.js +5 -5
- package/dist/components/ui/announcement-bar-view.d.ts +26 -24
- package/dist/components/ui/announcement-bar-view.d.ts.map +1 -1
- package/dist/components/ui/entity-image.d.ts.map +1 -1
- package/dist/components/ui/image-uploader.d.ts.map +1 -1
- package/dist/components/ui/index.cjs +3 -3
- package/dist/components/ui/index.js +2 -2
- package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
- package/dist/components/ui/square-avatar.d.ts.map +1 -1
- package/dist/hooks/index.cjs +6 -2
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +5 -1
- package/dist/hooks/use-authed-image-src.d.ts +10 -0
- package/dist/hooks/use-authed-image-src.d.ts.map +1 -0
- package/dist/index.cjs +7 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -2
- package/dist/types/announcement.cjs.map +1 -1
- package/dist/types/announcement.d.ts +5 -0
- package/dist/types/announcement.d.ts.map +1 -1
- package/dist/types/announcement.js.map +1 -1
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/embed-authed-fetch.d.ts +15 -0
- package/dist/utils/embed-authed-fetch.d.ts.map +1 -1
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/announcement-bar.tsx +58 -42
- package/src/components/navigation/mobile-burger-menu.tsx +1 -0
- package/src/components/ui/announcement-bar-view.tsx +42 -66
- package/src/components/ui/entity-image.tsx +5 -3
- package/src/components/ui/image-uploader.tsx +21 -12
- package/src/components/ui/simple-markdown-renderer.tsx +57 -58
- package/src/components/ui/square-avatar.tsx +5 -3
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-authed-image-src.ts +93 -0
- package/src/stories/AnnouncementBar.stories.tsx +20 -0
- package/src/types/announcement.ts +5 -0
- package/src/utils/embed-authed-fetch.ts +30 -0
- package/dist/chunk-OTV4A6NA.js.map +0 -1
- package/dist/chunk-RIEAXUJX.cjs.map +0 -1
- package/dist/chunk-TONMD7QX.cjs.map +0 -1
- package/dist/chunk-TVMARS74.js.map +0 -1
- /package/dist/{chunk-BY6TZ6KA.js.map → chunk-3NNCBZEM.js.map} +0 -0
- /package/dist/{chunk-FPOHUGEK.js.map → chunk-AGX565ZT.js.map} +0 -0
- /package/dist/{chunk-PJYGEXWM.js.map → chunk-FBUIZTAI.js.map} +0 -0
- /package/dist/{chunk-XNJ2LZH2.js.map → chunk-K52S6LZ5.js.map} +0 -0
- /package/dist/{chunk-ZPUT2BB4.js.map → chunk-OKRUL7YV.js.map} +0 -0
- /package/dist/{chunk-W6RDDT3S.js.map → chunk-PTFSF3UP.js.map} +0 -0
- /package/dist/{chunk-74ZFCTRZ.js.map → chunk-R4OGP4OV.js.map} +0 -0
- /package/dist/{chunk-7D5KOJMF.js.map → chunk-RIPWRVA3.js.map} +0 -0
- /package/dist/{chunk-EK2VQXUN.js.map → chunk-S6IB3BZK.js.map} +0 -0
- /package/dist/{chunk-OUHLWOPJ.js.map → chunk-SAH4FR36.js.map} +0 -0
- /package/dist/{chunk-XDBNMB5K.js.map → chunk-VNDAMVMI.js.map} +0 -0
- /package/dist/{chunk-NY4WLKNU.js.map → chunk-Z4LAZ4ZZ.js.map} +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useEffect, useReducer } from 'react'
|
|
4
|
+
import { embedAuthedFetch, needsBearerAssetFetch } from '../utils/embed-authed-fetch'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Resolve an image URL for hosts whose auth rides in request headers
|
|
8
|
+
* instead of cookies (native shells — `capacitor://localhost`,
|
|
9
|
+
* `tauri://localhost` — running in bearer mode). A native `<img>` load
|
|
10
|
+
* can't carry an `Authorization` header, so a gateway image URL that
|
|
11
|
+
* works on the cookie-auth web 401s in a shell. When
|
|
12
|
+
* `needsBearerAssetFetch` says the URL's origin is bearer-authed, this
|
|
13
|
+
* hook fetches it through `embedAuthedFetch` (bearer + deduped
|
|
14
|
+
* 401-refresh-retry + the adapter's cross-origin guard) and returns a
|
|
15
|
+
* blob object-URL; every other URL is returned unchanged, so on the
|
|
16
|
+
* cookie-auth web the hook is a pass-through.
|
|
17
|
+
*
|
|
18
|
+
* Returns `undefined` while the fetch is in flight OR after it fails, so
|
|
19
|
+
* callers show their existing initials/placeholder fallback instead of a
|
|
20
|
+
* broken image; a failed fetch retries on the next mount.
|
|
21
|
+
*
|
|
22
|
+
* Cache: module-level, session-lifetime, keyed by full URL. Gateway image
|
|
23
|
+
* URLs carry a `?v=<content-hash>` cache-buster, so a changed image is a
|
|
24
|
+
* new key; entries are never revoked (avatars are a few KB — refcount
|
|
25
|
+
* churn isn't worth it).
|
|
26
|
+
*
|
|
27
|
+
* Distinct from the legacy `useAuthenticatedImage`, which ALWAYS
|
|
28
|
+
* blob-fetches with `credentials: 'include'` and its own global config.
|
|
29
|
+
* This hook is pass-through-first and keys off the single auth knob the
|
|
30
|
+
* lib already has: the registered `EmbedAuthAdapter`.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
const resolvedCache = new Map<string, string>()
|
|
34
|
+
const inFlight = new Map<string, Promise<void>>()
|
|
35
|
+
let cacheGeneration = 0
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Drop every cached blob and revoke its object URL. Hosts call this at
|
|
39
|
+
* session end (logout / forced re-login) so a follow-on login as a
|
|
40
|
+
* different identity cannot be served blobs fetched under the previous
|
|
41
|
+
* one's bearer. Fetches still in flight when the clear happens are fenced
|
|
42
|
+
* by a generation counter — their results are revoked instead of cached.
|
|
43
|
+
*/
|
|
44
|
+
export function clearAuthedImageCache(): void {
|
|
45
|
+
cacheGeneration++
|
|
46
|
+
for (const url of resolvedCache.values()) URL.revokeObjectURL(url)
|
|
47
|
+
resolvedCache.clear()
|
|
48
|
+
inFlight.clear()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function fetchAsBlobUrl(src: string): Promise<void> {
|
|
52
|
+
let pending = inFlight.get(src)
|
|
53
|
+
if (!pending) {
|
|
54
|
+
const startedGeneration = cacheGeneration
|
|
55
|
+
pending = embedAuthedFetch(src, { headers: { Accept: 'image/*' } })
|
|
56
|
+
.then(async response => {
|
|
57
|
+
if (!response.ok) throw new Error(`image fetch failed: ${response.status}`)
|
|
58
|
+
const blobUrl = URL.createObjectURL(await response.blob())
|
|
59
|
+
if (startedGeneration === cacheGeneration) {
|
|
60
|
+
resolvedCache.set(src, blobUrl)
|
|
61
|
+
} else {
|
|
62
|
+
URL.revokeObjectURL(blobUrl)
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
.finally(() => {
|
|
66
|
+
if (inFlight.get(src) === pending) inFlight.delete(src)
|
|
67
|
+
})
|
|
68
|
+
inFlight.set(src, pending)
|
|
69
|
+
}
|
|
70
|
+
return pending
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function useAuthedImageSrc(src?: string | null): string | undefined {
|
|
74
|
+
const bearerSrc = src && needsBearerAssetFetch(src) ? src : null
|
|
75
|
+
const [, rerender] = useReducer((c: number) => c + 1, 0)
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
if (!bearerSrc || resolvedCache.has(bearerSrc)) return
|
|
79
|
+
let cancelled = false
|
|
80
|
+
fetchAsBlobUrl(bearerSrc)
|
|
81
|
+
.catch(() => {})
|
|
82
|
+
.finally(() => {
|
|
83
|
+
if (!cancelled) rerender()
|
|
84
|
+
})
|
|
85
|
+
return () => {
|
|
86
|
+
cancelled = true
|
|
87
|
+
}
|
|
88
|
+
}, [bearerSrc])
|
|
89
|
+
|
|
90
|
+
if (!src) return undefined
|
|
91
|
+
if (!bearerSrc) return src
|
|
92
|
+
return resolvedCache.get(bearerSrc)
|
|
93
|
+
}
|
|
@@ -83,6 +83,26 @@ export const WithCTA: Story = {
|
|
|
83
83
|
},
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Non-dismissible announcement — `dismissible={false}` drops the close (X)
|
|
88
|
+
* button, so the bar only disappears when the announcement is deactivated.
|
|
89
|
+
*/
|
|
90
|
+
export const WithoutCloseButton: Story = {
|
|
91
|
+
args: {
|
|
92
|
+
dismissible: false,
|
|
93
|
+
initialAnnouncement: {
|
|
94
|
+
...baseAnnouncement,
|
|
95
|
+
id: 'story-no-dismiss',
|
|
96
|
+
title: 'Mandatory Maintenance Notice',
|
|
97
|
+
description: 'This announcement cannot be dismissed by the user.',
|
|
98
|
+
cta_enabled: true,
|
|
99
|
+
cta_text: 'Learn More',
|
|
100
|
+
cta_url: 'https://example.com',
|
|
101
|
+
cta_target: '_blank',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
|
|
86
106
|
/**
|
|
87
107
|
* Announcement with a CTA button that opens in the same tab.
|
|
88
108
|
*/
|
|
@@ -238,6 +238,11 @@ export interface AnnouncementBarProps {
|
|
|
238
238
|
* cookies or touches localStorage).
|
|
239
239
|
*/
|
|
240
240
|
previewMode?: boolean;
|
|
241
|
+
/**
|
|
242
|
+
* When false, the dismiss (X) button is not rendered — the bar can only
|
|
243
|
+
* disappear by deactivating the announcement. Default true.
|
|
244
|
+
*/
|
|
245
|
+
dismissible?: boolean;
|
|
241
246
|
className?: string;
|
|
242
247
|
}
|
|
243
248
|
|
|
@@ -156,6 +156,36 @@ export function hasEmbedAuthAdapter(): boolean {
|
|
|
156
156
|
return getRegisteredAuthAdapter() !== null
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Whether `url` is an asset the browser CANNOT load natively because its
|
|
161
|
+
* auth rides in request headers: the registered adapter is currently
|
|
162
|
+
* supplying an `Authorization` header AND the URL's origin is one the
|
|
163
|
+
* adapter explicitly sanctions for that bearer (`allowedOrigins` — the
|
|
164
|
+
* host's gateway, cross-origin by construction in native shells).
|
|
165
|
+
*
|
|
166
|
+
* Native asset loads (`<img src>`, CSS `background-image`) can't carry
|
|
167
|
+
* custom headers, so a URL this returns `true` for must go through
|
|
168
|
+
* `embedAuthedFetch` → blob object-URL instead (see `useAuthedImageSrc`).
|
|
169
|
+
* Everything else — cookie-auth web (no Authorization), relative /
|
|
170
|
+
* same-origin URLs (cookies work), third-party origins the bearer does
|
|
171
|
+
* NOT belong to (public images) — loads natively, unchanged.
|
|
172
|
+
*/
|
|
173
|
+
export function needsBearerAssetFetch(url: string): boolean {
|
|
174
|
+
if (typeof window === 'undefined') return false
|
|
175
|
+
const adapter = getRegisteredAuthAdapter()
|
|
176
|
+
if (!adapter?.allowedOrigins?.length || adapter.getHeaders?.().Authorization === undefined) {
|
|
177
|
+
return false
|
|
178
|
+
}
|
|
179
|
+
let target: URL
|
|
180
|
+
try {
|
|
181
|
+
target = new URL(url, window.location.href)
|
|
182
|
+
} catch {
|
|
183
|
+
return false
|
|
184
|
+
}
|
|
185
|
+
if (target.protocol !== 'http:' && target.protocol !== 'https:') return false
|
|
186
|
+
return adapter.allowedOrigins.includes(target.origin)
|
|
187
|
+
}
|
|
188
|
+
|
|
159
189
|
/**
|
|
160
190
|
* `fetch` wrapper that attaches embed-proxy bearer headers (when
|
|
161
191
|
* present in sessionStorage) and forces `credentials: 'same-origin'`
|