@celestia-island/hikari 0.54.8 → 0.55.0
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/DemoApp.tsx +5 -3
- package/src/animation/registerAnimations.ts +2 -2
- package/src/components/HkDrawer.test.tsx +57 -0
- package/src/components/HkDrawer.tsx +6 -1
- package/src/components/HkInput.password.test.tsx +821 -0
- package/src/components/HkInput.scss +4 -33
- package/src/components/HkInput.tsx +91 -31
- package/src/components/HkKanban.scss +81 -0
- package/src/components/HkKanban.test.tsx +219 -0
- package/src/components/HkKanban.tsx +264 -0
- package/src/components/HkModal.test.tsx +76 -0
- package/src/components/HkModal.tsx +8 -1
- package/src/components/HkModalBreadcrumb.overflow.contract.test.ts +115 -0
- package/src/components/HkModalBreadcrumb.scss +114 -2
- package/src/components/HkModalBreadcrumb.test.tsx +549 -6
- package/src/components/HkModalBreadcrumb.tsx +433 -37
- package/src/components/{HkPasswordInput.scss → HkPasswordSurface.scss} +93 -57
- package/src/components/HkPasswordSurface.styles.test.ts +68 -0
- package/src/components/HkPasswordSurface.tsx +1006 -0
- package/src/components/HkPopover.tsx +8 -0
- package/src/components/HkPopoverSheet.test.tsx +21 -0
- package/src/components/HkSelectPanel.test.tsx +21 -0
- package/src/components/HkSelectPanel.tsx +3 -0
- package/src/components/HkSignInCard.tsx +6 -6
- package/src/components/HkTooltip.test.tsx +67 -0
- package/src/components/HkTooltip.tsx +54 -1
- package/src/i18n/flatKeyParity.test.ts +97 -0
- package/src/i18n/locales/ar/components.json +9 -2
- package/src/i18n/locales/de/components.json +9 -2
- package/src/i18n/locales/en/components.json +4 -2
- package/src/i18n/locales/es/components.json +9 -2
- package/src/i18n/locales/fr/components.json +9 -2
- package/src/i18n/locales/ja/components.json +9 -2
- package/src/i18n/locales/ko/components.json +9 -2
- package/src/i18n/locales/pt/components.json +9 -2
- package/src/i18n/locales/ru/components.json +9 -2
- package/src/i18n/locales/zh-Hans/components.json +9 -7
- package/src/i18n/locales/zh-Hant/components.json +9 -7
- package/src/i18n/modalKeys.test.ts +59 -0
- package/src/index.ts +8 -3
- package/src/runtime/backStack.test.ts +171 -0
- package/src/runtime/backStack.ts +118 -39
- package/src/runtime/credentialAutofill.test.ts +4 -4
- package/src/runtime/displayWidth.test.ts +102 -0
- package/src/runtime/displayWidth.ts +76 -0
- package/src/runtime/index.ts +6 -0
- package/src/runtime/usePopupManager.test.ts +60 -0
- package/src/runtime/usePopupManager.ts +42 -1
- package/src/utils/password.ts +9 -0
- package/src/components/HkPasswordInput.test.ts +0 -329
- package/src/components/HkPasswordInput.tsx +0 -820
package/package.json
CHANGED
package/src/DemoApp.tsx
CHANGED
|
@@ -8,7 +8,7 @@ import { utf8ToBase64 } from "./utils/base64";
|
|
|
8
8
|
import {
|
|
9
9
|
HButton, HIconButton, HIconButtonGroup, HTooltip, HBadge, HTag, HIcon, HSpinner,
|
|
10
10
|
HProgressBar, HProgressRing, HGaugeRing,
|
|
11
|
-
HInput, HSearchInput, HNumberInput,
|
|
11
|
+
HInput, HSearchInput, HNumberInput, HTextarea,
|
|
12
12
|
HFileField,
|
|
13
13
|
HFilePickerField,
|
|
14
14
|
type PickedFile, type RemoteFsAdapter,
|
|
@@ -360,13 +360,15 @@ export default defineComponent({
|
|
|
360
360
|
</section>
|
|
361
361
|
|
|
362
362
|
<section>
|
|
363
|
-
<h2>HInput /
|
|
363
|
+
<h2>HInput (text / password) / HSearchInput / HNumberInput / HTextarea</h2>
|
|
364
364
|
<div class="form-grid">
|
|
365
365
|
<HInput modelValue={form.value.text} onUpdate:modelValue={(v: string) => (form.value.text = v)} placeholder="Text input" />
|
|
366
366
|
<HInput modelValue={form.value.text} onUpdate:modelValue={(v: string) => (form.value.text = v)} placeholder="Disabled" disabled />
|
|
367
367
|
<HSearchInput modelValue={form.value.search} onUpdate:modelValue={(v: string | number) => (form.value.search = String(v))} placeholder="Search..." />
|
|
368
368
|
<HNumberInput modelValue={form.value.number} onUpdate:modelValue={(v: number) => (form.value.number = v)} placeholder="Number" />
|
|
369
|
-
<
|
|
369
|
+
<HInput variant="password" modelValue={form.value.password} onUpdate:modelValue={(v: string) => (form.value.password = v)} placeholder="Password (hold the eye)" />
|
|
370
|
+
<HInput variant="password" passwordTrailing="strength" modelValue={form.value.password} onUpdate:modelValue={(v: string) => (form.value.password = v)} placeholder="Password (strength light)" />
|
|
371
|
+
<HInput variant="password" passwordTrailing="none" modelValue={form.value.password} onUpdate:modelValue={(v: string) => (form.value.password = v)} placeholder="Password (no affordance)" />
|
|
370
372
|
<HTextarea modelValue={form.value.textarea} onUpdate:modelValue={(v: string) => (form.value.textarea = v)} placeholder="Textarea" rows={3} />
|
|
371
373
|
</div>
|
|
372
374
|
{anyForm.value ? <p class="result">Form: {anyForm.value}</p> : null}
|
|
@@ -82,9 +82,9 @@ registerCssAnimation("hk-skeleton-shimmer", { infinite: true });
|
|
|
82
82
|
registerCssAnimation("hk-image-preview-shimmer", { infinite: true });
|
|
83
83
|
// components/HkProgressBar.scss — indeterminate bar sweep (loops forever).
|
|
84
84
|
registerCssAnimation("hk-progress-indeterminate", { infinite: true });
|
|
85
|
-
// components/
|
|
85
|
+
// components/HkPasswordSurface.scss — caps-lock warning flash (plays once).
|
|
86
86
|
registerCssAnimation("hk-pwd-flash");
|
|
87
|
-
// components/
|
|
87
|
+
// components/HkPasswordSurface.scss — breathing hint glow (loops forever).
|
|
88
88
|
registerCssAnimation("hk-pwd-breathe", { infinite: true });
|
|
89
89
|
// components/HkPickerPane.scss — date/time picker view drill forward
|
|
90
90
|
// (plays once, shared by HkDatePicker and HkDateTimePicker).
|
|
@@ -2,6 +2,7 @@ import { afterEach, describe, expect, it } from "vitest";
|
|
|
2
2
|
import { createApp, defineComponent, h, nextTick, ref } from "vue";
|
|
3
3
|
|
|
4
4
|
import HkDrawer from "./HkDrawer";
|
|
5
|
+
import { usePopupManager } from "../runtime/usePopupManager";
|
|
5
6
|
|
|
6
7
|
const mounts: ReturnType<typeof createApp>[] = [];
|
|
7
8
|
const containers: HTMLElement[] = [];
|
|
@@ -89,3 +90,59 @@ describe("HkDrawer back-guard (window-first back priority)", () => {
|
|
|
89
90
|
app.unmount();
|
|
90
91
|
});
|
|
91
92
|
});
|
|
93
|
+
|
|
94
|
+
describe("HkDrawer window-stack close channel", () => {
|
|
95
|
+
function mount(open: { value: boolean }, closable: boolean, title: string) {
|
|
96
|
+
const container = document.createElement("div");
|
|
97
|
+
document.body.appendChild(container);
|
|
98
|
+
containers.push(container);
|
|
99
|
+
const Wrapper = defineComponent({
|
|
100
|
+
setup() {
|
|
101
|
+
return () =>
|
|
102
|
+
h(HkDrawer, {
|
|
103
|
+
modelValue: open.value,
|
|
104
|
+
closable,
|
|
105
|
+
title,
|
|
106
|
+
"onUpdate:modelValue": (v: boolean) => { open.value = v; },
|
|
107
|
+
}, { default: () => h("div", "content") });
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
const app = createApp(Wrapper);
|
|
111
|
+
mounts.push(app);
|
|
112
|
+
app.mount(container);
|
|
113
|
+
return app;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
it("closes through the popup manager when the stack navigates back", async () => {
|
|
117
|
+
const manager = usePopupManager();
|
|
118
|
+
const below = manager.register("modal", true, "Below");
|
|
119
|
+
try {
|
|
120
|
+
const open = ref(true);
|
|
121
|
+
mount(open, true, "Details");
|
|
122
|
+
await nextTick();
|
|
123
|
+
|
|
124
|
+
expect(manager.closeAbove(below.id)).toBe(1);
|
|
125
|
+
await nextTick();
|
|
126
|
+
expect(open.value).toBe(false);
|
|
127
|
+
} finally {
|
|
128
|
+
manager.unregister(below.id);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("cannot close a non-closable drawer", async () => {
|
|
133
|
+
const manager = usePopupManager();
|
|
134
|
+
const below = manager.register("modal", true, "Below");
|
|
135
|
+
try {
|
|
136
|
+
const open = ref(true);
|
|
137
|
+
mount(open, false, "Locked");
|
|
138
|
+
await nextTick();
|
|
139
|
+
|
|
140
|
+
// Asked, but the drawer refuses — exactly as it does for Escape.
|
|
141
|
+
expect(manager.closeAbove(below.id)).toBe(1);
|
|
142
|
+
await nextTick();
|
|
143
|
+
expect(open.value).toBe(true);
|
|
144
|
+
} finally {
|
|
145
|
+
manager.unregister(below.id);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
});
|
|
@@ -126,7 +126,12 @@ export default defineComponent({
|
|
|
126
126
|
// Register with the drawer title so the modal-stack breadcrumb
|
|
127
127
|
// labels this layer by name — a drawer is a window on every
|
|
128
128
|
// form factor and must never fall back to a generic label.
|
|
129
|
-
|
|
129
|
+
// Close channel for the modal-stack breadcrumb (see
|
|
130
|
+
// usePopupManager): the drawer owns its dismissal, and a
|
|
131
|
+
// non-closable drawer refuses like it does for Escape.
|
|
132
|
+
handle.value = manager.register("drawer", true, props.title, false, () => {
|
|
133
|
+
if (props.closable) close();
|
|
134
|
+
});
|
|
130
135
|
overlayHook.open();
|
|
131
136
|
previouslyFocused = document.activeElement as HTMLElement | null;
|
|
132
137
|
if (backGuardEnabled() && backGuard.entries === 0) {
|