@celestia-island/hikari 0.45.3 → 0.45.4
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/HkAboutModal.scss +31 -3
- package/src/components/HkAboutModal.test.tsx +30 -16
- package/src/components/HkAboutModal.tsx +41 -17
- package/src/i18n/locales/ar/platform.json +0 -1
- package/src/i18n/locales/de/platform.json +0 -1
- package/src/i18n/locales/en/platform.json +0 -1
- package/src/i18n/locales/es/platform.json +0 -1
- package/src/i18n/locales/fr/platform.json +0 -1
- package/src/i18n/locales/ja/platform.json +0 -1
- package/src/i18n/locales/ko/platform.json +0 -1
- package/src/i18n/locales/pt/platform.json +0 -1
- package/src/i18n/locales/ru/platform.json +0 -1
- package/src/i18n/locales/zh-Hans/platform.json +0 -1
- package/src/i18n/locales/zh-Hant/platform.json +0 -1
package/package.json
CHANGED
|
@@ -72,6 +72,14 @@
|
|
|
72
72
|
color: rgb(var(--color-muted));
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
.s-about-modal-slogan {
|
|
76
|
+
margin: 0;
|
|
77
|
+
font-size: var(--text-base, 1rem);
|
|
78
|
+
font-weight: 600;
|
|
79
|
+
text-align: center;
|
|
80
|
+
color: rgb(var(--color-text));
|
|
81
|
+
}
|
|
82
|
+
|
|
75
83
|
.s-about-modal-tagline {
|
|
76
84
|
margin: var(--space-2, 0.125rem) 0 0;
|
|
77
85
|
font-size: var(--text-xs, 0.75rem);
|
|
@@ -80,8 +88,9 @@
|
|
|
80
88
|
|
|
81
89
|
.s-about-modal-description {
|
|
82
90
|
margin: 0;
|
|
83
|
-
font-size: var(--text-
|
|
84
|
-
line-height: 1.
|
|
91
|
+
font-size: var(--text-xs, 0.75rem);
|
|
92
|
+
line-height: 1.6;
|
|
93
|
+
text-align: center;
|
|
85
94
|
color: rgb(var(--color-muted));
|
|
86
95
|
}
|
|
87
96
|
|
|
@@ -127,6 +136,7 @@
|
|
|
127
136
|
.s-about-modal-links-list {
|
|
128
137
|
display: flex;
|
|
129
138
|
flex-wrap: wrap;
|
|
139
|
+
justify-content: center;
|
|
130
140
|
gap: var(--space-8, 0.5rem);
|
|
131
141
|
}
|
|
132
142
|
|
|
@@ -154,7 +164,25 @@
|
|
|
154
164
|
0 0 0 4px rgb(var(--color-primary));
|
|
155
165
|
}
|
|
156
166
|
|
|
167
|
+
.s-about-modal-footer-links {
|
|
168
|
+
display: flex;
|
|
169
|
+
flex-wrap: wrap;
|
|
170
|
+
justify-content: center;
|
|
171
|
+
gap: var(--space-12, 0.75rem);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.s-about-modal-footer-link {
|
|
175
|
+
font-size: var(--text-xs, 0.75rem);
|
|
176
|
+
color: rgb(var(--color-muted));
|
|
177
|
+
text-decoration: none;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.s-about-modal-footer-link:hover {
|
|
181
|
+
color: rgb(var(--color-primary));
|
|
182
|
+
text-decoration: underline;
|
|
183
|
+
}
|
|
184
|
+
|
|
157
185
|
.s-about-modal-footer {
|
|
158
186
|
display: flex;
|
|
159
|
-
justify-content:
|
|
187
|
+
justify-content: center;
|
|
160
188
|
}
|
|
@@ -94,15 +94,18 @@ describe("HkAboutModal branding", () => {
|
|
|
94
94
|
expect(query<HTMLElement>(".s-about-modal-description").textContent).toBe("Save the world.");
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
-
it("renders
|
|
97
|
+
it("renders the made-by row with a linked origin", async () => {
|
|
98
98
|
mountAbout({
|
|
99
|
-
author: "
|
|
100
|
-
|
|
99
|
+
author: "由 伊欧 主创",
|
|
100
|
+
origin: "来自 Celestia Island",
|
|
101
|
+
originHref: "https://github.com/celestia-island",
|
|
101
102
|
license: "BUSL-1.1",
|
|
102
103
|
});
|
|
103
104
|
await flushModal();
|
|
105
|
+
const row = query<HTMLElement>(".s-about-modal-row");
|
|
106
|
+
expect(row.querySelector(".s-about-modal-row-label")?.textContent).toBe("由 伊欧 主创");
|
|
104
107
|
const link = query<HTMLAnchorElement>(".s-about-modal-row-link");
|
|
105
|
-
expect(link.textContent).toBe("Celestia Island");
|
|
108
|
+
expect(link.textContent).toBe("来自 Celestia Island");
|
|
106
109
|
expect(link.getAttribute("href")).toBe("https://github.com/celestia-island");
|
|
107
110
|
expect(link.getAttribute("target")).toBe("_blank");
|
|
108
111
|
const rows = [...document.body.querySelectorAll<HTMLElement>(".s-about-modal-row")];
|
|
@@ -111,13 +114,28 @@ describe("HkAboutModal branding", () => {
|
|
|
111
114
|
expect(licenseRow!.textContent).toContain("License");
|
|
112
115
|
});
|
|
113
116
|
|
|
114
|
-
it("renders the
|
|
115
|
-
mountAbout({ author: "Celestia Island" });
|
|
117
|
+
it("renders the made-by row as plain text without originHref", async () => {
|
|
118
|
+
mountAbout({ author: "由 伊欧 主创", origin: "来自 Celestia Island" });
|
|
116
119
|
await flushModal();
|
|
117
|
-
expect(query<HTMLElement>(".s-about-modal-row").textContent).toContain("Celestia Island");
|
|
120
|
+
expect(query<HTMLElement>(".s-about-modal-row").textContent).toContain("来自 Celestia Island");
|
|
118
121
|
expect(document.body.querySelector(".s-about-modal-row-link")).toBeNull();
|
|
119
122
|
});
|
|
120
123
|
|
|
124
|
+
it("renders the centered slogan and centered legal footer links", async () => {
|
|
125
|
+
mountAbout({
|
|
126
|
+
slogan: "技术宅拯救世界。",
|
|
127
|
+
footerLinks: [{ label: "京ICP备2026xxxx号", href: "https://beian.miit.gov.cn/" }],
|
|
128
|
+
});
|
|
129
|
+
await flushModal();
|
|
130
|
+
expect(query<HTMLElement>(".s-about-modal-slogan").textContent).toBe("技术宅拯救世界。");
|
|
131
|
+
const links = [
|
|
132
|
+
...document.body.querySelectorAll<HTMLAnchorElement>(".s-about-modal-footer-link"),
|
|
133
|
+
];
|
|
134
|
+
expect(links.length).toBe(1);
|
|
135
|
+
expect(links[0]!.textContent).toBe("京ICP备2026xxxx号");
|
|
136
|
+
expect(links[0]!.getAttribute("href")).toBe("https://beian.miit.gov.cn/");
|
|
137
|
+
});
|
|
138
|
+
|
|
121
139
|
it("renders the backdrop factory inside the clipped layer", async () => {
|
|
122
140
|
mountAbout({ backdrop: () => h("div", { class: "test-backdrop-marker" }) });
|
|
123
141
|
await flushModal();
|
|
@@ -159,23 +177,19 @@ describe("HkAboutModal branding", () => {
|
|
|
159
177
|
expect(badge.textContent).toContain(`© ${year} Test App`);
|
|
160
178
|
});
|
|
161
179
|
|
|
162
|
-
it("localizes the
|
|
163
|
-
mountAbout({
|
|
180
|
+
it("localizes the license label", async () => {
|
|
181
|
+
mountAbout({ license: "BUSL-1.1" });
|
|
164
182
|
await flushModal();
|
|
165
|
-
const
|
|
183
|
+
const labels = () => [
|
|
166
184
|
...document.body.querySelectorAll<HTMLElement>(".s-about-modal-row-label"),
|
|
167
185
|
];
|
|
168
186
|
|
|
169
187
|
setLocale("zh-Hans");
|
|
170
188
|
await flushModal();
|
|
171
|
-
|
|
172
|
-
expect(text.some((t) => t === "作者")).toBe(true);
|
|
173
|
-
expect(text.some((t) => t === "许可证")).toBe(true);
|
|
189
|
+
expect(labels().some((el) => el.textContent === "许可证")).toBe(true);
|
|
174
190
|
|
|
175
191
|
setLocale("en");
|
|
176
192
|
await flushModal();
|
|
177
|
-
|
|
178
|
-
expect(text.some((t) => t === "Author")).toBe(true);
|
|
179
|
-
expect(text.some((t) => t === "License")).toBe(true);
|
|
193
|
+
expect(labels().some((el) => el.textContent === "License")).toBe(true);
|
|
180
194
|
});
|
|
181
195
|
});
|
|
@@ -15,12 +15,13 @@ export interface HAboutLink {
|
|
|
15
15
|
* (Upstreamed from shittim-chest's plana-legacy layer.)
|
|
16
16
|
*
|
|
17
17
|
* Shows the app identity and version metadata plus optional branding: a
|
|
18
|
-
* logo image, tagline,
|
|
19
|
-
* decorative backdrop layer (canvas or anything
|
|
20
|
-
* content and pointer-inert)
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
18
|
+
* logo image, tagline, centered slogan + organization line, a made-by /
|
|
19
|
+
* origin row, license row, a decorative backdrop layer (canvas or anything
|
|
20
|
+
* else, rendered behind the content and pointer-inert), external link
|
|
21
|
+
* chips and centered legal footer links (e.g. ICP filings). Version/build
|
|
22
|
+
* hashes render as short hashes when longer than 12 chars (full value in
|
|
23
|
+
* `title` tooltip). Every branding prop is optional — the modal degrades
|
|
24
|
+
* to the plain identity + version card when none are given.
|
|
24
25
|
*/
|
|
25
26
|
export const HkAboutModal = defineComponent({
|
|
26
27
|
name: "HkAboutModal",
|
|
@@ -40,18 +41,24 @@ export const HkAboutModal = defineComponent({
|
|
|
40
41
|
logoSrc: { type: String, default: undefined },
|
|
41
42
|
/** Optional one-liner under the version (e.g. the app tagline). */
|
|
42
43
|
tagline: { type: String, default: undefined },
|
|
43
|
-
/** Optional
|
|
44
|
+
/** Optional centered slogan below the header (the app's one-liner). */
|
|
45
|
+
slogan: { type: String, default: undefined },
|
|
46
|
+
/** Optional centered small line under the slogan (organization blurb). */
|
|
44
47
|
description: { type: String, default: undefined },
|
|
45
|
-
/** Optional
|
|
48
|
+
/** Optional made-by row: left label (e.g. "由 伊欧 主创"). */
|
|
46
49
|
author: { type: String, default: undefined },
|
|
47
|
-
/** Optional
|
|
48
|
-
|
|
50
|
+
/** Optional right value of the made-by row (e.g. "来自 Celestia Island"). */
|
|
51
|
+
origin: { type: String, default: undefined },
|
|
52
|
+
/** Optional link applied to the origin value. */
|
|
53
|
+
originHref: { type: String, default: undefined },
|
|
49
54
|
/** Optional license identifier row (e.g. "BUSL-1.1"). */
|
|
50
55
|
license: { type: String, default: undefined },
|
|
51
56
|
/** Optional copyright holder in the footer (defaults to the app name). */
|
|
52
57
|
copyright: { type: String, default: undefined },
|
|
53
58
|
/** Optional external links (e.g. GitHub, docs). */
|
|
54
59
|
links: { type: Array as PropType<HAboutLink[]>, default: () => [] },
|
|
60
|
+
/** Optional centered legal links above the copyright (ICP filings). */
|
|
61
|
+
footerLinks: { type: Array as PropType<HAboutLink[]>, default: () => [] },
|
|
55
62
|
/**
|
|
56
63
|
* Optional decorative backdrop factory, rendered behind the content
|
|
57
64
|
* inside a clipped, pointer-inert layer. The modal owns only the layer —
|
|
@@ -70,16 +77,16 @@ export const HkAboutModal = defineComponent({
|
|
|
70
77
|
return hash.length > 12 ? `${hash.slice(0, 12)}…` : hash;
|
|
71
78
|
}
|
|
72
79
|
|
|
73
|
-
const
|
|
74
|
-
if (!props.
|
|
80
|
+
const renderOriginValue = () => {
|
|
81
|
+
if (!props.originHref) return props.origin;
|
|
75
82
|
return (
|
|
76
83
|
<a
|
|
77
84
|
class="s-about-modal-row-link"
|
|
78
|
-
href={props.
|
|
85
|
+
href={props.originHref}
|
|
79
86
|
target="_blank"
|
|
80
87
|
rel="noopener noreferrer"
|
|
81
88
|
>
|
|
82
|
-
{props.
|
|
89
|
+
{props.origin}
|
|
83
90
|
</a>
|
|
84
91
|
);
|
|
85
92
|
};
|
|
@@ -113,13 +120,14 @@ export const HkAboutModal = defineComponent({
|
|
|
113
120
|
</div>
|
|
114
121
|
</header>
|
|
115
122
|
|
|
123
|
+
{props.slogan && <p class="s-about-modal-slogan">{props.slogan}</p>}
|
|
116
124
|
{props.description && <p class="s-about-modal-description">{props.description}</p>}
|
|
117
125
|
|
|
118
126
|
<div class="s-about-modal-rows">
|
|
119
|
-
{props.author && (
|
|
127
|
+
{(props.author || props.origin) && (
|
|
120
128
|
<div class="s-about-modal-row">
|
|
121
|
-
<span class="s-about-modal-row-label">{
|
|
122
|
-
<span class="s-about-modal-row-value">{
|
|
129
|
+
<span class="s-about-modal-row-label">{props.author}</span>
|
|
130
|
+
<span class="s-about-modal-row-value">{renderOriginValue()}</span>
|
|
123
131
|
</div>
|
|
124
132
|
)}
|
|
125
133
|
{props.license && (
|
|
@@ -176,6 +184,22 @@ export const HkAboutModal = defineComponent({
|
|
|
176
184
|
</div>
|
|
177
185
|
)}
|
|
178
186
|
|
|
187
|
+
{props.footerLinks.length > 0 && (
|
|
188
|
+
<div class="s-about-modal-footer-links">
|
|
189
|
+
{props.footerLinks.map((link) => (
|
|
190
|
+
<a
|
|
191
|
+
key={link.href}
|
|
192
|
+
href={link.href}
|
|
193
|
+
target="_blank"
|
|
194
|
+
rel="noopener noreferrer"
|
|
195
|
+
class="s-about-modal-footer-link"
|
|
196
|
+
>
|
|
197
|
+
{link.label}
|
|
198
|
+
</a>
|
|
199
|
+
))}
|
|
200
|
+
</div>
|
|
201
|
+
)}
|
|
202
|
+
|
|
179
203
|
<footer class="s-about-modal-footer">
|
|
180
204
|
<HBadge variant="muted">
|
|
181
205
|
© {new Date().getFullYear()} {props.copyright ?? props.appName}
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"hikari::about.buildHash": "البناء",
|
|
18
18
|
"hikari::about.engineVersion": "إصدار المحرك",
|
|
19
19
|
"hikari::about.engineBuildHash": "بناء المحرك",
|
|
20
|
-
"hikari::about.author": "المؤلف",
|
|
21
20
|
"hikari::about.license": "الترخيص",
|
|
22
21
|
"hikari::theme.mode": "وضع السمة",
|
|
23
22
|
"hikari::theme.modeLight": "فاتح",
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"hikari::about.buildHash": "Build",
|
|
18
18
|
"hikari::about.engineVersion": "Engine-Version",
|
|
19
19
|
"hikari::about.engineBuildHash": "Engine-Build",
|
|
20
|
-
"hikari::about.author": "Autor",
|
|
21
20
|
"hikari::about.license": "Lizenz",
|
|
22
21
|
"hikari::theme.mode": "Design-Modus",
|
|
23
22
|
"hikari::theme.modeLight": "Hell",
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"hikari::about.buildHash": "Build",
|
|
18
18
|
"hikari::about.engineVersion": "Engine version",
|
|
19
19
|
"hikari::about.engineBuildHash": "Engine build",
|
|
20
|
-
"hikari::about.author": "Author",
|
|
21
20
|
"hikari::about.license": "License",
|
|
22
21
|
"hikari::theme.mode": "Theme mode",
|
|
23
22
|
"hikari::theme.modeLight": "Light",
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"hikari::about.buildHash": "Compilación",
|
|
18
18
|
"hikari::about.engineVersion": "Versión del motor",
|
|
19
19
|
"hikari::about.engineBuildHash": "Compilación del motor",
|
|
20
|
-
"hikari::about.author": "Autor",
|
|
21
20
|
"hikari::about.license": "Licencia",
|
|
22
21
|
"hikari::theme.mode": "Modo de tema",
|
|
23
22
|
"hikari::theme.modeLight": "Claro",
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"hikari::about.buildHash": "Build",
|
|
18
18
|
"hikari::about.engineVersion": "Version du moteur",
|
|
19
19
|
"hikari::about.engineBuildHash": "Build du moteur",
|
|
20
|
-
"hikari::about.author": "Auteur",
|
|
21
20
|
"hikari::about.license": "Licence",
|
|
22
21
|
"hikari::theme.mode": "Mode du thème",
|
|
23
22
|
"hikari::theme.modeLight": "Clair",
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"hikari::about.buildHash": "ビルド",
|
|
18
18
|
"hikari::about.engineVersion": "エンジンバージョン",
|
|
19
19
|
"hikari::about.engineBuildHash": "エンジンビルド",
|
|
20
|
-
"hikari::about.author": "作者",
|
|
21
20
|
"hikari::about.license": "ライセンス",
|
|
22
21
|
"hikari::theme.mode": "テーマモード",
|
|
23
22
|
"hikari::theme.modeLight": "ライト",
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"hikari::about.buildHash": "빌드",
|
|
18
18
|
"hikari::about.engineVersion": "엔진 버전",
|
|
19
19
|
"hikari::about.engineBuildHash": "엔진 빌드",
|
|
20
|
-
"hikari::about.author": "제작자",
|
|
21
20
|
"hikari::about.license": "라이선스",
|
|
22
21
|
"hikari::theme.mode": "테마 모드",
|
|
23
22
|
"hikari::theme.modeLight": "라이트",
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"hikari::about.buildHash": "Build",
|
|
18
18
|
"hikari::about.engineVersion": "Versão do motor",
|
|
19
19
|
"hikari::about.engineBuildHash": "Build do motor",
|
|
20
|
-
"hikari::about.author": "Autor",
|
|
21
20
|
"hikari::about.license": "Licença",
|
|
22
21
|
"hikari::theme.mode": "Modo do tema",
|
|
23
22
|
"hikari::theme.modeLight": "Claro",
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"hikari::about.buildHash": "Сборка",
|
|
18
18
|
"hikari::about.engineVersion": "Версия движка",
|
|
19
19
|
"hikari::about.engineBuildHash": "Сборка движка",
|
|
20
|
-
"hikari::about.author": "Автор",
|
|
21
20
|
"hikari::about.license": "Лицензия",
|
|
22
21
|
"hikari::theme.mode": "Режим темы",
|
|
23
22
|
"hikari::theme.modeLight": "Светлая",
|