@hina-ui/vue 1.7.7 → 1.7.9
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/dist/index.js +1338 -562
- package/dist/index.js.map +1 -1
- package/dist/shared/behavior/anchor-follow.ts +20 -11
- package/dist/shared/behavior/form.ts +5 -9
- package/dist/shared/lib/command-palette/match.ts +9 -0
- package/dist/shared/lib/line-clamp.ts +76 -0
- package/dist/shared/lib/scroll-restore.ts +163 -0
- package/dist/shared/locale/en-US.ts +4 -0
- package/dist/shared/locale/index.ts +2 -0
- package/dist/shared/locale/ja-JP.ts +229 -0
- package/dist/shared/locale/types.ts +4 -0
- package/dist/shared/locale/zh-CN.ts +4 -0
- package/dist/shared/styles/density.css +4 -0
- package/dist/shared/styles/line-clamp.css +98 -0
- package/dist/shared/styles/tokens.css +1 -0
- package/dist/shared/styles/typography.css +18 -0
- package/dist/shared/variants/button.ts +2 -0
- package/dist/shared/variants/command-palette.ts +4 -0
- package/dist/shared/variants/line-clamp.ts +13 -0
- package/dist/shared/variants/tag.ts +1 -0
- package/dist/types/shared/src/behavior/anchor-follow.d.ts.map +1 -1
- package/dist/types/shared/src/behavior/form.d.ts.map +1 -1
- package/dist/types/shared/src/lib/command-palette/match.d.ts +5 -0
- package/dist/types/shared/src/lib/command-palette/match.d.ts.map +1 -1
- package/dist/types/shared/src/lib/line-clamp.d.ts +6 -0
- package/dist/types/shared/src/lib/line-clamp.d.ts.map +1 -0
- package/dist/types/shared/src/lib/scroll-restore.d.ts +16 -0
- package/dist/types/shared/src/lib/scroll-restore.d.ts.map +1 -1
- package/dist/types/shared/src/locale/en-US.d.ts.map +1 -1
- package/dist/types/shared/src/locale/index.d.ts +1 -0
- package/dist/types/shared/src/locale/index.d.ts.map +1 -1
- package/dist/types/shared/src/locale/ja-JP.d.ts +3 -0
- package/dist/types/shared/src/locale/ja-JP.d.ts.map +1 -0
- package/dist/types/shared/src/locale/types.d.ts +4 -0
- package/dist/types/shared/src/locale/types.d.ts.map +1 -1
- package/dist/types/shared/src/locale/zh-CN.d.ts.map +1 -1
- package/dist/types/shared/src/variants/button.d.ts +6 -0
- package/dist/types/shared/src/variants/button.d.ts.map +1 -1
- package/dist/types/shared/src/variants/command-palette.d.ts +1 -0
- package/dist/types/shared/src/variants/command-palette.d.ts.map +1 -1
- package/dist/types/shared/src/variants/line-clamp.d.ts +4 -0
- package/dist/types/shared/src/variants/line-clamp.d.ts.map +1 -0
- package/dist/types/shared/src/variants/tag.d.ts +3 -0
- package/dist/types/shared/src/variants/tag.d.ts.map +1 -1
- package/dist/types/shared/src/variants/toggle.d.ts +7 -0
- package/dist/types/shared/src/variants/toggle.d.ts.map +1 -1
- package/dist/types/vue/src/components/app-shell/AppShell.vue.d.ts +2 -2
- package/dist/types/vue/src/components/app-shell/AppShell.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/close-button/CloseButton.vue.d.ts +1 -1
- package/dist/types/vue/src/components/command-palette/CommandPalette.vue.d.ts +40 -34
- package/dist/types/vue/src/components/command-palette/CommandPalette.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/command-palette/CommandPaletteInput.vue.d.ts +8 -0
- package/dist/types/vue/src/components/command-palette/CommandPaletteInput.vue.d.ts.map +1 -0
- package/dist/types/vue/src/components/command-palette/CommandPaletteItem.vue.d.ts +21 -7
- package/dist/types/vue/src/components/command-palette/CommandPaletteItem.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/command-palette/CommandPalettePanel.vue.d.ts +37 -31
- package/dist/types/vue/src/components/command-palette/CommandPalettePanel.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/command-palette/composables/useCommandItems.d.ts +6 -6
- package/dist/types/vue/src/components/command-palette/composables/useCommandItems.d.ts.map +1 -1
- package/dist/types/vue/src/components/command-palette/context.d.ts +11 -0
- package/dist/types/vue/src/components/command-palette/context.d.ts.map +1 -0
- package/dist/types/vue/src/components/command-palette/types.d.ts +16 -5
- package/dist/types/vue/src/components/command-palette/types.d.ts.map +1 -1
- package/dist/types/vue/src/components/command-palette/utils/match.d.ts +3 -3
- package/dist/types/vue/src/components/command-palette/utils/match.d.ts.map +1 -1
- package/dist/types/vue/src/components/copy-button/CopyButton.vue.d.ts +1 -1
- package/dist/types/vue/src/components/description-list/DescriptionList.vue.d.ts +1 -0
- package/dist/types/vue/src/components/description-list/DescriptionList.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/dialog/Dialog.vue.d.ts +3 -0
- package/dist/types/vue/src/components/dialog/Dialog.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/drawer/Drawer.vue.d.ts +3 -0
- package/dist/types/vue/src/components/drawer/Drawer.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/form/Form.vue.d.ts +5 -0
- package/dist/types/vue/src/components/form/Form.vue.d.ts.map +1 -1
- package/dist/types/vue/src/components/form/scope.d.ts +4 -0
- package/dist/types/vue/src/components/form/scope.d.ts.map +1 -0
- package/dist/types/vue/src/components/line-clamp/LineClamp.vue.d.ts +28 -0
- package/dist/types/vue/src/components/line-clamp/LineClamp.vue.d.ts.map +1 -0
- package/dist/types/vue/src/components/line-clamp/line-clamp.variants.d.ts +2 -0
- package/dist/types/vue/src/components/line-clamp/line-clamp.variants.d.ts.map +1 -0
- package/dist/types/vue/src/components/sheet/Sheet.vue.d.ts +3 -0
- package/dist/types/vue/src/components/sheet/Sheet.vue.d.ts.map +1 -1
- package/dist/types/vue/src/index.d.ts +6 -4
- package/dist/types/vue/src/index.d.ts.map +1 -1
- package/dist/types/vue/src/locale/index.d.ts +1 -1
- package/dist/types/vue/src/locale/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/app-shell/AppShell.vue +54 -4
- package/src/components/command-palette/CommandPalette.vue +53 -16
- package/src/components/command-palette/CommandPaletteInput.vue +32 -0
- package/src/components/command-palette/CommandPaletteItem.vue +7 -5
- package/src/components/command-palette/CommandPalettePanel.vue +95 -34
- package/src/components/command-palette/composables/useCommandItems.ts +16 -14
- package/src/components/command-palette/context.ts +28 -0
- package/src/components/command-palette/types.ts +21 -5
- package/src/components/command-palette/utils/match.ts +6 -3
- package/src/components/description-list/DescriptionList.vue +8 -2
- package/src/components/dialog/Dialog.vue +13 -8
- package/src/components/drawer/Drawer.vue +13 -8
- package/src/components/form/Form.vue +14 -1
- package/src/components/form/scope.ts +39 -0
- package/src/components/line-clamp/LineClamp.vue +105 -0
- package/src/components/line-clamp/line-clamp.variants.ts +1 -0
- package/src/components/sheet/Sheet.vue +14 -10
- package/src/index.ts +16 -2
- package/src/locale/index.ts +1 -1
|
@@ -24,9 +24,16 @@ export interface AnchorFollowResult {
|
|
|
24
24
|
viewport: HTMLElement | undefined
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
const FLIGHT_MS = 1500
|
|
28
|
+
|
|
27
29
|
export function createAnchorFollow() {
|
|
28
30
|
let lastCurrent: string | undefined
|
|
29
31
|
let lastEnd: string | undefined
|
|
32
|
+
let flight: { port: HTMLElement; top: number; until: number } | undefined
|
|
33
|
+
|
|
34
|
+
function land(event: Event) {
|
|
35
|
+
if (flight?.port === event.currentTarget) flight = undefined
|
|
36
|
+
}
|
|
30
37
|
|
|
31
38
|
function follow({
|
|
32
39
|
nav,
|
|
@@ -47,13 +54,18 @@ export function createAnchorFollow() {
|
|
|
47
54
|
if (!port || port.clientHeight <= 0 || port.scrollHeight <= port.clientHeight) return result
|
|
48
55
|
|
|
49
56
|
const box = port.getBoundingClientRect()
|
|
50
|
-
let row: Pick<DOMRect, 'top' | 'bottom' | 'height'> = link.getBoundingClientRect()
|
|
51
57
|
const scale = port.offsetHeight ? box.height / port.offsetHeight : 1
|
|
52
58
|
if (scale <= 0) return result
|
|
59
|
+
const now = performance.now()
|
|
60
|
+
if (flight && (flight.port !== port || now > flight.until)) flight = undefined
|
|
61
|
+
const base = flight ? flight.top : port.scrollTop
|
|
62
|
+
const ahead = (base - port.scrollTop) * scale
|
|
63
|
+
const rect = link.getBoundingClientRect()
|
|
64
|
+
let row = { top: rect.top - ahead, bottom: rect.bottom - ahead, height: rect.height }
|
|
53
65
|
if (endId !== id) {
|
|
54
66
|
const end = nav.querySelector<HTMLElement>(`a[href="#${CSS.escape(endId)}"]`)
|
|
55
67
|
if (end?.getClientRects().length) {
|
|
56
|
-
const bottom = end.getBoundingClientRect().bottom
|
|
68
|
+
const bottom = end.getBoundingClientRect().bottom - ahead
|
|
57
69
|
const height = bottom - row.top
|
|
58
70
|
if (height >= row.height && height <= port.clientHeight * scale)
|
|
59
71
|
row = { top: row.top, bottom, height }
|
|
@@ -79,15 +91,12 @@ export function createAnchorFollow() {
|
|
|
79
91
|
row.height > bottom - top || row.top < top
|
|
80
92
|
? (row.top - top) / scale - before
|
|
81
93
|
: (row.bottom - bottom) / scale + after
|
|
82
|
-
const next = Math.max(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (
|
|
87
|
-
port.scrollTo({
|
|
88
|
-
top: next,
|
|
89
|
-
behavior: changed && !prefersReducedMotion() ? 'smooth' : 'instant',
|
|
90
|
-
})
|
|
94
|
+
const next = Math.max(0, Math.min(port.scrollHeight - port.clientHeight, base + delta))
|
|
95
|
+
if (Math.abs(next - base) < 1) return result
|
|
96
|
+
const smooth = changed && !prefersReducedMotion()
|
|
97
|
+
flight = smooth ? { port, top: next, until: now + FLIGHT_MS } : undefined
|
|
98
|
+
if (smooth) port.addEventListener('scrollend', land, { once: true })
|
|
99
|
+
port.scrollTo({ top: next, behavior: smooth ? 'smooth' : 'instant' })
|
|
91
100
|
return result
|
|
92
101
|
}
|
|
93
102
|
|
|
@@ -37,7 +37,7 @@ export function createForm(options: FormOptions): FormController {
|
|
|
37
37
|
let submitted = false
|
|
38
38
|
let submitting = false
|
|
39
39
|
let server = new Map<string, ServerError>()
|
|
40
|
-
let pending: { values: FormValues
|
|
40
|
+
let pending: { values: FormValues } | undefined
|
|
41
41
|
let validation = 0
|
|
42
42
|
let submission = 0
|
|
43
43
|
let initial = snapshot(options.values()) as FormValues
|
|
@@ -75,14 +75,11 @@ export function createForm(options: FormOptions): FormController {
|
|
|
75
75
|
async function validate() {
|
|
76
76
|
const current = ++validation
|
|
77
77
|
const values = snapshot(options.values()) as FormValues
|
|
78
|
-
const
|
|
79
|
-
const request = { values, rules }
|
|
78
|
+
const request = { values }
|
|
80
79
|
pending = request
|
|
81
80
|
try {
|
|
82
|
-
const result = await runRules(rules, values)
|
|
83
|
-
if (current !== validation ||
|
|
84
|
-
return false
|
|
85
|
-
}
|
|
81
|
+
const result = await runRules(options.rules(), values)
|
|
82
|
+
if (current !== validation || !same(values, options.values())) return false
|
|
86
83
|
found = result
|
|
87
84
|
notify()
|
|
88
85
|
return Object.keys(result).length === 0
|
|
@@ -92,8 +89,7 @@ export function createForm(options: FormOptions): FormController {
|
|
|
92
89
|
}
|
|
93
90
|
|
|
94
91
|
function revalidate() {
|
|
95
|
-
if (pending &&
|
|
96
|
-
return
|
|
92
|
+
if (pending && same(pending.values, options.values())) return
|
|
97
93
|
void validate()
|
|
98
94
|
}
|
|
99
95
|
|
|
@@ -90,3 +90,12 @@ export function filterCommands<T extends CommandMatchable>(
|
|
|
90
90
|
if (q) sections.sort((a, b) => b.best - a.best)
|
|
91
91
|
return sections.map(({ key, label, matches }) => ({ key, label, matches }))
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
export interface CommandMatchRange {
|
|
95
|
+
start: number
|
|
96
|
+
end: number
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function commandMatchRange(match: CommandMatch): CommandMatchRange | null {
|
|
100
|
+
return match.start < 0 ? null : { start: match.start, end: match.end }
|
|
101
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export const LINE_CLAMP_DEFAULT = 3
|
|
2
|
+
|
|
3
|
+
export function lineClampCount(lines: number | undefined) {
|
|
4
|
+
if (lines === undefined || !Number.isFinite(lines)) return LINE_CLAMP_DEFAULT
|
|
5
|
+
return Math.max(1, Math.floor(lines))
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function measureHeights(content: HTMLElement) {
|
|
9
|
+
content.setAttribute('data-measuring', '')
|
|
10
|
+
const collapsed = content.clientHeight
|
|
11
|
+
const full = content.scrollHeight
|
|
12
|
+
content.removeAttribute('data-measuring')
|
|
13
|
+
return { collapsed, full }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function measureLineClamp(content: HTMLElement) {
|
|
17
|
+
if (content.hasAttribute('data-animating')) return null
|
|
18
|
+
const { collapsed, full } = measureHeights(content)
|
|
19
|
+
return full - collapsed > 1
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function toMs(value: string) {
|
|
23
|
+
const amount = Number.parseFloat(value)
|
|
24
|
+
if (Number.isNaN(amount)) return 0
|
|
25
|
+
return value.trim().endsWith('ms') ? amount : amount * 1000
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const FADE = '--hn-line-clamp-fade'
|
|
29
|
+
|
|
30
|
+
export function animateLineClamp(content: HTMLElement, expanded: boolean, done: () => void) {
|
|
31
|
+
const running = content.style.maxHeight !== ''
|
|
32
|
+
const current = running ? content.getBoundingClientRect().height : undefined
|
|
33
|
+
const fade = running ? getComputedStyle(content).getPropertyValue(FADE) : ''
|
|
34
|
+
|
|
35
|
+
content.style.transition = 'none'
|
|
36
|
+
const { collapsed, full } = measureHeights(content)
|
|
37
|
+
const from = current ?? (expanded ? collapsed : full)
|
|
38
|
+
const to = expanded ? full : collapsed
|
|
39
|
+
content.toggleAttribute('data-expanded', !expanded)
|
|
40
|
+
if (fade) content.style.setProperty(FADE, fade)
|
|
41
|
+
content.style.maxHeight = `${from}px`
|
|
42
|
+
content.setAttribute('data-animating', '')
|
|
43
|
+
void content.offsetHeight
|
|
44
|
+
content.style.transition = ''
|
|
45
|
+
content.style.removeProperty(FADE)
|
|
46
|
+
content.toggleAttribute('data-expanded', expanded)
|
|
47
|
+
content.style.maxHeight = `${to}px`
|
|
48
|
+
|
|
49
|
+
let timer: ReturnType<typeof setTimeout> | undefined
|
|
50
|
+
const stop = () => {
|
|
51
|
+
content.removeEventListener('transitionend', onEnd)
|
|
52
|
+
clearTimeout(timer)
|
|
53
|
+
}
|
|
54
|
+
const finish = () => {
|
|
55
|
+
stop()
|
|
56
|
+
content.style.maxHeight = ''
|
|
57
|
+
content.removeAttribute('data-animating')
|
|
58
|
+
done()
|
|
59
|
+
}
|
|
60
|
+
function onEnd(event: TransitionEvent) {
|
|
61
|
+
if (event.target === content && event.propertyName === 'max-height') finish()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (Math.abs(from - to) < 1) {
|
|
65
|
+
finish()
|
|
66
|
+
return stop
|
|
67
|
+
}
|
|
68
|
+
const duration = Math.max(...getComputedStyle(content).transitionDuration.split(',').map(toMs))
|
|
69
|
+
content.addEventListener('transitionend', onEnd)
|
|
70
|
+
timer = setTimeout(finish, duration + 80)
|
|
71
|
+
return stop
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function revealLineClamp(root: HTMLElement | null) {
|
|
75
|
+
root?.scrollIntoView?.({ block: 'nearest' })
|
|
76
|
+
}
|
|
@@ -146,3 +146,166 @@ export function createScrollRestorer(key: string, ports: ScrollRestorerPorts): S
|
|
|
146
146
|
},
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
|
+
|
|
150
|
+
export const SCROLL_FIRST_PAINT_FIELD = '__hnScrollAt'
|
|
151
|
+
|
|
152
|
+
export function scrollRestoreScript() {
|
|
153
|
+
const collect = `(function(){var s=window.${SCROLL_FIRST_PAINT_FIELD}=window.${SCROLL_FIRST_PAINT_FIELD}||{};var e=document.querySelectorAll('[${SCROLL_AT_ATTR}]');for(var i=0;i<e.length;i++){s[e[i].getAttribute('${SCROLL_RESTORE_ATTR}')]=Number(e[i].getAttribute('${SCROLL_AT_ATTR}'));e[i].removeAttribute('${SCROLL_AT_ATTR}')}})()`
|
|
154
|
+
return `${firstPaintRestoreScript()};${collect}`
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface ScrollRestoreSessionOptions {
|
|
158
|
+
key: string
|
|
159
|
+
viewport: HTMLElement
|
|
160
|
+
target: HTMLElement
|
|
161
|
+
initial?: boolean
|
|
162
|
+
onUpdated: (listener: () => void) => () => void
|
|
163
|
+
onScroll: (listener: () => void) => () => void
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface ScrollRestoreSession {
|
|
167
|
+
dispose: () => void
|
|
168
|
+
keep: () => void
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const sessions = new Map<ScrollRestoreSession, string>()
|
|
172
|
+
|
|
173
|
+
export function keepScrollPosition(key?: string) {
|
|
174
|
+
for (const [session, name] of sessions) if (key === undefined || name === key) session.keep()
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const ABANDON_EVENTS = ['wheel', 'touchstart', 'keydown'] as const
|
|
178
|
+
const NAVIGATION_FALLBACK_MS = 500
|
|
179
|
+
|
|
180
|
+
function takeFirstPaint(key: string, target: HTMLElement) {
|
|
181
|
+
const store = (window as unknown as Record<string, Record<string, number> | undefined>)[
|
|
182
|
+
SCROLL_FIRST_PAINT_FIELD
|
|
183
|
+
]
|
|
184
|
+
if (store && key in store) {
|
|
185
|
+
const top = store[key]
|
|
186
|
+
delete store[key]
|
|
187
|
+
return top
|
|
188
|
+
}
|
|
189
|
+
const at = target.getAttribute(SCROLL_AT_ATTR)
|
|
190
|
+
target.removeAttribute(SCROLL_AT_ATTR)
|
|
191
|
+
return at === null ? undefined : Number(at)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function hashTarget() {
|
|
195
|
+
if (!location.hash) return null
|
|
196
|
+
try {
|
|
197
|
+
return document.getElementById(decodeURIComponent(location.hash.slice(1)))
|
|
198
|
+
} catch {
|
|
199
|
+
return null
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function createScrollRestoreSession({
|
|
204
|
+
key,
|
|
205
|
+
viewport,
|
|
206
|
+
target,
|
|
207
|
+
initial = true,
|
|
208
|
+
onUpdated,
|
|
209
|
+
onScroll,
|
|
210
|
+
}: ScrollRestoreSessionOptions): ScrollRestoreSession {
|
|
211
|
+
const page = () => location.pathname + location.search
|
|
212
|
+
const here = () => ({ href: location.href, page: page() })
|
|
213
|
+
const setTimer = (fn: () => void, ms: number) => {
|
|
214
|
+
const id = setTimeout(fn, ms)
|
|
215
|
+
return () => clearTimeout(id)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
let settled = here()
|
|
219
|
+
let navigating = false
|
|
220
|
+
let clearFallback: (() => void) | null = null
|
|
221
|
+
let disposed = false
|
|
222
|
+
let held: number | undefined
|
|
223
|
+
|
|
224
|
+
const restorer = createScrollRestorer(key, {
|
|
225
|
+
getViewport: () => viewport,
|
|
226
|
+
takeFirstPaintTop: () => takeFirstPaint(key, target),
|
|
227
|
+
readState: () => history.state,
|
|
228
|
+
writeState: state => {
|
|
229
|
+
if (!navigating && page() === settled.page) history.replaceState(state, '')
|
|
230
|
+
},
|
|
231
|
+
setTimer,
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
function land(first = false) {
|
|
235
|
+
navigating = false
|
|
236
|
+
clearFallback?.()
|
|
237
|
+
clearFallback = null
|
|
238
|
+
settled = here()
|
|
239
|
+
const keep = held
|
|
240
|
+
held = undefined
|
|
241
|
+
if (!first && keep !== undefined && readScrollRecord(history.state)[key] === undefined)
|
|
242
|
+
history.replaceState(writeScrollRecord(history.state, key, keep), '')
|
|
243
|
+
const saved = readScrollRecord(history.state)[key]
|
|
244
|
+
restorer.restore(first)
|
|
245
|
+
if (!first && saved === undefined) hashTarget()?.scrollIntoView()
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function detect(traversal = false) {
|
|
249
|
+
if (disposed || location.href === settled.href) return
|
|
250
|
+
if (page() === settled.page) {
|
|
251
|
+
settled = here()
|
|
252
|
+
if (traversal && readScrollRecord(history.state)[key] !== undefined) restorer.restore()
|
|
253
|
+
return
|
|
254
|
+
}
|
|
255
|
+
if (navigating) return
|
|
256
|
+
navigating = true
|
|
257
|
+
restorer.abandon()
|
|
258
|
+
clearFallback = setTimer(() => land(), NAVIGATION_FALLBACK_MS)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const check = () => queueMicrotask(() => detect())
|
|
262
|
+
const traverse = () => queueMicrotask(() => detect(true))
|
|
263
|
+
const entryChange = (event: Event) => {
|
|
264
|
+
const traversal = (event as Event & { navigationType?: string }).navigationType === 'traverse'
|
|
265
|
+
queueMicrotask(() => detect(traversal))
|
|
266
|
+
}
|
|
267
|
+
const abandon = () => restorer.abandon()
|
|
268
|
+
const save = () => restorer.save()
|
|
269
|
+
const navigation = (window as Window & { navigation?: EventTarget }).navigation
|
|
270
|
+
|
|
271
|
+
const off = [
|
|
272
|
+
onUpdated(() => {
|
|
273
|
+
detect()
|
|
274
|
+
if (navigating) land()
|
|
275
|
+
else restorer.settle()
|
|
276
|
+
}),
|
|
277
|
+
onScroll(() => {
|
|
278
|
+
detect()
|
|
279
|
+
restorer.saveSoon()
|
|
280
|
+
}),
|
|
281
|
+
]
|
|
282
|
+
for (const name of ABANDON_EVENTS) viewport.addEventListener(name, abandon, { passive: true })
|
|
283
|
+
navigation?.addEventListener('currententrychange', entryChange)
|
|
284
|
+
window.addEventListener('popstate', traverse)
|
|
285
|
+
window.addEventListener('hashchange', check)
|
|
286
|
+
window.addEventListener('pagehide', save)
|
|
287
|
+
document.addEventListener('click', save, true)
|
|
288
|
+
|
|
289
|
+
land(initial)
|
|
290
|
+
|
|
291
|
+
const session: ScrollRestoreSession = {
|
|
292
|
+
keep() {
|
|
293
|
+
held = viewport.scrollTop
|
|
294
|
+
},
|
|
295
|
+
dispose() {
|
|
296
|
+
disposed = true
|
|
297
|
+
sessions.delete(session)
|
|
298
|
+
off.forEach(stop => stop())
|
|
299
|
+
for (const name of ABANDON_EVENTS) viewport.removeEventListener(name, abandon)
|
|
300
|
+
navigation?.removeEventListener('currententrychange', entryChange)
|
|
301
|
+
window.removeEventListener('popstate', traverse)
|
|
302
|
+
window.removeEventListener('hashchange', check)
|
|
303
|
+
window.removeEventListener('pagehide', save)
|
|
304
|
+
document.removeEventListener('click', save, true)
|
|
305
|
+
clearFallback?.()
|
|
306
|
+
restorer.dispose()
|
|
307
|
+
},
|
|
308
|
+
}
|
|
309
|
+
sessions.set(session, key)
|
|
310
|
+
return session
|
|
311
|
+
}
|
|
@@ -44,9 +44,11 @@ export function mergeUiMessages(base: UiMessages, patch: PartialUiMessages): UiM
|
|
|
44
44
|
rating: { ...base.rating, ...patch.rating },
|
|
45
45
|
form: { ...base.form, ...patch.form },
|
|
46
46
|
command: { ...base.command, ...patch.command },
|
|
47
|
+
lineClamp: { ...base.lineClamp, ...patch.lineClamp },
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
export { zhCN } from './zh-CN'
|
|
51
52
|
export { enUS } from './en-US'
|
|
53
|
+
export { jaJP } from './ja-JP'
|
|
52
54
|
export type { UiMessages, PartialUiMessages } from './types'
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import type { UiMessages } from './types'
|
|
2
|
+
|
|
3
|
+
export const jaJP: UiMessages = {
|
|
4
|
+
qrCode: {
|
|
5
|
+
label: 'QRコード',
|
|
6
|
+
empty: 'コンテンツがありません',
|
|
7
|
+
expired: 'QRコードの有効期限が切れました',
|
|
8
|
+
scanned: 'スキャン済み',
|
|
9
|
+
error: 'QRコードを生成できません',
|
|
10
|
+
refresh: 'QRコードを更新',
|
|
11
|
+
},
|
|
12
|
+
carousel: {
|
|
13
|
+
label: 'おすすめコンテンツ',
|
|
14
|
+
role: 'カルーセル',
|
|
15
|
+
slide: 'スライド',
|
|
16
|
+
prev: '前のグループ',
|
|
17
|
+
next: '次のグループ',
|
|
18
|
+
choose: '表示位置を選択',
|
|
19
|
+
play: '自動再生を開始',
|
|
20
|
+
pause: '自動再生を停止',
|
|
21
|
+
empty: 'コンテンツがありません',
|
|
22
|
+
position: (index, total) => `${total} 件中 ${index} 件目`,
|
|
23
|
+
goTo: index => `グループ ${index} に移動`,
|
|
24
|
+
},
|
|
25
|
+
monthGrid: { today: '今月に戻る' },
|
|
26
|
+
masonry: { empty: 'コンテンツがありません' },
|
|
27
|
+
splitButton: { more: 'その他の操作' },
|
|
28
|
+
editable: {
|
|
29
|
+
edit: '編集',
|
|
30
|
+
save: '保存',
|
|
31
|
+
placeholder: 'クリックして編集',
|
|
32
|
+
failed: '保存できませんでした。もう一度お試しください',
|
|
33
|
+
},
|
|
34
|
+
tag: 'ja-JP',
|
|
35
|
+
stepper: {
|
|
36
|
+
label: 'ステップ',
|
|
37
|
+
progress: (step, total) => `ステップ ${step} / ${total}`,
|
|
38
|
+
completed: '完了',
|
|
39
|
+
error: 'このステップにエラーがあります',
|
|
40
|
+
},
|
|
41
|
+
common: {
|
|
42
|
+
close: '閉じる',
|
|
43
|
+
copy: 'コピー',
|
|
44
|
+
copied: 'コピーしました',
|
|
45
|
+
clear: 'クリア',
|
|
46
|
+
loading: '読み込み中',
|
|
47
|
+
confirm: 'OK',
|
|
48
|
+
cancel: 'キャンセル',
|
|
49
|
+
},
|
|
50
|
+
banner: {
|
|
51
|
+
prev: '前のお知らせ',
|
|
52
|
+
next: '次のお知らせ',
|
|
53
|
+
},
|
|
54
|
+
pagination: {
|
|
55
|
+
rangeLabel: (from, to, total) =>
|
|
56
|
+
total ? String(from) + '–' + to + ' / 全 ' + total + ' 件' : '全 0 件',
|
|
57
|
+
pageCountLabel: (page, count) => page + ' / ' + count + ' ページ',
|
|
58
|
+
pageSizeLabel: '1 ページあたりの件数',
|
|
59
|
+
pageSizeOption: n => String(n) + ' 件 / ページ',
|
|
60
|
+
jumpLabel: 'ページへ移動',
|
|
61
|
+
previousPagesLabel: n => n + ' ページ戻る',
|
|
62
|
+
nextPagesLabel: n => n + ' ページ進む',
|
|
63
|
+
choosePage: 'ページを選択',
|
|
64
|
+
choosePageHint: '上下の矢印キーでページを選択',
|
|
65
|
+
navLabel: 'ページネーション',
|
|
66
|
+
prev: '前のページ',
|
|
67
|
+
next: '次のページ',
|
|
68
|
+
first: '最初のページ',
|
|
69
|
+
last: '最後のページ',
|
|
70
|
+
pageLabel: n => `${n} ページ`,
|
|
71
|
+
totalLabel: n => `全 ${n} 件`,
|
|
72
|
+
},
|
|
73
|
+
table: {
|
|
74
|
+
edit: '編集',
|
|
75
|
+
save: '保存',
|
|
76
|
+
cancel: 'キャンセル',
|
|
77
|
+
editFailed: '保存できませんでした。もう一度お試しください',
|
|
78
|
+
selectPage: '現在のページを選択',
|
|
79
|
+
selectFiltered: '絞り込み結果を選択',
|
|
80
|
+
expand: '展開',
|
|
81
|
+
collapse: '折りたたむ',
|
|
82
|
+
moveRow: '行を移動',
|
|
83
|
+
moveColumn: '列を移動',
|
|
84
|
+
resizeColumn: '列幅を調整',
|
|
85
|
+
|
|
86
|
+
noColumns: '表示する列がありません',
|
|
87
|
+
empty: 'データがありません',
|
|
88
|
+
loading: '読み込み中',
|
|
89
|
+
sortAsc: '昇順で並べ替え',
|
|
90
|
+
sortDesc: '降順で並べ替え',
|
|
91
|
+
sortNone: '並べ替えを解除',
|
|
92
|
+
selectRow: 'この行を選択',
|
|
93
|
+
selectAll: 'すべて選択',
|
|
94
|
+
},
|
|
95
|
+
select: {
|
|
96
|
+
placeholder: '選択してください',
|
|
97
|
+
empty: '一致する項目がありません',
|
|
98
|
+
optionCountLabel: n => `${n} 件の選択肢があります`,
|
|
99
|
+
},
|
|
100
|
+
upload: {
|
|
101
|
+
choose: 'ファイルを選択',
|
|
102
|
+
dropHint: 'ここにファイルをドロップ、またはクリックして選択',
|
|
103
|
+
tooLargeLabel: readableSize => `ファイルが上限の ${readableSize} を超えています`,
|
|
104
|
+
remove: '削除',
|
|
105
|
+
removeFile: name => `${name} を削除`,
|
|
106
|
+
},
|
|
107
|
+
time: {
|
|
108
|
+
justNow: 'たった今',
|
|
109
|
+
unknown: '日時不明',
|
|
110
|
+
},
|
|
111
|
+
virtualList: { empty: 'データがありません' },
|
|
112
|
+
dataList: {
|
|
113
|
+
empty: 'データがありません',
|
|
114
|
+
list: 'リスト表示',
|
|
115
|
+
grid: 'グリッド表示',
|
|
116
|
+
layout: '表示レイアウト',
|
|
117
|
+
},
|
|
118
|
+
scroll: {
|
|
119
|
+
regionLabel: 'スクロール可能な領域',
|
|
120
|
+
backToTop: 'ページの先頭へ戻る',
|
|
121
|
+
},
|
|
122
|
+
toast: {
|
|
123
|
+
regionLabel: '通知',
|
|
124
|
+
},
|
|
125
|
+
spoiler: {
|
|
126
|
+
revealLabel: 'ネタバレを含みます。クリックして表示',
|
|
127
|
+
hideLabel: 'ネタバレを隠す',
|
|
128
|
+
},
|
|
129
|
+
codeblock: {
|
|
130
|
+
copy: 'コードをコピー',
|
|
131
|
+
},
|
|
132
|
+
splitter: {
|
|
133
|
+
handleLabel: 'パネルのサイズを調整',
|
|
134
|
+
},
|
|
135
|
+
sidebar: {
|
|
136
|
+
navLabel: 'サイドバーナビゲーション',
|
|
137
|
+
toggleLabel: 'サイドバーを切り替え',
|
|
138
|
+
},
|
|
139
|
+
anchor: {
|
|
140
|
+
navLabel: 'このページの目次',
|
|
141
|
+
},
|
|
142
|
+
breadcrumb: {
|
|
143
|
+
navLabel: 'パンくずリスト',
|
|
144
|
+
},
|
|
145
|
+
lightbox: {
|
|
146
|
+
zoomIn: '拡大',
|
|
147
|
+
zoomOut: '縮小',
|
|
148
|
+
resetZoom: 'ウィンドウに合わせる',
|
|
149
|
+
actualSize: '実際のサイズ',
|
|
150
|
+
rotate: '回転',
|
|
151
|
+
download: 'ダウンロード',
|
|
152
|
+
loadingLarge: '高画質版を読み込み中',
|
|
153
|
+
},
|
|
154
|
+
chip: {
|
|
155
|
+
remove: '削除',
|
|
156
|
+
},
|
|
157
|
+
numberInput: {
|
|
158
|
+
increase: '増やす',
|
|
159
|
+
decrease: '減らす',
|
|
160
|
+
},
|
|
161
|
+
passwordInput: {
|
|
162
|
+
show: 'パスワードを表示',
|
|
163
|
+
hide: 'パスワードを隠す',
|
|
164
|
+
},
|
|
165
|
+
tree: { empty: 'ノードがありません' },
|
|
166
|
+
treeSelect: {
|
|
167
|
+
search: 'ノードを検索',
|
|
168
|
+
},
|
|
169
|
+
combobox: {
|
|
170
|
+
placeholder: '入力または選択',
|
|
171
|
+
toggle: '選択肢を表示',
|
|
172
|
+
},
|
|
173
|
+
slider: {
|
|
174
|
+
minimum: '最小値',
|
|
175
|
+
maximum: '最大値',
|
|
176
|
+
},
|
|
177
|
+
pinInput: {
|
|
178
|
+
cellLabel: (index, total) => `${total} 桁中 ${index} 桁目`,
|
|
179
|
+
},
|
|
180
|
+
dateField: {
|
|
181
|
+
year: '年',
|
|
182
|
+
month: '月',
|
|
183
|
+
day: '日',
|
|
184
|
+
hour: '時',
|
|
185
|
+
minute: '分',
|
|
186
|
+
second: '秒',
|
|
187
|
+
dayPeriod: '午前または午後',
|
|
188
|
+
},
|
|
189
|
+
dateRangeField: {
|
|
190
|
+
start: '開始日',
|
|
191
|
+
end: '終了日',
|
|
192
|
+
separator: '〜',
|
|
193
|
+
},
|
|
194
|
+
datePicker: {
|
|
195
|
+
open: 'カレンダーを開く',
|
|
196
|
+
},
|
|
197
|
+
dateTimePicker: {
|
|
198
|
+
time: '時刻',
|
|
199
|
+
},
|
|
200
|
+
rating: {
|
|
201
|
+
star: value => `星 ${value}`,
|
|
202
|
+
label: (value, max) => `星 ${max} 個中 ${value} 個`,
|
|
203
|
+
score: (value, max) => `${max} 点中 ${value} 点`,
|
|
204
|
+
},
|
|
205
|
+
form: {
|
|
206
|
+
required: '必須',
|
|
207
|
+
},
|
|
208
|
+
command: {
|
|
209
|
+
label: 'コマンドパレット',
|
|
210
|
+
placeholder: '検索',
|
|
211
|
+
empty: '一致する項目がありません',
|
|
212
|
+
},
|
|
213
|
+
lineClamp: {
|
|
214
|
+
expand: 'すべて表示',
|
|
215
|
+
collapse: '折りたたむ',
|
|
216
|
+
},
|
|
217
|
+
calendar: {
|
|
218
|
+
label: 'カレンダー',
|
|
219
|
+
prev: '前の月',
|
|
220
|
+
next: '次の月',
|
|
221
|
+
prevYear: '前の年',
|
|
222
|
+
nextYear: '次の年',
|
|
223
|
+
prevYears: '前の 12 年',
|
|
224
|
+
nextYears: '次の 12 年',
|
|
225
|
+
pickMonth: '月を選択',
|
|
226
|
+
pickYear: '年を選択',
|
|
227
|
+
weekStartsOn: 0,
|
|
228
|
+
},
|
|
229
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
:root,
|
|
2
2
|
[data-density='comfortable'] {
|
|
3
|
+
--hn-control-h-xs: 1.5rem;
|
|
3
4
|
--hn-control-h-sm: 1.75rem;
|
|
4
5
|
--hn-control-h-md: 2.25rem;
|
|
5
6
|
--hn-control-h-lg: 2.75rem;
|
|
7
|
+
--hn-control-px-xs: 0.5rem;
|
|
6
8
|
--hn-control-px-sm: 0.625rem;
|
|
7
9
|
--hn-control-px-md: 1rem;
|
|
8
10
|
--hn-control-px-lg: 1.25rem;
|
|
@@ -16,9 +18,11 @@
|
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
[data-density='compact'] {
|
|
21
|
+
--hn-control-h-xs: 1.25rem;
|
|
19
22
|
--hn-control-h-sm: 1.5rem;
|
|
20
23
|
--hn-control-h-md: 1.875rem;
|
|
21
24
|
--hn-control-h-lg: 2.25rem;
|
|
25
|
+
--hn-control-px-xs: 0.25rem;
|
|
22
26
|
--hn-control-px-sm: 0.375rem;
|
|
23
27
|
--hn-control-px-md: 0.5rem;
|
|
24
28
|
--hn-control-px-lg: 0.75rem;
|