@reflagged/shell 1.8.0 → 1.8.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reflagged/shell",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Shared app shell for Reflagged services — OIDC auth, SSO, app switcher",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -55,16 +55,34 @@ export function faviconHref(
55
55
  export function useTenantFavicon(href: string | null | undefined): void {
56
56
  useEffect(() => {
57
57
  if (!href) return
58
- const existing = document.getElementById(FAVICON_LINK_ID) as HTMLLinkElement | null
59
- if (existing) {
60
- if (existing.href !== href) existing.href = href
61
- return
58
+
59
+ const apply = () => {
60
+ let link = document.getElementById(FAVICON_LINK_ID) as HTMLLinkElement | null
61
+ if (!link) {
62
+ link = document.createElement('link')
63
+ link.id = FAVICON_LINK_ID
64
+ link.rel = 'icon'
65
+ }
66
+ if (link.href !== href) link.href = href
67
+ // An app may ship icons of its own — the Payload admin does, one per
68
+ // colour scheme. Browsers take the last matching `rel=icon` in the head,
69
+ // and Next re-inserts its metadata links on every client navigation,
70
+ // after ours. Appending alone therefore holds only until the first
71
+ // in-app navigation, so the competitors go and ours is appended last.
72
+ for (const other of document.querySelectorAll<HTMLLinkElement>('link[rel~="icon"]')) {
73
+ if (other !== link) other.remove()
74
+ }
75
+ document.head.appendChild(link)
62
76
  }
63
- const link = document.createElement('link')
64
- link.id = FAVICON_LINK_ID
65
- link.rel = 'icon'
66
- link.href = href
67
- document.head.appendChild(link)
77
+
78
+ apply()
79
+ // Guarded by the count: `apply` itself mutates the head, and without the
80
+ // check the observer would call it again on its own changes.
81
+ const observer = new MutationObserver(() => {
82
+ if (document.querySelectorAll('link[rel~="icon"]').length > 1) apply()
83
+ })
84
+ observer.observe(document.head, { childList: true })
85
+ return () => observer.disconnect()
68
86
  }, [href])
69
87
  }
70
88