@mundogamernetwork/shared-ui 1.1.20 → 1.1.22

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.
@@ -1,10 +1,23 @@
1
1
  <script setup lang="ts">
2
+ // Optional props — allow the consuming layout to pass config directly
3
+ // instead of relying on the store guessing the right runtimeConfig key.
4
+ const props = withDefaults(defineProps<{
5
+ apiBaseUrl?: string;
6
+ platformId?: number | string;
7
+ }>(), {
8
+ apiBaseUrl: undefined,
9
+ platformId: undefined,
10
+ });
11
+
2
12
  const colorMode = useColorMode();
3
13
  const store = useAppInstallBannerStore();
4
14
  const locale = useNuxtApp().$i18n.locale;
5
15
 
6
16
  onMounted(async () => {
7
- await store.fetchBanner();
17
+ await store.fetchBanner(
18
+ props.apiBaseUrl,
19
+ props.platformId !== undefined ? Number(props.platformId) : undefined,
20
+ );
8
21
  });
9
22
 
10
23
  const banner = computed(() => store.banner);
@@ -15,10 +15,10 @@ const isMobile = ref(false);
15
15
  const currentIndex = ref(0);
16
16
  let timer: ReturnType<typeof setInterval> | null = null;
17
17
 
18
- const { data: banners } = await useAsyncData(
18
+ const { data: banners, pending } = await useAsyncData(
19
19
  `mg-campaign-banners-${props.platform}-${props.page}-${locale.value}`,
20
20
  () => fetchCampaignBanners(props.platform, props.page, locale.value),
21
- { default: () => [], lazy: true, server: false },
21
+ { default: () => [], lazy: true },
22
22
  );
23
23
 
24
24
  const hasBanners = computed(() => (banners.value?.length ?? 0) > 0);
@@ -67,7 +67,9 @@ onUnmounted(() => {
67
67
  </script>
68
68
 
69
69
  <template>
70
- <div v-if="hasBanners" class="mg-campaign-banner-carousel mb-4">
70
+ <div v-if="pending" class="mg-campaign-banner-skeleton mb-4" aria-hidden="true" />
71
+
72
+ <div v-else-if="hasBanners" class="mg-campaign-banner-carousel mb-4">
71
73
  <div
72
74
  class="mg-campaign-banner-slide"
73
75
  role="button"
@@ -96,6 +98,18 @@ onUnmounted(() => {
96
98
  </template>
97
99
 
98
100
  <style lang="scss" scoped>
101
+ @keyframes mg-skeleton-loading {
102
+ 0% { background-color: rgba(255, 255, 255, 0.06); }
103
+ 100% { background-color: rgba(221, 221, 221, 0.18); }
104
+ }
105
+
106
+ .mg-campaign-banner-skeleton {
107
+ width: 100%;
108
+ aspect-ratio: 4 / 1;
109
+ min-height: 120px;
110
+ animation: mg-skeleton-loading 0.8s linear infinite alternate;
111
+ }
112
+
99
113
  .mg-campaign-banner-carousel {
100
114
  position: relative;
101
115
  width: 100%;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mundogamernetwork/shared-ui",
3
- "version": "1.1.20",
3
+ "version": "1.1.22",
4
4
  "description": "Mundo Gamer Network - Shared UI Layer (Nuxt 3)",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -92,14 +92,25 @@ useHead(() => ({
92
92
 
93
93
  <template v-else>
94
94
  <!-- CAPA / COVER -->
95
- <header class="kit-cover">
96
- <img v-if="kit.hero_image_url" class="kit-cover-art" :src="kit.hero_image_url" :alt="kit.name" />
95
+ <header class="kit-cover" :style="kit.hero_image_url ? { backgroundImage: `url(${kit.hero_image_url})` } : {}">
97
96
  <div class="kit-cover-inner">
98
- <img v-if="kit.cover_image_url" class="kit-cover-poster" :src="kit.cover_image_url" :alt="kit.name" />
97
+ <img
98
+ v-if="kit.cover_image_url"
99
+ class="kit-cover-poster"
100
+ :src="kit.cover_image_url"
101
+ :alt="kit.name"
102
+ @error="(e: any) => e.target.style.display = 'none'"
103
+ />
99
104
  <div class="kit-cover-text">
100
105
  <span v-if="kit.release_status" class="kit-eyebrow">{{ String(kit.release_status).replace(/_/g, ' ') }}</span>
101
- <img v-if="kit.logo_url" class="kit-cover-logo-img" :src="kit.logo_url" :alt="kit.name" />
102
- <h1 v-else>{{ kit.name }}</h1>
106
+ <img
107
+ v-if="kit.logo_url"
108
+ class="kit-cover-logo-img"
109
+ :src="kit.logo_url"
110
+ :alt="kit.name"
111
+ @error="(e: any) => { e.target.style.display = 'none'; e.target.nextElementSibling.style.display = 'block'; }"
112
+ />
113
+ <h1 :style="kit.logo_url ? { display: 'none' } : {}">{{ kit.name }}</h1>
103
114
  <p v-if="kit.tagline" class="kit-tagline">{{ kit.tagline }}</p>
104
115
  <p v-if="kit.developer" class="kit-kicker">{{ kit.developer }}</p>
105
116
  <div class="kit-actions">
@@ -256,14 +267,13 @@ useHead(() => ({
256
267
  .kit-state { display: flex; align-items: center; justify-content: center; min-height: 60vh; color: var(--kit-muted); flex-direction: column; gap: 8px; }
257
268
  .kit-wrap { max-width: var(--kit-maxw); margin: 0 auto; padding: 0 24px; }
258
269
 
259
- .kit-cover { position: relative; min-height: 480px; display: flex; align-items: center; justify-content: center; text-align: center; overflow: hidden; border-bottom: 1px solid var(--kit-line); background: linear-gradient(135deg, #161b2a, #0f1320 55%, #1d1530); }
260
- .kit-cover-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .5; }
270
+ .kit-cover { position: relative; min-height: 480px; display: flex; align-items: center; justify-content: center; text-align: center; overflow: hidden; border-bottom: 1px solid var(--kit-line); background: linear-gradient(135deg, #161b2a, #0f1320 55%, #1d1530) center/cover; }
261
271
  .kit-cover::after { content: ""; position: absolute; inset: 0; background: radial-gradient(circle at 50% 40%, transparent, var(--kit-bg) 95%); }
262
272
  .kit-cover-inner { position: relative; z-index: 2; padding: 60px 24px; display: flex; align-items: center; justify-content: center; gap: 44px; width: 100%; max-width: var(--kit-maxw); }
263
273
  .kit-cover-poster { width: 240px; flex-shrink: 0; aspect-ratio: 2/3; object-fit: cover; border: 1px solid rgba(255,255,255,.15); box-shadow: 0 24px 70px rgba(0,0,0,.65); background: var(--kit-surface-2); }
264
274
  .kit-cover-text { text-align: left; max-width: 560px; }
265
275
  .kit-cover-text h1 { font-family: 'Rajdhani', sans-serif; font-size: 72px; font-weight: 700; line-height: .95; }
266
- .kit-cover-logo-img { max-height: 150px; }
276
+ .kit-cover-logo-img { display: block; max-height: 150px; margin-bottom: 12px; }
267
277
  .kit-eyebrow { display: inline-block; background: var(--kit-accent); color: var(--kit-accent-ink); font-family: 'Rajdhani'; font-weight: 700; font-size: 12px; letter-spacing: 2px; text-transform: uppercase; padding: 5px 14px; margin-bottom: 18px; }
268
278
  .kit-tagline { font-size: 20px; color: #dce0e8; margin-top: 14px; }
269
279
  .kit-kicker { margin-top: 8px; font-family: 'Rajdhani'; letter-spacing: 4px; text-transform: uppercase; font-size: 13px; color: var(--kit-accent); font-weight: 600; }
@@ -72,26 +72,28 @@ export const useAppInstallBannerStore = defineStore("app-install-banner-store",
72
72
  }),
73
73
 
74
74
  actions: {
75
- async fetchBanner() {
75
+ async fetchBanner(overrideBaseUrl?: string, overridePlatformId?: number) {
76
76
  if (this.loaded) return;
77
77
 
78
78
  const runtimeConfig = useRuntimeConfig();
79
79
  const cfg = runtimeConfig.public;
80
- // Support both shared-ui namespace (mgSharedUi.networkBaseUrl / mgSharedUi.systemId)
81
- // and the per-front flat keys used by fronts that don't go through the full mgSharedUi config
82
- // (networkBaseURL / platformId).
80
+ // Priority: explicit props from layout > shared-ui namespace > flat runtimeConfig keys > build-time env vars
83
81
  const networkBaseUrl =
82
+ overrideBaseUrl ||
84
83
  cfg.mgSharedUi?.networkBaseUrl ||
85
84
  cfg.networkBaseURL ||
86
85
  cfg.networkBaseUrl ||
87
86
  cfg.apiBaseURL ||
88
- import.meta.env.VITE_BASE_URL_NETWORK;
89
- const platformId = Number(
90
- cfg.mgSharedUi?.systemId ||
91
- cfg.platformId ||
92
- cfg.systemId ||
93
- import.meta.env.VITE_SYSTEM_ID,
94
- );
87
+ (import.meta.env.VITE_BASE_URL_NETWORK as string) ||
88
+ (import.meta.env.VITE_API_BASE_URL as string);
89
+ const platformId =
90
+ overridePlatformId ||
91
+ Number(
92
+ cfg.mgSharedUi?.systemId ||
93
+ cfg.platformId ||
94
+ cfg.systemId ||
95
+ import.meta.env.VITE_SYSTEM_ID,
96
+ );
95
97
 
96
98
  if (!networkBaseUrl || !platformId) {
97
99
  this.loaded = true;