@celestia-island/hikari 0.40.27 → 0.40.29

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.40.27",
3
+ "version": "0.40.29",
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",
@@ -103,3 +103,20 @@ registerCssAnimation("s-voice-wave-bounce", { infinite: true });
103
103
  // components/HkPlaceholderMarquee.scss — overflowing placeholder sweep
104
104
  // (loops forever; pure CSS, loop geometry on inline custom properties).
105
105
  registerCssAnimation("hk-placeholder-marquee-scroll", { infinite: true });
106
+ // styles/theme/mixins.scss — ambient/glow pulses (loop forever) and the
107
+ // one-shot entrance/exit grammar, vendored byte-identical from
108
+ // packages/theme. #353 brought the file under src/ without registering
109
+ // its keyframes — the parity test caught the gap 6 days later.
110
+ registerCssAnimation("pulse", { infinite: true });
111
+ registerCssAnimation("ambient-move", { infinite: true });
112
+ registerCssAnimation("pulse-glow-animation", { infinite: true });
113
+ registerCssAnimation("expand-horizontal");
114
+ registerCssAnimation("collapse-vertical");
115
+ registerCssAnimation("slide-in-left");
116
+ registerCssAnimation("slide-in-right");
117
+ registerCssAnimation("slide-in-top");
118
+ registerCssAnimation("slide-in-bottom");
119
+ registerCssAnimation("fade-in-scale");
120
+ registerCssAnimation("fade-out-scale");
121
+ registerCssAnimation("blur-in");
122
+ registerCssAnimation("bounce-in");
@@ -281,7 +281,6 @@ describe("HkAffixPicker", () => {
281
281
  .find((b) => !b.classList.contains("hk-message-box-confirm"))!
282
282
  .click();
283
283
  await flush();
284
- console.log("DBG-cancel openEvents", JSON.stringify(events.open), "tags", tags().length, "box", !!document.body.querySelector(".hk-message-box-text"));
285
284
  expect(events.remove).toHaveLength(0);
286
285
  expect(tag("China")).toBeTruthy();
287
286
  // Second pass: the dialog's Confirm is what erases.
@@ -136,6 +136,18 @@
136
136
  color: var(--hi-color-text-primary);
137
137
  }
138
138
 
139
+ /* Mobile sheet context (#424 centered-cap pattern): the calendar keeps its
140
+ * designed measure inside the viewport-wide sheet instead of left-gluing
141
+ * at the anchored popover's min-width. Safe to stretch: the stage pins
142
+ * only its height (HkPickerPane.scss) and the day/month grids use 1fr
143
+ * tracks, so nothing fixed fights width: 100%. */
144
+ .hk-popover-panel.hk-is-sheet .hk-dp-panel {
145
+ min-width: 0;
146
+ max-width: min(22rem, 100%);
147
+ margin-inline: auto;
148
+ width: 100%;
149
+ }
150
+
139
151
  .hk-dp-header {
140
152
  display: grid;
141
153
  grid-template-columns: 1fr auto 1fr;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Source contract for the date/datetime picker mobile sheet docking
3
+ * (2026-09-08 mobile audit deferred item, family contract completion):
4
+ * HkDatePicker and HkDateTimePicker were the last anchored surfaces that
5
+ * never docked as bottom sheets on phones — on non-native touch hosts
6
+ * (nativeOnMobile=false) their calendars opened as tiny trigger-anchored
7
+ * popovers while every other popover-family window docked. Both pickers
8
+ * must pass sheetOnMobile to HPopover (the native path returns before the
9
+ * popover renders, so this is inherently non-native-touch-only) and cap
10
+ * their panels with the #424 centered-cap pattern inside the sheet.
11
+ */
12
+ import { describe, expect, it } from "vitest";
13
+ import { readFileSync } from "node:fs";
14
+ import { dirname, join } from "node:path";
15
+ import { fileURLToPath } from "node:url";
16
+
17
+ const here = dirname(fileURLToPath(import.meta.url));
18
+ const read = (name: string) => readFileSync(join(here, name), "utf-8");
19
+ /* Fixed window from the opening tag — a non-greedy `[\s\S]*?>` would stop
20
+ * at the `=>` inside the onUpdate prop's inline arrow. */
21
+ const popoverTag = (src: string) => {
22
+ const at = src.indexOf("<HPopover");
23
+ return at < 0 ? "" : src.slice(at, at + 700);
24
+ };
25
+
26
+ describe("date picker mobile sheet family contract", () => {
27
+ it("HkDatePicker opts its calendar popover into mobile sheet docking", () => {
28
+ const popover = popoverTag(read("HkDatePicker.tsx"));
29
+ expect(popover).toContain("sheetOnMobile");
30
+ });
31
+
32
+ it("HkDateTimePicker opts its popup popover into mobile sheet docking", () => {
33
+ const popover = popoverTag(read("HkDateTimePicker.tsx"));
34
+ expect(popover).toContain("sheetOnMobile");
35
+ });
36
+
37
+ it("HkDatePicker caps the calendar panel with the #424 centered-cap pattern", () => {
38
+ const src = read("HkDatePicker.scss");
39
+ const block = src.match(/\.hk-popover-panel\.hk-is-sheet \.hk-dp-panel\s*\{[^}]*\}/)?.[0] ?? "";
40
+ expect(block).toContain("min-width: 0");
41
+ expect(block).toContain("max-width: min(22rem, 100%)");
42
+ expect(block).toContain("margin-inline: auto");
43
+ expect(block).toContain("width: 100%");
44
+ });
45
+
46
+ it("HkDateTimePicker caps the popup panel and lifts the body floor in the sheet", () => {
47
+ const src = read("HkDateTimePicker.scss");
48
+ const popup = src.match(/\.hk-popover-panel\.hk-is-sheet \.hk-dtp-popup\s*\{[^}]*\}/)?.[0] ?? "";
49
+ expect(popup).toContain("min-width: 0");
50
+ expect(popup).toContain("max-width: min(22rem, 100%)");
51
+ expect(popup).toContain("margin-inline: auto");
52
+ expect(popup).toContain("width: 100%");
53
+ const body = src.match(/\.hk-popover-panel\.hk-is-sheet \.hk-dtp\s*\{[^}]*\}/)?.[0] ?? "";
54
+ expect(body).toContain("min-width: 0");
55
+ });
56
+ });
@@ -539,6 +539,10 @@ export default defineComponent({
539
539
  placement="bottom-start"
540
540
  offset={6}
541
541
  backdrop={false}
542
+ sheetOnMobile
543
+ // The calendar docks as a bottom sheet on non-native touch
544
+ // hosts (nativeOnMobile=false); the native path returns
545
+ // before this popover ever renders.
542
546
  title={t("hikari::datePicker.pickDate")}
543
547
  class="hk-dp-popover"
544
548
  >
@@ -331,6 +331,23 @@
331
331
  min-width: 260px;
332
332
  }
333
333
 
334
+ /* Mobile sheet context (#424 centered-cap pattern): the popup wrapper is
335
+ * the sheet's direct content child, so it takes the centered cap; the
336
+ * .hk-dtp body root already fills via width: 100% and only needs its
337
+ * 17.5rem floor lifted so narrow sheets never overflow. The stage pins
338
+ * height only (HkPickerPane.scss) and the grids use 1fr tracks, so
339
+ * stretching fights no fixed geometry. */
340
+ .hk-popover-panel.hk-is-sheet .hk-dtp-popup {
341
+ min-width: 0;
342
+ max-width: min(22rem, 100%);
343
+ margin-inline: auto;
344
+ width: 100%;
345
+ }
346
+
347
+ .hk-popover-panel.hk-is-sheet .hk-dtp {
348
+ min-width: 0;
349
+ }
350
+
334
351
  .hk-dtp-popup-foot {
335
352
  display: flex;
336
353
  justify-content: flex-end;
@@ -578,6 +578,10 @@ export default defineComponent({
578
578
  anchorRef={triggerWrapRef.value ?? null}
579
579
  placement={props.placement}
580
580
  offset={props.offset}
581
+ sheetOnMobile
582
+ // The popup docks as a bottom sheet on non-native touch hosts
583
+ // (nativeOnMobile=false); the native path returns before this
584
+ // popover ever renders.
581
585
  title={t("hikari::dateTimePicker.pickDate")}
582
586
  >
583
587
  <div class="hk-dtp-popup">