feat(layout): re-enable "Back to hub" with a sticky sheet footer
Reverses the events-only hide (c037d45) now that the link has a real
home. Three parts:
- Add a @brand-hub-logo alias (brandHubLogoAliasEntry) resolving to the
brand's primary/global logo — the HUB's logo, never the per-standalone
@brand-app-logo. Wired into all 9 app vite configs since the shared
ProfileSheetContent renders it.
- Restructure the profile sheet into a fixed-height flex column: a
flex-1 min-h-0 overflow-y-auto scroll region over a shrink-0 footer,
so "Back to hub" + the log-in/out bar stay pinned to the bottom while
the identity/preferences area scrolls.
- Move the edit-profile Dialog out of the flex root (it portals to body,
so it's not part of the sheet flow).
Logo bumped to w-8 h-8, centered, with tightened footer padding.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8419ca4660
commit
2cc8e34b9d
11 changed files with 183 additions and 149 deletions
|
|
@ -66,9 +66,7 @@ const npubPreview = computed(() => {
|
||||||
return value.length > 24 ? `${value.slice(0, 12)}…${value.slice(-8)}` : value
|
return value.length > 24 ? `${value.slice(0, 12)}…${value.slice(-8)}` : value
|
||||||
})
|
})
|
||||||
|
|
||||||
// "Back to hub" is hidden for the events-only launch (see template).
|
const hubRootUrl = computed(() => import.meta.env.VITE_HUB_ROOT_URL || '/')
|
||||||
// Re-enable this alongside the commented-out link below when the hub ships.
|
|
||||||
// const hubRootUrl = computed(() => import.meta.env.VITE_HUB_ROOT_URL || '/')
|
|
||||||
|
|
||||||
const copiedField = ref<string | null>(null)
|
const copiedField = ref<string | null>(null)
|
||||||
async function copyToClipboard(text: string, field: string) {
|
async function copyToClipboard(text: string, field: string) {
|
||||||
|
|
@ -105,6 +103,14 @@ async function onLogout() {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<!-- Fill the sheet exactly (h-full) so the footer stays stuck to the
|
||||||
|
bottom while only the region above it scrolls. The sheet host already
|
||||||
|
has overflow-y-auto, but with an exact-fit child it never triggers —
|
||||||
|
the inner flex-1 region owns the scroll instead. -->
|
||||||
|
<div class="flex h-full flex-col">
|
||||||
|
<!-- Scrollable region: everything above the pinned footer. min-h-0 lets
|
||||||
|
this flex child shrink below its content height so it can scroll. -->
|
||||||
|
<div class="flex-1 min-h-0 overflow-y-auto">
|
||||||
<SheetHeader>
|
<SheetHeader>
|
||||||
<SheetTitle>{{ t('common.nav.profile') }}</SheetTitle>
|
<SheetTitle>{{ t('common.nav.profile') }}</SheetTitle>
|
||||||
<SheetDescription v-if="isAuthenticated">
|
<SheetDescription v-if="isAuthenticated">
|
||||||
|
|
@ -190,31 +196,30 @@ async function onLogout() {
|
||||||
|
|
||||||
<!-- Cross-app links + global preferences (always visible, auth or not) -->
|
<!-- Cross-app links + global preferences (always visible, auth or not) -->
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<!-- "Back to hub" hidden for the events-only launch — re-enable when
|
<PreferencesRow layout="list" />
|
||||||
the hub ships. When re-enabled, show the HUB's brand-kit logo
|
</div>
|
||||||
(the brand's primary/global logo, or a hub-specific override) —
|
</div>
|
||||||
NOT the per-standalone @brand-app-logo, which resolves to this
|
|
||||||
standalone's own logo. This needs a hub-logo alias (e.g.
|
<!-- Pinned footer: stays stuck to the bottom of the sheet (shrink-0);
|
||||||
@brand-hub-logo = resolveAppLogo for the hub) added in
|
"Back to hub" sits directly above the log-in/out bar. -->
|
||||||
vite-branding.ts + the standalone vite configs.
|
<div class="shrink-0 pt-1">
|
||||||
|
<!-- "Back to hub" shows the HUB's brand-kit logo (the brand's
|
||||||
|
primary/global logo via @brand-hub-logo) — NOT the per-standalone
|
||||||
|
@brand-app-logo, which resolves to this standalone's own logo. -->
|
||||||
<a
|
<a
|
||||||
:href="hubRootUrl"
|
:href="hubRootUrl"
|
||||||
class="flex items-center justify-between gap-3 px-3 py-3 hover:bg-accent rounded-md transition-colors"
|
class="flex items-center justify-center gap-3 px-3 py-1.5 hover:bg-accent rounded-md transition-colors"
|
||||||
:aria-label="t('common.nav.backToHub')"
|
:aria-label="t('common.nav.backToHub')"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<img src="@brand-hub-logo" :alt="t('common.nav.backToHub')" class="w-5 h-5 shrink-0" />
|
<img src="@brand-hub-logo" :alt="t('common.nav.backToHub')" class="w-8 h-8 shrink-0" />
|
||||||
<span class="text-sm font-medium">{{ t('common.nav.backToHub') }}</span>
|
<span class="text-sm font-medium">{{ t('common.nav.backToHub') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
-->
|
|
||||||
|
|
||||||
<PreferencesRow layout="list" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Logged-out: prominent log-in CTA -->
|
<!-- Logged-out: prominent log-in CTA -->
|
||||||
<div v-if="!isAuthenticated" class="mt-6">
|
<div v-if="!isAuthenticated">
|
||||||
<Separator class="mb-4" />
|
<Separator class="mb-2" />
|
||||||
<Button class="w-full" @click="goLogin">
|
<Button class="w-full" @click="goLogin">
|
||||||
<LogIn class="mr-2 h-4 w-4" />
|
<LogIn class="mr-2 h-4 w-4" />
|
||||||
{{ t('common.nav.login') }}
|
{{ t('common.nav.login') }}
|
||||||
|
|
@ -222,8 +227,8 @@ async function onLogout() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Logged-in: log-out button stays visible without opening the edit popup. -->
|
<!-- Logged-in: log-out button stays visible without opening the edit popup. -->
|
||||||
<div v-else class="mt-6">
|
<div v-else>
|
||||||
<Separator class="mb-4" />
|
<Separator class="mb-2" />
|
||||||
<AlertDialog>
|
<AlertDialog>
|
||||||
<AlertDialogTrigger as-child>
|
<AlertDialogTrigger as-child>
|
||||||
<Button variant="destructive" class="w-full">
|
<Button variant="destructive" class="w-full">
|
||||||
|
|
@ -252,9 +257,12 @@ async function onLogout() {
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Edit-profile popup (pencil button in the identity card) — the full
|
<!-- Edit-profile popup (pencil button in the identity card) — the full
|
||||||
form lives here so the sheet stays scannable. -->
|
form lives here so the sheet stays scannable. Outside the flex root:
|
||||||
|
its content portals to <body>, so it's not part of the sheet flow. -->
|
||||||
<Dialog v-model:open="editProfileOpen">
|
<Dialog v-model:open="editProfileOpen">
|
||||||
<DialogContent class="max-w-md max-h-[90vh] overflow-y-auto overflow-x-hidden">
|
<DialogContent class="max-w-md max-h-[90vh] overflow-y-auto overflow-x-hidden">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,22 @@ export function brandAppLogoAliasEntry(app?: string) {
|
||||||
} as const
|
} as const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hub-logo alias entry. Resolves `@brand-hub-logo` to the brand's
|
||||||
|
* primary/global logo (the hub's logo), independent of which standalone
|
||||||
|
* is building. Unlike {@link brandAppLogoAliasEntry}, this never takes an
|
||||||
|
* `app` argument — the "Back to hub" link in every standalone must point
|
||||||
|
* at the HUB's logo, not the current standalone's own logo. Wire it into
|
||||||
|
* every vite.<app>.config.ts that builds ProfileSheetContent.vue.
|
||||||
|
*/
|
||||||
|
export function brandHubLogoAliasEntry() {
|
||||||
|
const resolved = resolveAppLogo()
|
||||||
|
return {
|
||||||
|
find: /^@brand-hub-logo(\?.*)?$/,
|
||||||
|
replacement: `${resolved}$1`,
|
||||||
|
} as const
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional brand banner — a wide lockup (logo + wordmark in one image)
|
* Optional brand banner — a wide lockup (logo + wordmark in one image)
|
||||||
* that replaces the logo + app-name pair in a standalone's header.
|
* that replaces the logo + app-name pair in a standalone's header.
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
||||||
import { VitePWA } from 'vite-plugin-pwa'
|
import { VitePWA } from 'vite-plugin-pwa'
|
||||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||||
import { visualizer } from 'rollup-plugin-visualizer'
|
import { visualizer } from 'rollup-plugin-visualizer'
|
||||||
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin } from './vite-branding'
|
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin, brandHubLogoAliasEntry } from './vite-branding'
|
||||||
|
|
||||||
function chatHtmlPlugin(): Plugin {
|
function chatHtmlPlugin(): Plugin {
|
||||||
return {
|
return {
|
||||||
|
|
@ -107,6 +107,7 @@ export default defineConfig(({ mode }) => ({
|
||||||
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
||||||
alias: [
|
alias: [
|
||||||
brandAppLogoAliasEntry('chat'),
|
brandAppLogoAliasEntry('chat'),
|
||||||
|
brandHubLogoAliasEntry(),
|
||||||
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
||||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||||
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/chat-app/app.config.ts', import.meta.url)) },
|
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/chat-app/app.config.ts', import.meta.url)) },
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { defineConfig } from 'vite'
|
||||||
import Inspect from 'vite-plugin-inspect'
|
import Inspect from 'vite-plugin-inspect'
|
||||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||||
import { visualizer } from 'rollup-plugin-visualizer'
|
import { visualizer } from 'rollup-plugin-visualizer'
|
||||||
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin } from './vite-branding'
|
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin, brandHubLogoAliasEntry } from './vite-branding'
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
//
|
//
|
||||||
|
|
@ -53,6 +53,7 @@ export default defineConfig(({ mode }) => ({
|
||||||
// with optional `?url` query) doesn't get shadowed by the bare alias.
|
// with optional `?url` query) doesn't get shadowed by the bare alias.
|
||||||
alias: [
|
alias: [
|
||||||
brandAppLogoAliasEntry(),
|
brandAppLogoAliasEntry(),
|
||||||
|
brandHubLogoAliasEntry(),
|
||||||
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
||||||
{ find: '@', replacement: fileURLToPath(new URL('./src', import.meta.url)) },
|
{ find: '@', replacement: fileURLToPath(new URL('./src', import.meta.url)) },
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
brandAppBannerAliasEntry,
|
brandAppBannerAliasEntry,
|
||||||
brandAppLogoAliasEntry,
|
brandAppLogoAliasEntry,
|
||||||
brandAssetsPlugin,
|
brandAssetsPlugin,
|
||||||
|
brandHubLogoAliasEntry,
|
||||||
brandManifestName,
|
brandManifestName,
|
||||||
resolveAppBanner,
|
resolveAppBanner,
|
||||||
} from './vite-branding'
|
} from './vite-branding'
|
||||||
|
|
@ -137,6 +138,7 @@ export default defineConfig(({ mode }) => ({
|
||||||
alias: [
|
alias: [
|
||||||
brandAppLogoAliasEntry('events'),
|
brandAppLogoAliasEntry('events'),
|
||||||
brandAppBannerAliasEntry('events'),
|
brandAppBannerAliasEntry('events'),
|
||||||
|
brandHubLogoAliasEntry(),
|
||||||
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
||||||
{ find: '@', replacement: fileURLToPath(new URL('./src', import.meta.url)) },
|
{ find: '@', replacement: fileURLToPath(new URL('./src', import.meta.url)) },
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
||||||
import { VitePWA } from 'vite-plugin-pwa'
|
import { VitePWA } from 'vite-plugin-pwa'
|
||||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||||
import { visualizer } from 'rollup-plugin-visualizer'
|
import { visualizer } from 'rollup-plugin-visualizer'
|
||||||
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin } from './vite-branding'
|
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin, brandHubLogoAliasEntry } from './vite-branding'
|
||||||
|
|
||||||
function forumHtmlPlugin(): Plugin {
|
function forumHtmlPlugin(): Plugin {
|
||||||
return {
|
return {
|
||||||
|
|
@ -107,6 +107,7 @@ export default defineConfig(({ mode }) => ({
|
||||||
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
||||||
alias: [
|
alias: [
|
||||||
brandAppLogoAliasEntry('forum'),
|
brandAppLogoAliasEntry('forum'),
|
||||||
|
brandHubLogoAliasEntry(),
|
||||||
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
||||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||||
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/forum-app/app.config.ts', import.meta.url)) },
|
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/forum-app/app.config.ts', import.meta.url)) },
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
||||||
import { VitePWA } from 'vite-plugin-pwa'
|
import { VitePWA } from 'vite-plugin-pwa'
|
||||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||||
import { visualizer } from 'rollup-plugin-visualizer'
|
import { visualizer } from 'rollup-plugin-visualizer'
|
||||||
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin } from './vite-branding'
|
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin, brandHubLogoAliasEntry } from './vite-branding'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin to rewrite dev server requests to libra.html
|
* Plugin to rewrite dev server requests to libra.html
|
||||||
|
|
@ -114,6 +114,7 @@ export default defineConfig(({ mode }) => ({
|
||||||
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
||||||
alias: [
|
alias: [
|
||||||
brandAppLogoAliasEntry('libra'),
|
brandAppLogoAliasEntry('libra'),
|
||||||
|
brandHubLogoAliasEntry(),
|
||||||
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
||||||
// ORDER MATTERS — @rollup/plugin-alias is first-match-wins.
|
// ORDER MATTERS — @rollup/plugin-alias is first-match-wins.
|
||||||
// The more specific @/app.config remap must precede the @ prefix
|
// The more specific @/app.config remap must precede the @ prefix
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
||||||
import { VitePWA } from 'vite-plugin-pwa'
|
import { VitePWA } from 'vite-plugin-pwa'
|
||||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||||
import { visualizer } from 'rollup-plugin-visualizer'
|
import { visualizer } from 'rollup-plugin-visualizer'
|
||||||
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin } from './vite-branding'
|
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin, brandHubLogoAliasEntry } from './vite-branding'
|
||||||
|
|
||||||
function marketHtmlPlugin(): Plugin {
|
function marketHtmlPlugin(): Plugin {
|
||||||
return {
|
return {
|
||||||
|
|
@ -107,6 +107,7 @@ export default defineConfig(({ mode }) => ({
|
||||||
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
||||||
alias: [
|
alias: [
|
||||||
brandAppLogoAliasEntry('market'),
|
brandAppLogoAliasEntry('market'),
|
||||||
|
brandHubLogoAliasEntry(),
|
||||||
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
||||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||||
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/market-app/app.config.ts', import.meta.url)) },
|
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/market-app/app.config.ts', import.meta.url)) },
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
||||||
import { VitePWA } from 'vite-plugin-pwa'
|
import { VitePWA } from 'vite-plugin-pwa'
|
||||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||||
import { visualizer } from 'rollup-plugin-visualizer'
|
import { visualizer } from 'rollup-plugin-visualizer'
|
||||||
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin } from './vite-branding'
|
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin, brandHubLogoAliasEntry } from './vite-branding'
|
||||||
|
|
||||||
function restaurantHtmlPlugin(): Plugin {
|
function restaurantHtmlPlugin(): Plugin {
|
||||||
return {
|
return {
|
||||||
|
|
@ -114,6 +114,7 @@ export default defineConfig(({ mode }) => ({
|
||||||
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
||||||
alias: [
|
alias: [
|
||||||
brandAppLogoAliasEntry('restaurant'),
|
brandAppLogoAliasEntry('restaurant'),
|
||||||
|
brandHubLogoAliasEntry(),
|
||||||
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
||||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||||
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/restaurant-app/app.config.ts', import.meta.url)) },
|
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/restaurant-app/app.config.ts', import.meta.url)) },
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
||||||
import { VitePWA } from 'vite-plugin-pwa'
|
import { VitePWA } from 'vite-plugin-pwa'
|
||||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||||
import { visualizer } from 'rollup-plugin-visualizer'
|
import { visualizer } from 'rollup-plugin-visualizer'
|
||||||
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin } from './vite-branding'
|
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin, brandHubLogoAliasEntry } from './vite-branding'
|
||||||
|
|
||||||
function tasksHtmlPlugin(): Plugin {
|
function tasksHtmlPlugin(): Plugin {
|
||||||
return {
|
return {
|
||||||
|
|
@ -107,6 +107,7 @@ export default defineConfig(({ mode }) => ({
|
||||||
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
||||||
alias: [
|
alias: [
|
||||||
brandAppLogoAliasEntry('tasks'),
|
brandAppLogoAliasEntry('tasks'),
|
||||||
|
brandHubLogoAliasEntry(),
|
||||||
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
||||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||||
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/tasks-app/app.config.ts', import.meta.url)) },
|
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/tasks-app/app.config.ts', import.meta.url)) },
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { defineConfig, type Plugin } from 'vite'
|
||||||
import { VitePWA } from 'vite-plugin-pwa'
|
import { VitePWA } from 'vite-plugin-pwa'
|
||||||
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
import { ViteImageOptimizer } from 'vite-plugin-image-optimizer'
|
||||||
import { visualizer } from 'rollup-plugin-visualizer'
|
import { visualizer } from 'rollup-plugin-visualizer'
|
||||||
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin } from './vite-branding'
|
import { brand, brandAlias, brandAppLogoAliasEntry, brandAssetsPlugin, brandHubLogoAliasEntry } from './vite-branding'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin to rewrite dev server requests to wallet.html
|
* Plugin to rewrite dev server requests to wallet.html
|
||||||
|
|
@ -113,6 +113,7 @@ export default defineConfig(({ mode }) => ({
|
||||||
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
// with optional `?url` query) doesn't get shadowed by the bare aliases.
|
||||||
alias: [
|
alias: [
|
||||||
brandAppLogoAliasEntry('wallet'),
|
brandAppLogoAliasEntry('wallet'),
|
||||||
|
brandHubLogoAliasEntry(),
|
||||||
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
...Object.entries(brandAlias).map(([find, replacement]) => ({ find, replacement })),
|
||||||
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
// ORDER MATTERS — @/app.config must precede @ (first-match-wins).
|
||||||
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/wallet-app/app.config.ts', import.meta.url)) },
|
{ find: '@/app.config', replacement: fileURLToPath(new URL('./src/wallet-app/app.config.ts', import.meta.url)) },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue