@celestia-island/hikari 0.55.76 → 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.
Files changed (31) hide show
  1. package/package.json +1 -1
  2. package/src/components/HkFilterBar.scss +59 -0
  3. package/src/components/HkFilterBar.test.tsx +130 -0
  4. package/src/components/HkFilterBar.tsx +143 -0
  5. package/src/components/HkGaugeRing.tsx +13 -1
  6. package/src/components/HkSelectionGrid.scss +91 -0
  7. package/src/components/HkSelectionGrid.test.tsx +68 -0
  8. package/src/components/HkSelectionGrid.tsx +56 -1
  9. package/src/components/HkSettingsDialog.scss +12 -1
  10. package/src/components/HkStatCard.scss +107 -0
  11. package/src/components/HkStatCard.tsx +173 -21
  12. package/src/components/HkStatCard.variants.test.tsx +210 -0
  13. package/src/components/HkStepGuide.scss +177 -0
  14. package/src/components/HkStepGuide.test.tsx +81 -0
  15. package/src/components/HkStepGuide.tsx +129 -0
  16. package/src/components/HkThemeToggle.test.ts +23 -0
  17. package/src/components/HkThemeToggle.tsx +11 -2
  18. package/src/i18n/locales/ar/components.json +5 -1
  19. package/src/i18n/locales/de/components.json +5 -1
  20. package/src/i18n/locales/en/components.json +5 -1
  21. package/src/i18n/locales/es/components.json +5 -1
  22. package/src/i18n/locales/fr/components.json +5 -1
  23. package/src/i18n/locales/ja/components.json +5 -1
  24. package/src/i18n/locales/ko/components.json +5 -1
  25. package/src/i18n/locales/pt/components.json +5 -1
  26. package/src/i18n/locales/ru/components.json +5 -1
  27. package/src/i18n/locales/zh-Hans/components.json +5 -1
  28. package/src/i18n/locales/zh-Hant/components.json +5 -1
  29. package/src/index.ts +6 -1
  30. package/src/styles/admin-tokens.scss +21 -0
  31. package/src/theme/presets.ts +7 -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
+ });
@@ -427,3 +427,26 @@ describe("HkThemeToggle exposed closeMenu", () => {
427
427
  expect(document.body.querySelector(".s-theme-menu")).toBeTruthy();
428
428
  });
429
429
  });
430
+
431
+ describe("HkThemeToggle theme names", () => {
432
+ it("localizes a name that is a message key and passes literal names through", async () => {
433
+ // The ThemePreset.name convention: a resolvable catalog key renders its
434
+ // message (hosts ship localized built-ins); anything else — user-named
435
+ // customs, strings that merely LOOK like dotted keys — renders raw,
436
+ // because t() falls back to the input when the key is unknown.
437
+ useTheme().addCustomTheme({ ...anyPresetTokens(), id: "test-keyed", name: "hikari::theme.defaultThemeName" });
438
+ useTheme().addCustomTheme({ ...anyPresetTokens(), id: "test-literal", name: "Not A Catalog Key.At All" });
439
+ const { container } = mountToggle(true);
440
+ await settle();
441
+
442
+ openMenu(container);
443
+ await settle();
444
+
445
+ const names = [...document.body.querySelectorAll<HTMLElement>(".s-theme-menu .s-theme-item-row .s-theme-item-name")]
446
+ .map((el) => el.textContent?.trim());
447
+ // en bundle value of the key (the test locale is hikari's default).
448
+ expect(names).toContain("Default");
449
+ expect(names).toContain("Not A Catalog Key.At All");
450
+ expect(names).not.toContain("hikari::theme.defaultThemeName");
451
+ });
452
+ });
@@ -24,7 +24,9 @@ const AUTO_MERGE_KEYS = ["light", "dark"];
24
24
 
25
25
  /** Scoped payload handed to the `item-leading` / `item-trailing` slots:
26
26
  * one object per theme row, carrying enough identity for the host to
27
- * render swatches or affordances without re-deriving the preset. */
27
+ * render swatches or affordances without re-deriving the preset.
28
+ * `name` is the RAW stored string — it may be a message key (see
29
+ * `ThemePreset.name`); the row cell resolves it through the catalog. */
28
30
  export interface ThemeItemScope {
29
31
  id: ThemeId;
30
32
  name: string;
@@ -314,6 +316,13 @@ export const HkThemeToggle = defineComponent({
314
316
  };
315
317
  const leadingSlot = slots["item-leading"];
316
318
  const trailingSlot = slots["item-trailing"];
319
+ // A preset/custom name may be a message key into hikari's own
320
+ // catalog (the documented ThemePreset.name convention — hosts
321
+ // ship localized built-ins like "hikari::theme.defaultThemeName").
322
+ // `t()` falls back to the raw string for anything that is not a
323
+ // key, so literal display names pass through unchanged, and the
324
+ // reactive message lookup re-renders rows on locale switches.
325
+ const displayName = t(th.name);
317
326
  return (
318
327
  <div
319
328
  key={th.id}
@@ -334,7 +343,7 @@ export const HkThemeToggle = defineComponent({
334
343
  ) : currentTheme.value === th.id ? (
335
344
  <span class="hk-menu-item-icon s-theme-item-check"><Check size={14} /></span>
336
345
  ) : null}
337
- <span class="s-theme-item-name">{th.name}</span>
346
+ <span class="s-theme-item-name">{displayName}</span>
338
347
  </button>
339
348
  {trailingSlot ? (
340
349
  <span class="s-theme-item-trailing">{trailingSlot(scope)}</span>
@@ -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": "الخيارات",
@@ -220,6 +223,7 @@
220
223
  "hikari::tagInput.reorder": "إعادة الترتيب — {label}",
221
224
  "hikari::modal.hiddenLayers": "الطبقات المخفية",
222
225
  "hikari::theme.modeTabHint": "هذه التبويبات تختار لوحة الألوان التي تحرّرها؛ لتبديل الوضع الفاتح/الداكن للتطبيق كله استخدم شريط الأوضاع أعلى نافذة السمة.",
226
+ "hikari::theme.defaultThemeName": "افتراضي",
223
227
  "hikari::emptyState.loading": "جارٍ التحميل",
224
228
  "hikari::mfaVerify.title": "التحقق من الحساب",
225
229
  "hikari::mfaVerify.verifySubtitle": "جارٍ التحقق من {name} — أكمل طريقة تسجيل الدخول للمتابعة",
@@ -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",
@@ -220,6 +223,7 @@
220
223
  "hikari::tagInput.reorder": "Neu anordnen — {label}",
221
224
  "hikari::modal.hiddenLayers": "Verdeckte Ebenen",
222
225
  "hikari::theme.modeTabHint": "Diese Reiter wählen die zu bearbeitende Palette; die appweite Hell/Dunkel-Umschaltung liegt im Modusstreifen des Themen-Popups.",
226
+ "hikari::theme.defaultThemeName": "Standard",
223
227
  "hikari::emptyState.loading": "Wird geladen",
224
228
  "hikari::mfaVerify.title": "Konto verifizieren",
225
229
  "hikari::mfaVerify.verifySubtitle": "{name} wird verifiziert — Anmeldung abschließen, um fortzufahren",
@@ -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",
@@ -220,6 +223,7 @@
220
223
  "hikari::tagInput.reorder": "Reorder {label}",
221
224
  "hikari::modal.hiddenLayers": "Hidden layers",
222
225
  "hikari::theme.modeTabHint": "These tabs pick which palette you are EDITING; to switch the app-wide light/dark, use the mode strip at the top of the theme popup.",
226
+ "hikari::theme.defaultThemeName": "Default",
223
227
  "hikari::emptyState.loading": "Loading",
224
228
  "hikari::mfaVerify.title": "Verify account",
225
229
  "hikari::mfaVerify.verifySubtitle": "Verifying {name} — complete a sign-in method to continue",
@@ -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",
@@ -220,6 +223,7 @@
220
223
  "hikari::tagInput.reorder": "Reordenar — {label}",
221
224
  "hikari::modal.hiddenLayers": "Capas ocultas",
222
225
  "hikari::theme.modeTabHint": "Estas pestañas eligen la paleta que estás EDITANDO; para cambiar el modo claro/oscuro de toda la app, usa la franja de modos de la parte superior del panel de temas.",
226
+ "hikari::theme.defaultThemeName": "Predeterminado",
223
227
  "hikari::emptyState.loading": "Cargando",
224
228
  "hikari::mfaVerify.title": "Verificar cuenta",
225
229
  "hikari::mfaVerify.verifySubtitle": "Verificando {name}: completa un método de acceso para continuar",
@@ -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",
@@ -220,6 +223,7 @@
220
223
  "hikari::tagInput.reorder": "Réorganiser — {label}",
221
224
  "hikari::modal.hiddenLayers": "Couches masquées",
222
225
  "hikari::theme.modeTabHint": "Ces onglets choisissent la palette éditée ; pour basculer clair/sombre dans toute l’app, utilisez la barre de mode du menu de thème.",
226
+ "hikari::theme.defaultThemeName": "Par défaut",
223
227
  "hikari::emptyState.loading": "Chargement",
224
228
  "hikari::mfaVerify.title": "Vérifier le compte",
225
229
  "hikari::mfaVerify.verifySubtitle": "Vérification de {name} — terminez une méthode de connexion pour continuer",
@@ -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": "オプション",
@@ -220,6 +223,7 @@
220
223
  "hikari::tagInput.reorder": "並べ替え — {label}",
221
224
  "hikari::modal.hiddenLayers": "非表示の階層",
222
225
  "hikari::theme.modeTabHint": "このタブは編集対象のパレットを選ぶだけです。アプリ全体の明/暗はテーマポップアップ上部のモードストリップで切り替えてください。",
226
+ "hikari::theme.defaultThemeName": "デフォルト",
223
227
  "hikari::emptyState.loading": "読み込み中",
224
228
  "hikari::mfaVerify.title": "アカウントの確認",
225
229
  "hikari::mfaVerify.verifySubtitle": "{name} の本人確認を続行します",
@@ -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": "옵션",
@@ -220,6 +223,7 @@
220
223
  "hikari::tagInput.reorder": "순서 변경 — {label}",
221
224
  "hikari::modal.hiddenLayers": "숨겨진 레이어",
222
225
  "hikari::theme.modeTabHint": "이 탭은 편집할 팔레트를 고를 뿐입니다. 앱 전체 밝기/어둠은 테마 팝업 상단의 모드 스트립에서 바꾸세요.",
226
+ "hikari::theme.defaultThemeName": "기본값",
223
227
  "hikari::emptyState.loading": "불러오는 중",
224
228
  "hikari::mfaVerify.title": "계정 확인",
225
229
  "hikari::mfaVerify.verifySubtitle": "{name} 님의 신원을 확인하여 로그인을 계속하세요",
@@ -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",
@@ -220,6 +223,7 @@
220
223
  "hikari::tagInput.reorder": "Reordenar — {label}",
221
224
  "hikari::modal.hiddenLayers": "Camadas ocultas",
222
225
  "hikari::theme.modeTabHint": "Estas abas escolhem a paleta que você está EDITANDO; para alternar o claro/escuro do app inteiro, use a faixa de modos no topo do painel de temas.",
226
+ "hikari::theme.defaultThemeName": "Padrão",
223
227
  "hikari::emptyState.loading": "Carregando",
224
228
  "hikari::mfaVerify.title": "Verificar conta",
225
229
  "hikari::mfaVerify.verifySubtitle": "Verificando {name} — conclua um método de acesso para continuar",
@@ -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": "Параметры",
@@ -220,6 +223,7 @@
220
223
  "hikari::tagInput.reorder": "Изменить порядок — {label}",
221
224
  "hikari::modal.hiddenLayers": "Скрытые слои",
222
225
  "hikari::theme.modeTabHint": "Вкладки выбирают редактируемую палитру; общесистемное переключение светлой/тёмной — в полосе режимов вверху меню темы.",
226
+ "hikari::theme.defaultThemeName": "По умолчанию",
223
227
  "hikari::emptyState.loading": "Загрузка",
224
228
  "hikari::mfaVerify.title": "Подтверждение аккаунта",
225
229
  "hikari::mfaVerify.verifySubtitle": "Проверка {name} — завершите вход, чтобы продолжить",
@@ -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": "搜索",
@@ -224,6 +227,7 @@
224
227
  "hikari::tagInput.reorder": "拖动排序 — {label}",
225
228
  "hikari::modal.hiddenLayers": "隐藏层级",
226
229
  "hikari::theme.modeTabHint": "切换这里编辑的是对应模式的调色板;要切换应用整体深/浅,请用主题弹窗顶部的模式条。",
230
+ "hikari::theme.defaultThemeName": "默认",
227
231
  "hikari::emptyState.loading": "加载中",
228
232
  "hikari::mfaVerify.title": "验证账户",
229
233
  "hikari::mfaVerify.verifySubtitle": "正在验证 {name} 的身份,请完成验证以继续登录",