@celestia-island/hikari 0.55.307 → 0.55.308

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": "@celestia-island/hikari",
3
- "version": "0.55.307",
3
+ "version": "0.55.308",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Hikari UI library, Vue 3 runtime — one design system for Vue 3 and Rust/WASM applications",
@@ -332,7 +332,14 @@ export default defineComponent({
332
332
  // finding). Riding the block keeps the scrollport's content
333
333
  // untransformed; the block's own poke below the frame lands
334
334
  // off-screen on a bottom-docked sheet.
335
- if (bodyRef.value) out.push({ el: bodyRef.value });
335
+ // While the desktop height ride owns the body's paint (its scaleY
336
+ // IS the choreography), the morph must not write an inline transform
337
+ // on the same element: an inline style outranks the ride's class
338
+ // rule, and the close would stop compressing (2026-11-07 user
339
+ // report: the window folded "together with the chrome"). The body
340
+ // ride matters for the ≤767px sheet sweep, where the ride geometry
341
+ // is disabled — so the two never legitimately overlap.
342
+ if (bodyRef.value && rideStateClass() === null) out.push({ el: bodyRef.value });
336
343
  return out;
337
344
  },
338
345
  // Republish the morph's real sweep span and its landing on the body
@@ -1126,6 +1133,7 @@ export default defineComponent({
1126
1133
  <div
1127
1134
  ref={contentRef}
1128
1135
  class={["hk-modal-content", "hk-ride", rideStateClass(), props.contentClass, ...machine.classesFor("hk-modal-content")]}
1136
+ data-hk-ride-ready={ride.hasCache() ? "" : undefined}
1129
1137
  role="dialog"
1130
1138
  aria-modal="true"
1131
1139
  aria-label={resolvedSurfaceName.value}
@@ -1133,6 +1141,8 @@ export default defineComponent({
1133
1141
  style={{
1134
1142
  maxWidth: resolvedWidth.value,
1135
1143
  zIndex: contentZ.value,
1144
+ ...ride.styleVars(),
1145
+
1136
1146
  }}
1137
1147
  onClick={onContentClick}
1138
1148
  tabindex={-1}
@@ -76,6 +76,11 @@
76
76
  height: var(--hk-ride-content, auto);
77
77
  }
78
78
 
79
+ .hk-ride[data-hk-ride-ready].hk-ride--from > .hk-ride-chrome-start,
80
+ .hk-ride[data-hk-ride-ready].hk-ride--to > .hk-ride-chrome-start {
81
+ flex-shrink: 0;
82
+ }
83
+
79
84
  .hk-ride[data-hk-ride-ready].hk-ride--from > .hk-ride-chrome-end,
80
85
  .hk-ride[data-hk-ride-ready].hk-ride--to > .hk-ride-chrome-end {
81
86
  position: absolute;
@@ -70,6 +70,14 @@ export interface HeightRide {
70
70
  * ride needs); calling it mid-ride re-measures the live, compressed
71
71
  * box and is therefore a no-op unless `force` is passed. */
72
72
  refresh(force?: boolean): boolean;
73
+ /** Inline style vars for the CURRENT cache, or null when nothing has
74
+ * been measured yet. Consumers bind this in their render so the very
75
+ * first painted frame of a remount already carries the ride (a post-
76
+ * mount publish is one paint too late: the enter-from frame would show
77
+ * a full-height frame with unscaled content — read as "clipping"). */
78
+ styleVars(): Record<string, string> | null;
79
+ /** True when a measured split exists (drives the ready attribute). */
80
+ hasCache(): boolean;
73
81
  /** Re-apply the LAST measured split without touching the DOM boxes.
74
82
  * A surface that unmounts its frame on close loses the inline variables
75
83
  * with it; republishing on the next mount is what makes the very first
@@ -138,15 +146,12 @@ export function useHeightRide(
138
146
  if (child === c || !(child instanceof HTMLElement)) continue;
139
147
  chromeNatural += child.offsetHeight;
140
148
  }
141
- // At rest the frame is at (or pinned to) its natural height, so the
142
- // content region's natural height is the honest difference there; mid
143
- // flight only the content's own box is trustworthy (the frame is short
144
- // by design). Both branches are frame-height independent when it
145
- // matters — a compressed frame never feeds the next ride.
146
- const contentNatural = isInFlight(f)
147
- ? c.offsetHeight
148
- : Math.max(0, f.offsetHeight - chromeNatural);
149
- const measured = contentNatural > 0 ? contentNatural : c.offsetHeight;
149
+ // The content region's own layout box is the ONLY honest source. With
150
+ // no ride class the body is flex-natural; while a ride class is present
151
+ // the box is locked to the published var (stable, no new information —
152
+ // and the frame's height is the ride's own output, so deriving the
153
+ // content from it would feed every early error forward forever).
154
+ const measured = c.offsetHeight;
150
155
  if (measured <= 0) return false;
151
156
  contentH = measured;
152
157
  chrome = chromeNatural;
@@ -172,8 +177,19 @@ export function useHeightRide(
172
177
  return true;
173
178
  };
174
179
 
180
+ const styleVars = (): Record<string, string> | null =>
181
+ contentH <= 0
182
+ ? null
183
+ : {
184
+ "--hk-ride-chrome": `${chrome}px`,
185
+ "--hk-ride-content": `${contentH}px`,
186
+ "--hk-ride-factor": String(factorOf()),
187
+ };
188
+
175
189
  return {
176
190
  refresh,
191
+ styleVars,
192
+ hasCache: () => contentH > 0,
177
193
  publish,
178
194
  chromeHeight: () => chrome,
179
195
  contentHeight: () => contentH,