@celestia-island/hikari 0.55.343 → 0.55.344

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.343",
3
+ "version": "0.55.344",
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",
@@ -1,7 +1,8 @@
1
1
  import HkIconButton from "./HkIconButton";
2
+ import HkAddTile from "./HkAddTile";
2
3
 
3
4
  import { computed, defineComponent, onUnmounted, ref, watch, type PropType } from "vue";
4
- import { Monitor, MoonStar, Palette, Sun, Trash as Trash2 } from "lucide-vue-next";
5
+ import { Monitor, MoonStar, Sun, Trash as Trash2 } from "lucide-vue-next";
5
6
  import {
6
7
  HDivider,
7
8
  solarAltitude,
@@ -309,9 +310,18 @@ export const HkThemePanelContent = defineComponent({
309
310
  );
310
311
  })}
311
312
 
312
- <button
313
- type="button"
314
- class="s-theme-item-btn s-theme-item-customize"
313
+ {/* The customize entry is the standard add tile (2026-11-11
314
+ family migration): the compact dashed form riding the END of
315
+ the theme list — the same "add one more" gesture semantics
316
+ as every other list-end affordance, so hosts stop
317
+ hand-painting it (chest's centered dashed hand-roll retires
318
+ with this). The s-theme-item-customize class stays as the
319
+ host hook (host scopes and tests target it); the default
320
+ Plus glyph replaces the palette mark — creating a scheme is
321
+ an add gesture. */}
322
+ <HkAddTile
323
+ compact
324
+ class="s-theme-item-customize"
315
325
  onClick={() => {
316
326
  if (props.externalCustomize) {
317
327
  emit("request-close");
@@ -321,9 +331,8 @@ export const HkThemePanelContent = defineComponent({
321
331
  }
322
332
  }}
323
333
  >
324
- <span class="hk-menu-item-icon"><Palette size={14} /></span>
325
- <span class="s-theme-item-name">{t("hikari::theme.customize")}</span>
326
- </button>
334
+ {t("hikari::theme.customize")}
335
+ </HkAddTile>
327
336
  </div>
328
337
  {(() => {
329
338
  const extra = slots["menu-extra"]?.() ?? [];
@@ -9,13 +9,15 @@
9
9
  *
10
10
  * The widened cell must stay scoped (2026-09-12 field report): shipped
11
11
  * first as a bare `.s-theme-item-btn .hk-menu-item-icon` rule, it also
12
- * matched the 自定义 row and every host row reusing s-theme-item-btn —
13
- * and mi.icon normalizes those cells' svg to the cell, so their 14px
14
- * glyphs rendered 28px wide. The widening therefore targets named scopes
15
- * (lead slot, customize row) plus the toggle-owned mode-extra strip, the
16
- * last one widening the CELL while pinning the glyph back to the
17
- * standard box so host strip rows (chest's DPI entry) align their labels
18
- * with the theme rows' names without rescaling their icons.
12
+ * matched every host row reusing s-theme-item-btn — and mi.icon
13
+ * normalizes those cells' svg to the cell, so their 14px glyphs rendered
14
+ * 28px wide. The widening therefore targets named scopes (lead slot)
15
+ * plus the toggle-owned mode-extra strip, the last one widening the CELL
16
+ * while pinning the glyph back to the standard box so host strip rows
17
+ * (chest's DPI entry) align their labels with the theme rows' names
18
+ * without rescaling their icons. (The customize row left this contract
19
+ * 2026-11-11: the entry is the standard HkAddTile compact form now — a
20
+ * self-contained dashed tile, not a lead-column row.)
19
21
  */
20
22
  import { describe, expect, it } from "vitest";
21
23
  import { readFileSync } from "node:fs";
@@ -105,30 +107,27 @@ describe("HkThemeToggle row lead-cell contract", () => {
105
107
 
106
108
  it("does not widen icon cells with a bare unscoped theme-row rule", () => {
107
109
  const css = read("HkThemeToggle.scss");
108
- // A bare `.s-theme-item-btn .hk-menu-item-icon {` rule also hits the
109
- // customize row and host mode-extra rows; the widened cell may only
110
- // target named scopes (lead slot, customize row, mode-extra strip).
110
+ // A bare `.s-theme-item-btn .hk-menu-item-icon {` rule also hits
111
+ // host mode-extra rows; the widened cell may only target named
112
+ // scopes (lead slot, mode-extra strip).
111
113
  expect(css).not.toMatch(/^\.s-theme-item-btn \.hk-menu-item-icon\s*\{/m);
112
114
  });
113
115
 
114
- it("aligns the customize row to the lead column without rescaling its glyph", () => {
116
+ it("renders the customize entry as the standard HkAddTile compact form", () => {
117
+ // 2026-11-11 family migration: the entry rides the standard dashed
118
+ // add tile below the theme list (same "add one more" semantics as
119
+ // every other list-end affordance) instead of a lead-aligned menu
120
+ // row — the old .hk-menu-item-icon lead-column alignment rules are
121
+ // retired with the markup that needed them.
122
+ const panel = read("HkThemePanelContent.tsx");
123
+ const entry = panel.match(/<HkAddTile[\s\S]*?s-theme-item-customize[\s\S]*?>[\s\S]*?<\/HkAddTile>/);
124
+ expect(entry).not.toBeNull();
125
+ expect(entry![0]).toContain("compact");
126
+ expect(entry![0]).not.toContain("hk-menu-item-icon");
127
+ // The toggle's own sheet carries no customize-specific icon cell
128
+ // rules anymore (the alignment contract retired with the row).
115
129
  const css = read("HkThemeToggle.scss");
116
- // The customize affordance joins the 28px lead column (2026-09-11
117
- // field report: its palette sat a full cell left of the rows' bitmap
118
- // marks), but the glyph must keep the standard menu icon size —
119
- // mi.icon normalizes svg to the cell, so the box is pinned back.
120
- const block = css.match(
121
- /\.s-theme-item-customize \.hk-menu-item-icon\s*\{[^}]*\}/,
122
- );
123
- expect(block).not.toBeNull();
124
- expect(block![0]).toContain("width: 28px");
125
- expect(block![0]).toContain("height: 28px");
126
-
127
- const svgBlock = css.match(
128
- /\.s-theme-item-customize \.hk-menu-item-icon > svg\s*\{[^}]*\}/,
129
- );
130
- expect(svgBlock).not.toBeNull();
131
- expect(svgBlock![0]).toContain("var(--hk-menu-item-icon-box)");
130
+ expect(css).not.toMatch(/\.s-theme-item-customize \.hk-menu-item-icon/);
132
131
  });
133
132
 
134
133
  it("aligns mode-extra host rows to the lead column without rescaling their glyph", () => {
@@ -288,24 +288,13 @@
288
288
  height: 28px;
289
289
  }
290
290
 
291
- /* The customize affordance joins the theme rows' 28px lead column so the
292
- * palette glyph and the row marks sit on one line and every name starts
293
- * at the same x (2026-09-11 field report: with the lead cell at 28px and
294
- * this row at the generic box, the selected theme's bitmap mark read a
295
- * full cell to the right of the customize palette). The cell widens but
296
- * the GLYPH keeps the standard menu icon size — mi.icon normalizes svg
297
- * to the cell, so the box is pinned back explicitly; widening a cell
298
- * must never re-scale its glyph (the 0.42.2 regression class). */
299
- .s-theme-item-customize .hk-menu-item-icon {
300
- @include mi.icon;
301
-
302
- width: 28px;
303
- height: 28px;
304
- }
291
+ /* (The customize row's lead-column alignment rules retired 2026-11-11:
292
+ * the entry itself is the standard HkAddTile compact form now — a
293
+ * self-contained dashed tile below the list, not a row in the lead
294
+ * column — so it carries no .hk-menu-item-icon cell to widen.) */
305
295
 
306
- .s-theme-item-customize .hk-menu-item-icon > svg {
307
- width: var(--hk-menu-item-icon-box);
308
- height: var(--hk-menu-item-icon-box);
296
+ .s-theme-item-customize {
297
+ margin-top: var(--space-8, 0.5rem);
309
298
  }
310
299
 
311
300
  /* Host rows in the mode-extra strip (chest's DPI entry row reuses
@@ -314,9 +303,9 @@
314
303
  * (2026-09-12 field report: with the strip row at the generic 16px cell
315
304
  * its label sat a full cell-width left of the theme rows' names). The
316
305
  * strip container is the toggle's own, so the scope needs no host
317
- * class-name contract. As with the customize row, the cell widens but
318
- * the GLYPH keeps the standard menu icon size — widening a cell must
319
- * never re-scale its glyph (the 0.42.2 regression class). */
306
+ * class-name contract. The cell widens but the GLYPH keeps the standard
307
+ * menu icon size — widening a cell must never re-scale its glyph (the
308
+ * 0.42.2 regression class). */
320
309
  .s-theme-mode-extra .s-theme-item-btn .hk-menu-item-icon {
321
310
  @include mi.icon;
322
311
 
@@ -75,8 +75,11 @@ function triggerButton(container: HTMLElement): HTMLButtonElement {
75
75
  }
76
76
 
77
77
  function paletteButton(): HTMLButtonElement {
78
- const btn = [...document.body.querySelectorAll<HTMLButtonElement>(".s-theme-menu .s-theme-item-btn")].find(
79
- (b) => b.textContent?.includes("Customize"),
78
+ // The entry rides the standard HkAddTile (2026-11-11 family migration)
79
+ // and no longer carries s-theme-item-btn — the stable host hook class
80
+ // is the query surface.
81
+ const btn = document.body.querySelector<HTMLButtonElement>(
82
+ ".s-theme-menu .s-theme-item-customize",
80
83
  );
81
84
  return btn!;
82
85
  }