@celestia-island/hikari 0.55.77 → 0.55.78
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 +1 -1
- package/src/components/HkFilterBar.scss +59 -0
- package/src/components/HkFilterBar.test.tsx +130 -0
- package/src/components/HkFilterBar.tsx +143 -0
- package/src/components/HkGaugeRing.tsx +13 -1
- package/src/components/HkSelectionGrid.scss +91 -0
- package/src/components/HkSelectionGrid.test.tsx +68 -0
- package/src/components/HkSelectionGrid.tsx +56 -1
- package/src/components/HkSettingsDialog.scss +12 -1
- package/src/components/HkStatCard.scss +107 -0
- package/src/components/HkStatCard.tsx +173 -21
- package/src/components/HkStatCard.variants.test.tsx +210 -0
- package/src/components/HkStepGuide.scss +177 -0
- package/src/components/HkStepGuide.test.tsx +81 -0
- package/src/components/HkStepGuide.tsx +129 -0
- package/src/i18n/locales/ar/components.json +4 -1
- package/src/i18n/locales/de/components.json +4 -1
- package/src/i18n/locales/en/components.json +4 -1
- package/src/i18n/locales/es/components.json +4 -1
- package/src/i18n/locales/fr/components.json +4 -1
- package/src/i18n/locales/ja/components.json +4 -1
- package/src/i18n/locales/ko/components.json +4 -1
- package/src/i18n/locales/pt/components.json +4 -1
- package/src/i18n/locales/ru/components.json +4 -1
- package/src/i18n/locales/zh-Hans/components.json +4 -1
- package/src/i18n/locales/zh-Hant/components.json +4 -1
- package/src/index.ts +6 -1
- package/src/styles/admin-tokens.scss +21 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// HkStepGuide — the big-artwork illustrated step cards.
|
|
2
|
+
//
|
|
3
|
+
// Grammar (wowsp's 待命 walkthrough, user direction 2026-09-25): every
|
|
4
|
+
// step is a rounded SURFACE card. The artwork — stroke SVG, icon, or
|
|
5
|
+
// bitmap — is drawn LARGE and bare on the card face (no frame, no bed);
|
|
6
|
+
// the ordinal is a solid primary disc pinned to the card's outer
|
|
7
|
+
// top corner, half outside it; the title and one-line description sit
|
|
8
|
+
// left-aligned under the art. Completed steps swap the ordinal for a
|
|
9
|
+
// check and pick up a success edge, letting the guide double as a
|
|
10
|
+
// checklist while the flow progresses.
|
|
11
|
+
//
|
|
12
|
+
// Orientation follows the guide's OWN width (it is a container-query
|
|
13
|
+
// root): wide → cards sit side by side with a chevron bridging
|
|
14
|
+
// consecutive steps; narrow → they stack full-width. Fixed 520px
|
|
15
|
+
// breakpoint: container-query conditions cannot carry var(), so
|
|
16
|
+
// per-host thresholds would need a prop.
|
|
17
|
+
|
|
18
|
+
.hk-step-guide {
|
|
19
|
+
container-type: inline-size;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.hk-step-guide-title {
|
|
23
|
+
font-size: 0.6875rem;
|
|
24
|
+
font-weight: 600;
|
|
25
|
+
text-transform: uppercase;
|
|
26
|
+
letter-spacing: 0.05em;
|
|
27
|
+
color: var(--hi-color-text-tertiary, #8b949e);
|
|
28
|
+
margin: 0 0 var(--space-12, 0.75rem);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.hk-step-guide-list {
|
|
32
|
+
list-style: none;
|
|
33
|
+
margin: 0;
|
|
34
|
+
padding: 0;
|
|
35
|
+
// Headroom so the corner-pinned ordinals never crowd the section label.
|
|
36
|
+
padding-block-start: var(--space-10, 0.625rem);
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-direction: column;
|
|
39
|
+
gap: var(--space-20, 1.25rem);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ── the card ────────────────────────────────────────────────────────────────
|
|
43
|
+
.hk-step-guide-item {
|
|
44
|
+
position: relative;
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
align-items: flex-start;
|
|
48
|
+
gap: var(--space-10, 0.625rem);
|
|
49
|
+
padding: var(--space-20, 1.25rem);
|
|
50
|
+
padding-block-start: calc(var(--space-20, 1.25rem) + var(--space-2, 0.125rem));
|
|
51
|
+
border-radius: var(--radius-lg, 1rem);
|
|
52
|
+
background: var(--hi-color-surface, #f0f4f8);
|
|
53
|
+
|
|
54
|
+
&[data-done] {
|
|
55
|
+
box-shadow: inset 0 0 0 1px rgb(from var(--hi-color-success, #0eb840) r g b / 0.55);
|
|
56
|
+
|
|
57
|
+
.hk-step-guide-ordinal {
|
|
58
|
+
background: var(--hi-color-success, #0eb840);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.hk-step-guide-art {
|
|
62
|
+
opacity: 0.45;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ── the ordinal, pinned to the card's outer corner ──────────────────────────
|
|
68
|
+
.hk-step-guide-ordinal {
|
|
69
|
+
position: absolute;
|
|
70
|
+
top: calc(var(--space-10, 0.625rem) * -1);
|
|
71
|
+
inset-inline-start: calc(var(--space-10, 0.625rem) * -1);
|
|
72
|
+
width: var(--space-24, 1.5rem);
|
|
73
|
+
height: var(--space-24, 1.5rem);
|
|
74
|
+
border-radius: 50%;
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
justify-content: center;
|
|
78
|
+
background: var(--hi-color-primary, #7aa2f7);
|
|
79
|
+
color: rgb(var(--color-on-solid-icon, 255 255 255));
|
|
80
|
+
font-size: var(--text-xs, 0.75rem);
|
|
81
|
+
font-weight: 700;
|
|
82
|
+
font-variant-numeric: tabular-nums;
|
|
83
|
+
box-sizing: border-box;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.hk-step-guide-check {
|
|
87
|
+
width: 62%;
|
|
88
|
+
height: 62%;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ── the artwork, large and bare on the card face ────────────────────────────
|
|
92
|
+
.hk-step-guide-art {
|
|
93
|
+
width: 100%;
|
|
94
|
+
height: var(--hk-step-guide-art-height, 128px);
|
|
95
|
+
display: flex;
|
|
96
|
+
align-items: center;
|
|
97
|
+
justify-content: flex-start;
|
|
98
|
+
color: var(--hi-color-primary, #7aa2f7);
|
|
99
|
+
transition: opacity 200ms ease;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.hk-step-guide-art-svg {
|
|
103
|
+
width: 68%;
|
|
104
|
+
height: 100%;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.hk-step-guide-art-img {
|
|
108
|
+
width: 100%;
|
|
109
|
+
height: 100%;
|
|
110
|
+
object-fit: cover;
|
|
111
|
+
border-radius: calc(var(--radius-lg, 1rem) - var(--space-6, 0.375rem));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ── the caption ─────────────────────────────────────────────────────────────
|
|
115
|
+
.hk-step-guide-body {
|
|
116
|
+
display: flex;
|
|
117
|
+
flex-direction: column;
|
|
118
|
+
gap: var(--space-2, 0.125rem);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.hk-step-guide-item-title {
|
|
122
|
+
font-size: var(--text-base, 0.9375rem);
|
|
123
|
+
font-weight: 600;
|
|
124
|
+
line-height: 1.4;
|
|
125
|
+
color: var(--hi-color-text-primary, #1e1e1e);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.hk-step-guide-item-desc {
|
|
129
|
+
font-size: var(--text-sm, 0.8125rem);
|
|
130
|
+
line-height: 1.55;
|
|
131
|
+
color: var(--hi-color-text-tertiary, #8b949e);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ── wide host: the cards lie side by side, chevron between ──────────────────
|
|
135
|
+
@container (min-width: 520px) {
|
|
136
|
+
.hk-step-guide-list {
|
|
137
|
+
flex-direction: row;
|
|
138
|
+
align-items: stretch;
|
|
139
|
+
gap: var(--space-24, 1.5rem);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.hk-step-guide-item {
|
|
143
|
+
flex: 1 1 0;
|
|
144
|
+
min-width: 0;
|
|
145
|
+
|
|
146
|
+
// A chevron centered in the gap, pointing at the next card.
|
|
147
|
+
&:not(:last-child)::after {
|
|
148
|
+
content: "";
|
|
149
|
+
position: absolute;
|
|
150
|
+
top: 50%;
|
|
151
|
+
inset-inline-end: calc(var(--space-24, 1.5rem) * -1 + var(--space-2, 0.125rem));
|
|
152
|
+
width: 9px;
|
|
153
|
+
height: 9px;
|
|
154
|
+
border-inline-end: 2px solid var(--hi-color-text-tertiary, #8b949e);
|
|
155
|
+
border-block-end: 2px solid var(--hi-color-text-tertiary, #8b949e);
|
|
156
|
+
transform: translateY(-50%) rotate(-45deg);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ── grid layout: auto-fill cards ────────────────────────────────────────────
|
|
162
|
+
.hk-step-guide[data-layout="grid"] {
|
|
163
|
+
.hk-step-guide-list {
|
|
164
|
+
display: grid;
|
|
165
|
+
grid-template-columns: repeat(
|
|
166
|
+
auto-fill,
|
|
167
|
+
minmax(min(var(--hk-step-guide-card-min, 200px), 100%), 1fr)
|
|
168
|
+
);
|
|
169
|
+
gap: var(--space-20, 1.25rem);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@media (prefers-reduced-motion: reduce) {
|
|
174
|
+
.hk-step-guide-art {
|
|
175
|
+
transition: none;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { createApp, defineComponent, h } from "vue";
|
|
3
|
+
|
|
4
|
+
import HkStepGuide, { type StepGuideItem } from "./HkStepGuide";
|
|
5
|
+
|
|
6
|
+
const mounts: Array<{ app: ReturnType<typeof createApp>; container: HTMLElement }> = [];
|
|
7
|
+
|
|
8
|
+
function mount(node: ReturnType<typeof h>) {
|
|
9
|
+
const container = document.createElement("div");
|
|
10
|
+
document.body.appendChild(container);
|
|
11
|
+
const app = createApp({ render: () => node });
|
|
12
|
+
app.mount(container);
|
|
13
|
+
mounts.push({ app, container });
|
|
14
|
+
return container;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
for (const { app, container } of mounts.splice(0)) {
|
|
19
|
+
app.unmount();
|
|
20
|
+
container.remove();
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const StubIcon = defineComponent({
|
|
25
|
+
name: "StubIcon",
|
|
26
|
+
setup() {
|
|
27
|
+
return () => h("i", { class: "stub-step-icon" });
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const ITEMS: StepGuideItem[] = [
|
|
32
|
+
{ id: "power", title: "插入电源", description: "接通设备供电", icon: StubIcon },
|
|
33
|
+
{ id: "card", title: "装入 SD 卡", image: "https://example.com/card.png" },
|
|
34
|
+
{ id: "net", title: "连接网线" },
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
describe("HkStepGuide", () => {
|
|
38
|
+
it("renders every item as a list entry with its title", () => {
|
|
39
|
+
const c = mount(h(HkStepGuide, { items: ITEMS }));
|
|
40
|
+
const items = Array.from(c.querySelectorAll(".hk-step-guide-item"));
|
|
41
|
+
expect(items.length).toBe(3);
|
|
42
|
+
const titles = items.map((i) => i.querySelector(".hk-step-guide-item-title")?.textContent);
|
|
43
|
+
expect(titles).toEqual(["插入电源", "装入 SD 卡", "连接网线"]);
|
|
44
|
+
// An ordered list — a guide is sequential by contract.
|
|
45
|
+
expect(c.querySelector(".hk-step-guide-list")?.tagName).toBe("OL");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("numbers the steps and swaps the ordinal for a check on done steps", () => {
|
|
49
|
+
const c = mount(h(HkStepGuide, { items: ITEMS, doneIds: ["power"] }));
|
|
50
|
+
const ordinals = Array.from(c.querySelectorAll(".hk-step-guide-ordinal"));
|
|
51
|
+
expect(ordinals[0].querySelector(".hk-step-guide-check")).not.toBeNull();
|
|
52
|
+
expect(ordinals[1].textContent?.trim()).toBe("2");
|
|
53
|
+
expect(ordinals[2].textContent?.trim()).toBe("3");
|
|
54
|
+
// The done step's art dims.
|
|
55
|
+
const arts = Array.from(c.querySelectorAll(".hk-step-guide-item"));
|
|
56
|
+
expect(arts[0].hasAttribute("data-done")).toBe(true);
|
|
57
|
+
expect(arts[1].hasAttribute("data-done")).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("renders the icon component when given, the image otherwise, nothing last", () => {
|
|
61
|
+
const c = mount(h(HkStepGuide, { items: ITEMS }));
|
|
62
|
+
const arts = Array.from(c.querySelectorAll(".hk-step-guide-art"));
|
|
63
|
+
expect(arts[0].querySelector(".stub-step-icon")).not.toBeNull();
|
|
64
|
+
const img = arts[1].querySelector("img.hk-step-guide-art-img") as HTMLImageElement;
|
|
65
|
+
expect(img?.getAttribute("src")).toBe("https://example.com/card.png");
|
|
66
|
+
expect(img?.getAttribute("alt")).toBe("装入 SD 卡");
|
|
67
|
+
expect(arts[2].children.length).toBe(0);
|
|
68
|
+
expect(arts[2].getAttribute("aria-hidden")).toBe("true");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("renders the section title and honors the grid layout hook", () => {
|
|
72
|
+
const c = mount(h(HkStepGuide, { items: ITEMS, title: "上架步骤", layout: "grid" }));
|
|
73
|
+
expect(c.querySelector(".hk-step-guide-title")?.textContent).toBe("上架步骤");
|
|
74
|
+
expect(c.querySelector(".hk-step-guide")?.getAttribute("data-layout")).toBe("grid");
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("renders nothing for an empty item list", () => {
|
|
78
|
+
const c = mount(h(HkStepGuide, { items: [] }));
|
|
79
|
+
expect(c.querySelector(".hk-step-guide")).toBeNull();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { defineComponent, h, type Component, type PropType } from "vue";
|
|
2
|
+
|
|
3
|
+
import "./HkStepGuide.scss";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One step of an illustrated how-to guide.
|
|
7
|
+
*
|
|
8
|
+
* Each step renders as a CARD — the step's OWN artwork (an SVG component,
|
|
9
|
+
* a lucide icon, or a bitmap URL) drawn large on the card face, with the
|
|
10
|
+
* ordinal pinned to the card's outer corner and the caption beneath it.
|
|
11
|
+
*/
|
|
12
|
+
export interface StepGuideItem {
|
|
13
|
+
/** Stable key (also the list rendering key). */
|
|
14
|
+
id: string;
|
|
15
|
+
/** Short imperative title ("插入 SD 卡"). */
|
|
16
|
+
title: string;
|
|
17
|
+
/** One-line elaboration under the title. */
|
|
18
|
+
description?: string;
|
|
19
|
+
/** SVG/lucide component rendered as the artwork. */
|
|
20
|
+
icon?: Component;
|
|
21
|
+
/** Bitmap/photo URL for the artwork (`icon` wins when both given). */
|
|
22
|
+
image?: string;
|
|
23
|
+
/** Accessible name when the artwork is decorative-only. Defaults to the title. */
|
|
24
|
+
alt?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* HkStepGuide — the big-artwork illustrated step cards.
|
|
29
|
+
*
|
|
30
|
+
* The "what do I physically do now?" surface for hardware-adjacent flows
|
|
31
|
+
* (upstreamed from the flasher's 等待上线 step and wowsp's install
|
|
32
|
+
* walkthrough, user direction 2026-09-25): every step is a rounded card —
|
|
33
|
+
* large artwork on the face, a short title and a one-line description
|
|
34
|
+
* under it, the ordinal badge pinned to the card's outer top corner.
|
|
35
|
+
*
|
|
36
|
+
* Orientation follows the AVAILABLE WIDTH, not the viewport: the guide is
|
|
37
|
+
* its own container query root, so wide hosts lay the cards side by side
|
|
38
|
+
* with a chevron bridging consecutive steps, and only stack them
|
|
39
|
+
* vertically once the width runs out. `layout="grid"` instead wraps the
|
|
40
|
+
* cards as an auto-fill grid.
|
|
41
|
+
*
|
|
42
|
+
* The artwork slots are deliberately permissive: pass a Vue component
|
|
43
|
+
* (`icon: MySvg`) for crisp theme-aware SVGs, or `image: url` for
|
|
44
|
+
* photos/screenshots the docs pipeline produces. Steps may be marked
|
|
45
|
+
* `data-done` through the `doneIds` prop (the check replaces the ordinal,
|
|
46
|
+
* the card picks up a success edge) so the guide doubles as a checklist
|
|
47
|
+
* while the flow progresses.
|
|
48
|
+
*/
|
|
49
|
+
export default defineComponent({
|
|
50
|
+
name: "HkStepGuide",
|
|
51
|
+
props: {
|
|
52
|
+
items: { type: Array as PropType<StepGuideItem[]>, required: true },
|
|
53
|
+
/** Steps whose ids appear here render as completed (check, success edge). */
|
|
54
|
+
doneIds: { type: Array as PropType<string[]>, default: () => [] },
|
|
55
|
+
/** Width-responsive flow cards (default) or an auto-fill card grid. */
|
|
56
|
+
layout: { type: String as PropType<"list" | "grid">, default: "list" },
|
|
57
|
+
/** Section heading above the steps. */
|
|
58
|
+
title: { type: String, default: undefined },
|
|
59
|
+
},
|
|
60
|
+
setup(props) {
|
|
61
|
+
return () => {
|
|
62
|
+
if (!props.items.length) return null;
|
|
63
|
+
const done = new Set(props.doneIds);
|
|
64
|
+
return (
|
|
65
|
+
<div class="hk-step-guide" data-layout={props.layout}>
|
|
66
|
+
{props.title && <h4 class="hk-step-guide-title">{props.title}</h4>}
|
|
67
|
+
<ol class="hk-step-guide-list">
|
|
68
|
+
{props.items.map((item, idx) => {
|
|
69
|
+
const isDone = done.has(item.id);
|
|
70
|
+
const Art = item.icon;
|
|
71
|
+
const alt = item.alt ?? item.title;
|
|
72
|
+
return (
|
|
73
|
+
<li
|
|
74
|
+
key={item.id}
|
|
75
|
+
class="hk-step-guide-item"
|
|
76
|
+
data-done={isDone || undefined}
|
|
77
|
+
>
|
|
78
|
+
<span class="hk-step-guide-ordinal">
|
|
79
|
+
{isDone ? (
|
|
80
|
+
<svg
|
|
81
|
+
class="hk-step-guide-check"
|
|
82
|
+
viewBox="0 0 24 24"
|
|
83
|
+
aria-hidden="true"
|
|
84
|
+
>
|
|
85
|
+
<path
|
|
86
|
+
d="M20 6L9 17l-5-5"
|
|
87
|
+
fill="none"
|
|
88
|
+
stroke="currentColor"
|
|
89
|
+
stroke-width="3"
|
|
90
|
+
stroke-linecap="round"
|
|
91
|
+
stroke-linejoin="round"
|
|
92
|
+
/>
|
|
93
|
+
</svg>
|
|
94
|
+
) : (
|
|
95
|
+
idx + 1
|
|
96
|
+
)}
|
|
97
|
+
</span>
|
|
98
|
+
<span
|
|
99
|
+
class="hk-step-guide-art"
|
|
100
|
+
aria-hidden={Art || item.image ? undefined : true}
|
|
101
|
+
>
|
|
102
|
+
{Art ? (
|
|
103
|
+
h(Art, { class: "hk-step-guide-art-svg" })
|
|
104
|
+
) : item.image ? (
|
|
105
|
+
<img
|
|
106
|
+
class="hk-step-guide-art-img"
|
|
107
|
+
src={item.image}
|
|
108
|
+
alt={alt}
|
|
109
|
+
draggable={false}
|
|
110
|
+
/>
|
|
111
|
+
) : null}
|
|
112
|
+
</span>
|
|
113
|
+
<span class="hk-step-guide-body">
|
|
114
|
+
<span class="hk-step-guide-item-title">{item.title}</span>
|
|
115
|
+
{item.description && (
|
|
116
|
+
<span class="hk-step-guide-item-desc">
|
|
117
|
+
{item.description}
|
|
118
|
+
</span>
|
|
119
|
+
)}
|
|
120
|
+
</span>
|
|
121
|
+
</li>
|
|
122
|
+
);
|
|
123
|
+
})}
|
|
124
|
+
</ol>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
});
|
|
@@ -189,7 +189,10 @@
|
|
|
189
189
|
"hikari::zoomToolbar.reset": "إعادة تعيين التكبير",
|
|
190
190
|
"hikari::zoomToolbar.zoomIn": "تكبير",
|
|
191
191
|
"hikari::zoomToolbar.zoomOut": "تصغير",
|
|
192
|
-
"hikari::zoomToolbar.zoomSlider": "مستوى التكبير"
|
|
192
|
+
"hikari::zoomToolbar.zoomSlider": "مستوى التكبير",
|
|
193
|
+
"hikari::filterBar.trigger": "عوامل التصفية",
|
|
194
|
+
"hikari::filterBar.apply": "تطبيق",
|
|
195
|
+
"hikari::filterBar.reset": "إعادة تعيين"
|
|
193
196
|
},
|
|
194
197
|
"hikari::affixPicker.unset": "غير محدد",
|
|
195
198
|
"hikari::affixPicker.title": "الخيارات",
|
|
@@ -189,7 +189,10 @@
|
|
|
189
189
|
"hikari::zoomToolbar.reset": "Zoom zurücksetzen",
|
|
190
190
|
"hikari::zoomToolbar.zoomIn": "Vergrößern",
|
|
191
191
|
"hikari::zoomToolbar.zoomOut": "Verkleinern",
|
|
192
|
-
"hikari::zoomToolbar.zoomSlider": "Zoom-Stufe"
|
|
192
|
+
"hikari::zoomToolbar.zoomSlider": "Zoom-Stufe",
|
|
193
|
+
"hikari::filterBar.trigger": "Filter",
|
|
194
|
+
"hikari::filterBar.apply": "Anwenden",
|
|
195
|
+
"hikari::filterBar.reset": "Zurücksetzen"
|
|
193
196
|
},
|
|
194
197
|
"hikari::affixPicker.unset": "Nicht festgelegt",
|
|
195
198
|
"hikari::affixPicker.title": "Optionen",
|
|
@@ -189,7 +189,10 @@
|
|
|
189
189
|
"hikari::zoomToolbar.reset": "Reset zoom",
|
|
190
190
|
"hikari::zoomToolbar.zoomIn": "Zoom in",
|
|
191
191
|
"hikari::zoomToolbar.zoomOut": "Zoom out",
|
|
192
|
-
"hikari::zoomToolbar.zoomSlider": "Zoom level"
|
|
192
|
+
"hikari::zoomToolbar.zoomSlider": "Zoom level",
|
|
193
|
+
"hikari::filterBar.trigger": "Filters",
|
|
194
|
+
"hikari::filterBar.apply": "Apply",
|
|
195
|
+
"hikari::filterBar.reset": "Reset"
|
|
193
196
|
},
|
|
194
197
|
"hikari::affixPicker.title": "Options",
|
|
195
198
|
"hikari::affixPicker.search": "Search",
|
|
@@ -189,7 +189,10 @@
|
|
|
189
189
|
"hikari::zoomToolbar.reset": "Restablecer zoom",
|
|
190
190
|
"hikari::zoomToolbar.zoomIn": "Acercar",
|
|
191
191
|
"hikari::zoomToolbar.zoomOut": "Alejar",
|
|
192
|
-
"hikari::zoomToolbar.zoomSlider": "Nivel de zoom"
|
|
192
|
+
"hikari::zoomToolbar.zoomSlider": "Nivel de zoom",
|
|
193
|
+
"hikari::filterBar.trigger": "Filtros",
|
|
194
|
+
"hikari::filterBar.apply": "Aplicar",
|
|
195
|
+
"hikari::filterBar.reset": "Restablecer"
|
|
193
196
|
},
|
|
194
197
|
"hikari::affixPicker.unset": "Sin establecer",
|
|
195
198
|
"hikari::affixPicker.title": "Opciones",
|
|
@@ -189,7 +189,10 @@
|
|
|
189
189
|
"hikari::zoomToolbar.reset": "Réinitialiser le zoom",
|
|
190
190
|
"hikari::zoomToolbar.zoomIn": "Agrandir",
|
|
191
191
|
"hikari::zoomToolbar.zoomOut": "Réduire",
|
|
192
|
-
"hikari::zoomToolbar.zoomSlider": "Niveau de zoom"
|
|
192
|
+
"hikari::zoomToolbar.zoomSlider": "Niveau de zoom",
|
|
193
|
+
"hikari::filterBar.trigger": "Filtres",
|
|
194
|
+
"hikari::filterBar.apply": "Appliquer",
|
|
195
|
+
"hikari::filterBar.reset": "Réinitialiser"
|
|
193
196
|
},
|
|
194
197
|
"hikari::affixPicker.unset": "Non défini",
|
|
195
198
|
"hikari::affixPicker.title": "Options",
|
|
@@ -189,7 +189,10 @@
|
|
|
189
189
|
"hikari::zoomToolbar.reset": "ズームをリセット",
|
|
190
190
|
"hikari::zoomToolbar.zoomIn": "拡大",
|
|
191
191
|
"hikari::zoomToolbar.zoomOut": "縮小",
|
|
192
|
-
"hikari::zoomToolbar.zoomSlider": "ズーム倍率"
|
|
192
|
+
"hikari::zoomToolbar.zoomSlider": "ズーム倍率",
|
|
193
|
+
"hikari::filterBar.trigger": "絞り込み",
|
|
194
|
+
"hikari::filterBar.apply": "適用",
|
|
195
|
+
"hikari::filterBar.reset": "リセット"
|
|
193
196
|
},
|
|
194
197
|
"hikari::affixPicker.unset": "未設定",
|
|
195
198
|
"hikari::affixPicker.title": "オプション",
|
|
@@ -189,7 +189,10 @@
|
|
|
189
189
|
"hikari::zoomToolbar.reset": "줌 초기화",
|
|
190
190
|
"hikari::zoomToolbar.zoomIn": "확대",
|
|
191
191
|
"hikari::zoomToolbar.zoomOut": "축소",
|
|
192
|
-
"hikari::zoomToolbar.zoomSlider": "확대 수준"
|
|
192
|
+
"hikari::zoomToolbar.zoomSlider": "확대 수준",
|
|
193
|
+
"hikari::filterBar.trigger": "필터",
|
|
194
|
+
"hikari::filterBar.apply": "적용",
|
|
195
|
+
"hikari::filterBar.reset": "초기화"
|
|
193
196
|
},
|
|
194
197
|
"hikari::affixPicker.unset": "미설정",
|
|
195
198
|
"hikari::affixPicker.title": "옵션",
|
|
@@ -189,7 +189,10 @@
|
|
|
189
189
|
"hikari::zoomToolbar.reset": "Redefinir zoom",
|
|
190
190
|
"hikari::zoomToolbar.zoomIn": "Ampliar",
|
|
191
191
|
"hikari::zoomToolbar.zoomOut": "Reduzir",
|
|
192
|
-
"hikari::zoomToolbar.zoomSlider": "Nível de zoom"
|
|
192
|
+
"hikari::zoomToolbar.zoomSlider": "Nível de zoom",
|
|
193
|
+
"hikari::filterBar.trigger": "Filtros",
|
|
194
|
+
"hikari::filterBar.apply": "Aplicar",
|
|
195
|
+
"hikari::filterBar.reset": "Redefinir"
|
|
193
196
|
},
|
|
194
197
|
"hikari::affixPicker.unset": "Não definido",
|
|
195
198
|
"hikari::affixPicker.title": "Opções",
|
|
@@ -189,7 +189,10 @@
|
|
|
189
189
|
"hikari::zoomToolbar.reset": "Сбросить масштаб",
|
|
190
190
|
"hikari::zoomToolbar.zoomIn": "Увеличить",
|
|
191
191
|
"hikari::zoomToolbar.zoomOut": "Уменьшить",
|
|
192
|
-
"hikari::zoomToolbar.zoomSlider": "Уровень масштаба"
|
|
192
|
+
"hikari::zoomToolbar.zoomSlider": "Уровень масштаба",
|
|
193
|
+
"hikari::filterBar.trigger": "Фильтры",
|
|
194
|
+
"hikari::filterBar.apply": "Применить",
|
|
195
|
+
"hikari::filterBar.reset": "Сбросить"
|
|
193
196
|
},
|
|
194
197
|
"hikari::affixPicker.unset": "Не задано",
|
|
195
198
|
"hikari::affixPicker.title": "Параметры",
|
|
@@ -193,7 +193,10 @@
|
|
|
193
193
|
"hikari::statusBar.region.CN": "中国大陆",
|
|
194
194
|
"hikari::statusBar.region.HK": "中国香港",
|
|
195
195
|
"hikari::statusBar.region.MO": "中国澳门",
|
|
196
|
-
"hikari::statusBar.region.TW": "中国台湾"
|
|
196
|
+
"hikari::statusBar.region.TW": "中国台湾",
|
|
197
|
+
"hikari::filterBar.trigger": "筛选",
|
|
198
|
+
"hikari::filterBar.apply": "应用",
|
|
199
|
+
"hikari::filterBar.reset": "重置"
|
|
197
200
|
},
|
|
198
201
|
"hikari::affixPicker.title": "选项",
|
|
199
202
|
"hikari::affixPicker.search": "搜索",
|
|
@@ -193,7 +193,10 @@
|
|
|
193
193
|
"hikari::statusBar.region.CN": "中國大陸",
|
|
194
194
|
"hikari::statusBar.region.HK": "中國香港",
|
|
195
195
|
"hikari::statusBar.region.MO": "中國澳門",
|
|
196
|
-
"hikari::statusBar.region.TW": "中國台灣"
|
|
196
|
+
"hikari::statusBar.region.TW": "中國台灣",
|
|
197
|
+
"hikari::filterBar.trigger": "篩選",
|
|
198
|
+
"hikari::filterBar.apply": "套用",
|
|
199
|
+
"hikari::filterBar.reset": "重設"
|
|
197
200
|
},
|
|
198
201
|
"hikari::affixPicker.title": "選項",
|
|
199
202
|
"hikari::affixPicker.search": "搜尋",
|
package/src/index.ts
CHANGED
|
@@ -25,6 +25,8 @@ export {
|
|
|
25
25
|
} from "./components/HkDockBar";
|
|
26
26
|
export { default as HDrawer } from "./components/HkDrawer";
|
|
27
27
|
export { default as HEmptyState } from "./components/HkEmptyState";
|
|
28
|
+
export { default as HStepGuide } from "./components/HkStepGuide";
|
|
29
|
+
export type { StepGuideItem } from "./components/HkStepGuide";
|
|
28
30
|
export { default as HExpansionPanel } from "./components/HkExpansionPanel";
|
|
29
31
|
export { default as HFab, type HFabAction } from "./components/HkFab";
|
|
30
32
|
export { default as HIcon } from "./components/HkIcon";
|
|
@@ -492,7 +494,7 @@ export type { ChallengeDescriptor } from "./utils/powNonce";
|
|
|
492
494
|
export { HkAdminTablePage as HAdminTablePage } from "./components/HkAdminTablePage";
|
|
493
495
|
export type { HTableColumn } from "./components/HkAdminTablePage";
|
|
494
496
|
export { HkPageHeader as HPageHeader } from "./components/HkPageHeader";
|
|
495
|
-
export { HkStatCard as HStatCard
|
|
497
|
+
export { HkStatCard as HStatCard } from "./components/HkStatCard";
|
|
496
498
|
export { HkStatusPill as HStatusPill, type PillState } from "./components/HkStatusPill";
|
|
497
499
|
export { HkShareBar as HShareBar } from "./components/HkShareBar";
|
|
498
500
|
export { HkSecretRevealModal as HSecretRevealModal } from "./components/HkSecretRevealModal";
|
|
@@ -749,7 +751,10 @@ export { HkLocalePicker as HkLocalePicker } from "./components/HkLocalePicker";
|
|
|
749
751
|
export { HkAdminTablePage as HkAdminTablePage } from "./components/HkAdminTablePage";
|
|
750
752
|
export { HkPageHeader as HkPageHeader } from "./components/HkPageHeader";
|
|
751
753
|
export { HkStatCard as HkStatCard } from "./components/HkStatCard";
|
|
754
|
+
export { statToneColor, type StatTone as StatTone, type StatVariant as StatVariant } from "./components/HkStatCard";
|
|
752
755
|
export { HkStatusPill as HkStatusPill } from "./components/HkStatusPill";
|
|
756
|
+
export { default as HkFilterBar } from "./components/HkFilterBar";
|
|
757
|
+
export { default as HFilterBar } from "./components/HkFilterBar";
|
|
753
758
|
export { HkShareBar as HkShareBar } from "./components/HkShareBar";
|
|
754
759
|
export { HkSecretRevealModal as HkSecretRevealModal } from "./components/HkSecretRevealModal";
|
|
755
760
|
export { HkCaptchaWidget as HkCaptchaWidget } from "./components/HkCaptchaWidget";
|
|
@@ -1040,3 +1040,24 @@
|
|
|
1040
1040
|
.a-auth-page {
|
|
1041
1041
|
min-height: calc(100vh - var(--s-footer-height, 3rem));
|
|
1042
1042
|
}
|
|
1043
|
+
|
|
1044
|
+
// ── adjacent-button spacing (the button-row grammar) ──────────────────────
|
|
1045
|
+
// EVERY horizontal run of buttons keeps a visible gap between neighbours —
|
|
1046
|
+
// two buttons touching reads as one split control (user direction
|
|
1047
|
+
// 2026-09-25). Hosts wrap their button clusters in .hk-button-row and get
|
|
1048
|
+
// the house rhythm; modal footers and step docks already carry their own
|
|
1049
|
+
// gap on the same token, so everything agrees.
|
|
1050
|
+
.hk-button-row {
|
|
1051
|
+
display: flex;
|
|
1052
|
+
flex-direction: row;
|
|
1053
|
+
align-items: center;
|
|
1054
|
+
gap: var(--space-12, 0.75rem);
|
|
1055
|
+
|
|
1056
|
+
&[data-compact] {
|
|
1057
|
+
gap: var(--space-8, 0.5rem);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
&[data-end] {
|
|
1061
|
+
justify-content: flex-end;
|
|
1062
|
+
}
|
|
1063
|
+
}
|