@celestia-island/hikari 0.55.34 → 0.55.35

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.34",
3
+ "version": "0.55.35",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Hikari Vue 3 component library — production-grade UI components based on shittim-chest design system",
@@ -452,6 +452,22 @@
452
452
  }
453
453
 
454
454
  .hk-modal-content {
455
+ // IME cap-chase guard (2026-09-21, Xiaomi WebView chest report): on
456
+ // adjustResize engines the keyboard animation steps the layout
457
+ // viewport — and with it the 100dvh term of the max-height cap —
458
+ // every frame. With max-height in the base transition list each step
459
+ // RETARGETS a 150ms transition, so a sheet that binds the cap (tall
460
+ // content: multi-step wizards, model pickers) stays permanently
461
+ // mid-transition: the box chases the viewport, layout stays dirty,
462
+ // and the fixed layer re-rasters per step (black-block flicker).
463
+ // Short sheets never bind the cap and never noticed. The cap now
464
+ // follows the viewport INSTANTLY on phones — which is exactly how
465
+ // native iOS/Android sheets track the keyboard — while the height
466
+ // pin (content-driven, one-shot per morph) and the clip reveal
467
+ // keep their transition. Desktop keeps the full list.
468
+ transition:
469
+ height var(--duration-fast, 0.15s) var(--ease-standard, cubic-bezier(0.4, 0, 0.2, 1)),
470
+ clip-path var(--duration-fast, 0.15s) var(--ease-standard, cubic-bezier(0.4, 0, 0.2, 1));
455
471
  // !important beats the inline maxWidth (width prop); base width: 100%
456
472
  // already applies at every viewport, so only the cap is re-asserted.
457
473
  max-width: 100% !important;
@@ -74,6 +74,39 @@ describe("HkModal mobile sheet spacing contract", () => {
74
74
  expect(content).not.toMatch(/max-height:\s*none/);
75
75
  });
76
76
 
77
+ // 2026-09-21 IME cap-chase guard (Xiaomi WebView chest report): the
78
+ // keyboard animation steps the layout viewport — and the 100dvh term
79
+ // of the cap — every frame; with max-height in the transition list
80
+ // each step RETARGETS a 150ms transition and a cap-bound (tall)
81
+ // sheet chases its own viewport, re-rastering per step (black-block
82
+ // flicker). The phone sheet's transition list must therefore carry
83
+ // ONLY the content-driven channels: the height pin (one-shot per
84
+ // morph) and the clip reveal. The cap itself follows the viewport
85
+ // instantly — native sheet behavior.
86
+ it("drops max-height from the phone sheet transition (IME cap-chase guard)", () => {
87
+ // Extraction self-check: the mobile rule must exist and MUST carry
88
+ // a transition declaration at all (its absence is the regression,
89
+ // not a vacuous pass).
90
+ expect(content.length, "mobile .hk-modal-content rule extracted").toBeGreaterThan(0);
91
+ const tr = content.match(/transition:\s*([^;]+);/)?.[1] ?? "";
92
+ expect(tr.length, "mobile sheet transition declaration present").toBeGreaterThan(0);
93
+ expect(tr).toMatch(/\bheight\b/);
94
+ expect(tr).toMatch(/\bclip-path\b/);
95
+ expect(tr).not.toMatch(/\bmax-height\b/);
96
+ });
97
+
98
+ it("keeps the desktop frame transition list intact (base rule)", () => {
99
+ // The guard is phone-only by design: the base rule outside the
100
+ // media block keeps height+max-height+clip-path animated.
101
+ const base = src.match(/\.hk-modal-content\s*{[^}]*}/)?.[0] ?? "";
102
+ expect(base.length, "base .hk-modal-content rule extracted").toBeGreaterThan(0);
103
+ const tr = base.match(/transition:\s*([^;]+);/)?.[1] ?? "";
104
+ expect(tr.length, "base transition declaration present").toBeGreaterThan(0);
105
+ expect(tr).toMatch(/\bheight\b/);
106
+ expect(tr).toMatch(/\bmax-height\b/);
107
+ expect(tr).toMatch(/\bclip-path\b/);
108
+ });
109
+
77
110
  it("lifts the 70vh body cap on phones so the footer sits on the bottom edge", () => {
78
111
  expect(body).toContain("max-height: none");
79
112
  });