@mundogamernetwork/shared-ui 1.13.2 → 1.13.3

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.
@@ -86,13 +86,24 @@ onMounted(async () => {
86
86
  </script>
87
87
 
88
88
  <template>
89
+ <!--
90
+ The root renders unconditionally so the server and the client agree on
91
+ the node at hydration time. A v-if here produced a comment on the server
92
+ and an <a> on the client, and Vue bails out of hydrating a subtree whose
93
+ node type disagrees — leaving the server markup in place and never
94
+ mounting the component, so onMounted never ran and the bar was silently
95
+ dead. The skeleton is what both sides render before the fetch resolves.
96
+ -->
89
97
  <a
90
- v-if="loaded && level"
91
98
  :href="destination"
92
99
  class="mg-xp-bar"
93
- :class="{ 'mg-xp-bar--compact': props.compact }"
100
+ :class="{
101
+ 'mg-xp-bar--compact': props.compact,
102
+ 'mg-xp-bar--empty': loaded && !level,
103
+ }"
94
104
  @click="emit('navigate')"
95
105
  >
106
+ <template v-if="level">
96
107
  <div class="mg-xp-bar__top">
97
108
  <span class="mg-xp-bar__badge">{{ level.current_level }}</span>
98
109
 
@@ -111,6 +122,17 @@ onMounted(async () => {
111
122
  <div class="mg-xp-bar__track">
112
123
  <div class="mg-xp-bar__fill" :style="{ width: percent + '%' }" />
113
124
  </div>
125
+ </template>
126
+
127
+ <template v-else>
128
+ <div class="mg-xp-bar__top">
129
+ <span class="mg-xp-bar__badge mg-xp-bar__skeleton" />
130
+ <div class="mg-xp-bar__meta">
131
+ <span class="mg-xp-bar__skeleton mg-xp-bar__skeleton--line" />
132
+ </div>
133
+ </div>
134
+ <div class="mg-xp-bar__track" />
135
+ </template>
114
136
  </a>
115
137
  </template>
116
138
 
@@ -232,6 +254,22 @@ onMounted(async () => {
232
254
  transition: width 0.3s ease;
233
255
  }
234
256
 
257
+ // Hidden only after the fetch resolves with nothing — a client-side change
258
+ // that happens well after hydration, so it cannot cause a mismatch.
259
+ &--empty {
260
+ display: none;
261
+ }
262
+
263
+ &__skeleton {
264
+ background: rgba(128, 128, 128, 0.25);
265
+ border-color: transparent;
266
+
267
+ &--line {
268
+ height: 9px;
269
+ width: 70%;
270
+ }
271
+ }
272
+
235
273
  &--compact {
236
274
  padding: 0.35rem 0.5rem;
237
275
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mundogamernetwork/shared-ui",
3
- "version": "1.13.2",
3
+ "version": "1.13.3",
4
4
  "description": "Mundo Gamer Network - Shared UI Layer (Nuxt 3)",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",