@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.
Files changed (106) hide show
  1. package/dist/index.js +1338 -562
  2. package/dist/index.js.map +1 -1
  3. package/dist/shared/behavior/anchor-follow.ts +20 -11
  4. package/dist/shared/behavior/form.ts +5 -9
  5. package/dist/shared/lib/command-palette/match.ts +9 -0
  6. package/dist/shared/lib/line-clamp.ts +76 -0
  7. package/dist/shared/lib/scroll-restore.ts +163 -0
  8. package/dist/shared/locale/en-US.ts +4 -0
  9. package/dist/shared/locale/index.ts +2 -0
  10. package/dist/shared/locale/ja-JP.ts +229 -0
  11. package/dist/shared/locale/types.ts +4 -0
  12. package/dist/shared/locale/zh-CN.ts +4 -0
  13. package/dist/shared/styles/density.css +4 -0
  14. package/dist/shared/styles/line-clamp.css +98 -0
  15. package/dist/shared/styles/tokens.css +1 -0
  16. package/dist/shared/styles/typography.css +18 -0
  17. package/dist/shared/variants/button.ts +2 -0
  18. package/dist/shared/variants/command-palette.ts +4 -0
  19. package/dist/shared/variants/line-clamp.ts +13 -0
  20. package/dist/shared/variants/tag.ts +1 -0
  21. package/dist/types/shared/src/behavior/anchor-follow.d.ts.map +1 -1
  22. package/dist/types/shared/src/behavior/form.d.ts.map +1 -1
  23. package/dist/types/shared/src/lib/command-palette/match.d.ts +5 -0
  24. package/dist/types/shared/src/lib/command-palette/match.d.ts.map +1 -1
  25. package/dist/types/shared/src/lib/line-clamp.d.ts +6 -0
  26. package/dist/types/shared/src/lib/line-clamp.d.ts.map +1 -0
  27. package/dist/types/shared/src/lib/scroll-restore.d.ts +16 -0
  28. package/dist/types/shared/src/lib/scroll-restore.d.ts.map +1 -1
  29. package/dist/types/shared/src/locale/en-US.d.ts.map +1 -1
  30. package/dist/types/shared/src/locale/index.d.ts +1 -0
  31. package/dist/types/shared/src/locale/index.d.ts.map +1 -1
  32. package/dist/types/shared/src/locale/ja-JP.d.ts +3 -0
  33. package/dist/types/shared/src/locale/ja-JP.d.ts.map +1 -0
  34. package/dist/types/shared/src/locale/types.d.ts +4 -0
  35. package/dist/types/shared/src/locale/types.d.ts.map +1 -1
  36. package/dist/types/shared/src/locale/zh-CN.d.ts.map +1 -1
  37. package/dist/types/shared/src/variants/button.d.ts +6 -0
  38. package/dist/types/shared/src/variants/button.d.ts.map +1 -1
  39. package/dist/types/shared/src/variants/command-palette.d.ts +1 -0
  40. package/dist/types/shared/src/variants/command-palette.d.ts.map +1 -1
  41. package/dist/types/shared/src/variants/line-clamp.d.ts +4 -0
  42. package/dist/types/shared/src/variants/line-clamp.d.ts.map +1 -0
  43. package/dist/types/shared/src/variants/tag.d.ts +3 -0
  44. package/dist/types/shared/src/variants/tag.d.ts.map +1 -1
  45. package/dist/types/shared/src/variants/toggle.d.ts +7 -0
  46. package/dist/types/shared/src/variants/toggle.d.ts.map +1 -1
  47. package/dist/types/vue/src/components/app-shell/AppShell.vue.d.ts +2 -2
  48. package/dist/types/vue/src/components/app-shell/AppShell.vue.d.ts.map +1 -1
  49. package/dist/types/vue/src/components/close-button/CloseButton.vue.d.ts +1 -1
  50. package/dist/types/vue/src/components/command-palette/CommandPalette.vue.d.ts +40 -34
  51. package/dist/types/vue/src/components/command-palette/CommandPalette.vue.d.ts.map +1 -1
  52. package/dist/types/vue/src/components/command-palette/CommandPaletteInput.vue.d.ts +8 -0
  53. package/dist/types/vue/src/components/command-palette/CommandPaletteInput.vue.d.ts.map +1 -0
  54. package/dist/types/vue/src/components/command-palette/CommandPaletteItem.vue.d.ts +21 -7
  55. package/dist/types/vue/src/components/command-palette/CommandPaletteItem.vue.d.ts.map +1 -1
  56. package/dist/types/vue/src/components/command-palette/CommandPalettePanel.vue.d.ts +37 -31
  57. package/dist/types/vue/src/components/command-palette/CommandPalettePanel.vue.d.ts.map +1 -1
  58. package/dist/types/vue/src/components/command-palette/composables/useCommandItems.d.ts +6 -6
  59. package/dist/types/vue/src/components/command-palette/composables/useCommandItems.d.ts.map +1 -1
  60. package/dist/types/vue/src/components/command-palette/context.d.ts +11 -0
  61. package/dist/types/vue/src/components/command-palette/context.d.ts.map +1 -0
  62. package/dist/types/vue/src/components/command-palette/types.d.ts +16 -5
  63. package/dist/types/vue/src/components/command-palette/types.d.ts.map +1 -1
  64. package/dist/types/vue/src/components/command-palette/utils/match.d.ts +3 -3
  65. package/dist/types/vue/src/components/command-palette/utils/match.d.ts.map +1 -1
  66. package/dist/types/vue/src/components/copy-button/CopyButton.vue.d.ts +1 -1
  67. package/dist/types/vue/src/components/description-list/DescriptionList.vue.d.ts +1 -0
  68. package/dist/types/vue/src/components/description-list/DescriptionList.vue.d.ts.map +1 -1
  69. package/dist/types/vue/src/components/dialog/Dialog.vue.d.ts +3 -0
  70. package/dist/types/vue/src/components/dialog/Dialog.vue.d.ts.map +1 -1
  71. package/dist/types/vue/src/components/drawer/Drawer.vue.d.ts +3 -0
  72. package/dist/types/vue/src/components/drawer/Drawer.vue.d.ts.map +1 -1
  73. package/dist/types/vue/src/components/form/Form.vue.d.ts +5 -0
  74. package/dist/types/vue/src/components/form/Form.vue.d.ts.map +1 -1
  75. package/dist/types/vue/src/components/form/scope.d.ts +4 -0
  76. package/dist/types/vue/src/components/form/scope.d.ts.map +1 -0
  77. package/dist/types/vue/src/components/line-clamp/LineClamp.vue.d.ts +28 -0
  78. package/dist/types/vue/src/components/line-clamp/LineClamp.vue.d.ts.map +1 -0
  79. package/dist/types/vue/src/components/line-clamp/line-clamp.variants.d.ts +2 -0
  80. package/dist/types/vue/src/components/line-clamp/line-clamp.variants.d.ts.map +1 -0
  81. package/dist/types/vue/src/components/sheet/Sheet.vue.d.ts +3 -0
  82. package/dist/types/vue/src/components/sheet/Sheet.vue.d.ts.map +1 -1
  83. package/dist/types/vue/src/index.d.ts +6 -4
  84. package/dist/types/vue/src/index.d.ts.map +1 -1
  85. package/dist/types/vue/src/locale/index.d.ts +1 -1
  86. package/dist/types/vue/src/locale/index.d.ts.map +1 -1
  87. package/package.json +1 -1
  88. package/src/components/app-shell/AppShell.vue +54 -4
  89. package/src/components/command-palette/CommandPalette.vue +53 -16
  90. package/src/components/command-palette/CommandPaletteInput.vue +32 -0
  91. package/src/components/command-palette/CommandPaletteItem.vue +7 -5
  92. package/src/components/command-palette/CommandPalettePanel.vue +95 -34
  93. package/src/components/command-palette/composables/useCommandItems.ts +16 -14
  94. package/src/components/command-palette/context.ts +28 -0
  95. package/src/components/command-palette/types.ts +21 -5
  96. package/src/components/command-palette/utils/match.ts +6 -3
  97. package/src/components/description-list/DescriptionList.vue +8 -2
  98. package/src/components/dialog/Dialog.vue +13 -8
  99. package/src/components/drawer/Drawer.vue +13 -8
  100. package/src/components/form/Form.vue +14 -1
  101. package/src/components/form/scope.ts +39 -0
  102. package/src/components/line-clamp/LineClamp.vue +105 -0
  103. package/src/components/line-clamp/line-clamp.variants.ts +1 -0
  104. package/src/components/sheet/Sheet.vue +14 -10
  105. package/src/index.ts +16 -2
  106. 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
- 0,
84
- Math.min(port.scrollHeight - port.clientHeight, port.scrollTop + delta),
85
- )
86
- if (Math.abs(next - port.scrollTop) < 1) return result
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; rules: FormRules | undefined } | undefined
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 rules = options.rules()
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 || rules !== options.rules() || !same(values, options.values())) {
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 && pending.rules === options.rules() && same(pending.values, options.values()))
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
+ }
@@ -205,6 +205,10 @@ export const enUS: UiMessages = {
205
205
  placeholder: 'Search',
206
206
  empty: 'No matches',
207
207
  },
208
+ lineClamp: {
209
+ expand: 'Show all',
210
+ collapse: 'Show less',
211
+ },
208
212
  calendar: {
209
213
  label: 'Calendar',
210
214
  prev: 'Previous month',
@@ -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
+ }
@@ -206,6 +206,10 @@ export interface UiMessages {
206
206
  placeholder: string
207
207
  empty: string
208
208
  }
209
+ lineClamp: {
210
+ expand: string
211
+ collapse: string
212
+ }
209
213
  calendar: {
210
214
  label: string
211
215
  prev: string
@@ -200,6 +200,10 @@ export const zhCN: UiMessages = {
200
200
  placeholder: '搜索',
201
201
  empty: '无匹配项',
202
202
  },
203
+ lineClamp: {
204
+ expand: '展开全部',
205
+ collapse: '收起',
206
+ },
203
207
  calendar: {
204
208
  label: '日历',
205
209
  prev: '上个月',
@@ -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;