@hina-ui/vue 1.1.0 → 1.3.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.
Files changed (175) hide show
  1. package/dist/index.js +1062 -528
  2. package/dist/index.js.map +1 -1
  3. package/dist/types/components/accordion/AccordionContent.vue.d.ts.map +1 -1
  4. package/dist/types/components/alert-dialog/AlertDialog.vue.d.ts +4 -0
  5. package/dist/types/components/alert-dialog/AlertDialog.vue.d.ts.map +1 -1
  6. package/dist/types/components/alert-dialog/alert-dialog.variants.d.ts +5 -0
  7. package/dist/types/components/alert-dialog/alert-dialog.variants.d.ts.map +1 -0
  8. package/dist/types/components/alert-dialog/composables/useAlertDialogConfirm.d.ts +9 -0
  9. package/dist/types/components/alert-dialog/composables/useAlertDialogConfirm.d.ts.map +1 -0
  10. package/dist/types/components/alert-dialog/composables/useConfirmDelay.d.ts +3 -0
  11. package/dist/types/components/alert-dialog/composables/useConfirmDelay.d.ts.map +1 -0
  12. package/dist/types/components/anchor/Anchor.vue.d.ts.map +1 -1
  13. package/dist/types/components/avatar/AvatarGroup.vue.d.ts.map +1 -1
  14. package/dist/types/components/avatar/utils/children.d.ts +3 -0
  15. package/dist/types/components/avatar/utils/children.d.ts.map +1 -0
  16. package/dist/types/components/checkbox-group/CheckboxGroup.vue.d.ts +32 -29
  17. package/dist/types/components/checkbox-group/CheckboxGroup.vue.d.ts.map +1 -1
  18. package/dist/types/components/code-block/CodeBlock.vue.d.ts.map +1 -1
  19. package/dist/types/components/code-block/code-block.variants.d.ts +6 -0
  20. package/dist/types/components/code-block/code-block.variants.d.ts.map +1 -0
  21. package/dist/types/components/code-block/composables/useCodeHighlight.d.ts +7 -0
  22. package/dist/types/components/code-block/composables/useCodeHighlight.d.ts.map +1 -0
  23. package/dist/types/components/collapsible/CollapsibleContent.vue.d.ts.map +1 -1
  24. package/dist/types/components/combobox/Combobox.vue.d.ts +38 -38
  25. package/dist/types/components/combobox/Combobox.vue.d.ts.map +1 -1
  26. package/dist/types/components/combobox/ComboboxList.vue.d.ts +22 -15
  27. package/dist/types/components/combobox/ComboboxList.vue.d.ts.map +1 -1
  28. package/dist/types/components/dialog/Dialog.vue.d.ts +22 -16
  29. package/dist/types/components/dialog/Dialog.vue.d.ts.map +1 -1
  30. package/dist/types/components/dialog/dialog.variants.d.ts +32 -2
  31. package/dist/types/components/dialog/dialog.variants.d.ts.map +1 -1
  32. package/dist/types/components/dropdown-menu/DropdownMenu.vue.d.ts +18 -6
  33. package/dist/types/components/dropdown-menu/DropdownMenu.vue.d.ts.map +1 -1
  34. package/dist/types/components/highlight/Highlight.vue.d.ts +2 -0
  35. package/dist/types/components/highlight/Highlight.vue.d.ts.map +1 -1
  36. package/dist/types/components/highlight/composables/useHighlightMotion.d.ts +10 -0
  37. package/dist/types/components/highlight/composables/useHighlightMotion.d.ts.map +1 -0
  38. package/dist/types/components/image/ImageGroup.vue.d.ts.map +1 -1
  39. package/dist/types/components/image/composables/useImageGroupState.d.ts +7 -0
  40. package/dist/types/components/image/composables/useImageGroupState.d.ts.map +1 -0
  41. package/dist/types/components/input/Input.vue.d.ts +3 -3
  42. package/dist/types/components/input/Input.vue.d.ts.map +1 -1
  43. package/dist/types/components/input/InputBase.vue.d.ts +3 -3
  44. package/dist/types/components/input/InputBase.vue.d.ts.map +1 -1
  45. package/dist/types/components/input/input.variants.d.ts +52 -6
  46. package/dist/types/components/input/input.variants.d.ts.map +1 -1
  47. package/dist/types/components/input-group/InputGroup.vue.d.ts +3 -3
  48. package/dist/types/components/input-group/InputGroup.vue.d.ts.map +1 -1
  49. package/dist/types/components/input-group/context.d.ts +2 -1
  50. package/dist/types/components/input-group/context.d.ts.map +1 -1
  51. package/dist/types/components/input-group/input-group.variants.d.ts +13 -1
  52. package/dist/types/components/input-group/input-group.variants.d.ts.map +1 -1
  53. package/dist/types/components/lightbox/LightboxThumbs.vue.d.ts.map +1 -1
  54. package/dist/types/components/listbox/Listbox.vue.d.ts +36 -29
  55. package/dist/types/components/listbox/Listbox.vue.d.ts.map +1 -1
  56. package/dist/types/components/listbox/ListboxOptionContent.vue.d.ts +31 -0
  57. package/dist/types/components/listbox/ListboxOptionContent.vue.d.ts.map +1 -0
  58. package/dist/types/components/listbox/listbox.variants.d.ts +19 -1
  59. package/dist/types/components/listbox/listbox.variants.d.ts.map +1 -1
  60. package/dist/types/components/multi-combobox/MultiCombobox.vue.d.ts +41 -43
  61. package/dist/types/components/multi-combobox/MultiCombobox.vue.d.ts.map +1 -1
  62. package/dist/types/components/multi-combobox/composables/useMultiCombobox.d.ts +27 -0
  63. package/dist/types/components/multi-combobox/composables/useMultiCombobox.d.ts.map +1 -0
  64. package/dist/types/components/multi-select/MultiSelect.vue.d.ts +39 -41
  65. package/dist/types/components/multi-select/MultiSelect.vue.d.ts.map +1 -1
  66. package/dist/types/components/number-input/NumberInput.vue.d.ts +3 -3
  67. package/dist/types/components/number-input/NumberInput.vue.d.ts.map +1 -1
  68. package/dist/types/components/number-input/number-input.variants.d.ts +10 -1
  69. package/dist/types/components/number-input/number-input.variants.d.ts.map +1 -1
  70. package/dist/types/components/password-input/PasswordInput.vue.d.ts +3 -3
  71. package/dist/types/components/password-input/PasswordInput.vue.d.ts.map +1 -1
  72. package/dist/types/components/popover/Popover.vue.d.ts +19 -6
  73. package/dist/types/components/popover/Popover.vue.d.ts.map +1 -1
  74. package/dist/types/components/popover/PopoverContent.vue.d.ts +29 -0
  75. package/dist/types/components/popover/PopoverContent.vue.d.ts.map +1 -0
  76. package/dist/types/components/popover/composables/usePopoverCloseFocus.d.ts +2 -0
  77. package/dist/types/components/popover/composables/usePopoverCloseFocus.d.ts.map +1 -0
  78. package/dist/types/components/radio-group/RadioGroup.vue.d.ts +32 -29
  79. package/dist/types/components/radio-group/RadioGroup.vue.d.ts.map +1 -1
  80. package/dist/types/components/scroll-area/ScrollArea.vue.d.ts.map +1 -1
  81. package/dist/types/components/scroll-area/composables/useScrollFocus.d.ts +17 -0
  82. package/dist/types/components/scroll-area/composables/useScrollFocus.d.ts.map +1 -0
  83. package/dist/types/components/scroll-area/scroll-restore.d.ts +0 -1
  84. package/dist/types/components/scroll-area/scroll-restore.d.ts.map +1 -1
  85. package/dist/types/components/search-input/SearchInput.vue.d.ts +3 -3
  86. package/dist/types/components/search-input/SearchInput.vue.d.ts.map +1 -1
  87. package/dist/types/components/segmented-control/SegmentedControl.vue.d.ts +30 -30
  88. package/dist/types/components/segmented-control/SegmentedControl.vue.d.ts.map +1 -1
  89. package/dist/types/components/select/Select.vue.d.ts +41 -37
  90. package/dist/types/components/select/Select.vue.d.ts.map +1 -1
  91. package/dist/types/components/select/SelectList.vue.d.ts +22 -15
  92. package/dist/types/components/select/SelectList.vue.d.ts.map +1 -1
  93. package/dist/types/components/select/composables/useClearTransition.d.ts +10 -0
  94. package/dist/types/components/select/composables/useClearTransition.d.ts.map +1 -0
  95. package/dist/types/components/select/select.variants.d.ts +16 -0
  96. package/dist/types/components/select/select.variants.d.ts.map +1 -1
  97. package/dist/types/components/select/types.d.ts +7 -7
  98. package/dist/types/components/select/types.d.ts.map +1 -1
  99. package/dist/types/components/tabs/TabsTrigger.vue.d.ts.map +1 -1
  100. package/dist/types/components/textarea/Textarea.vue.d.ts.map +1 -1
  101. package/dist/types/components/textarea/composables/useTextareaSizing.d.ts +27 -0
  102. package/dist/types/components/textarea/composables/useTextareaSizing.d.ts.map +1 -0
  103. package/dist/types/components/textarea/textarea.variants.d.ts +9 -6
  104. package/dist/types/components/textarea/textarea.variants.d.ts.map +1 -1
  105. package/dist/types/lib/anchored-overlay.d.ts +23 -0
  106. package/dist/types/lib/anchored-overlay.d.ts.map +1 -0
  107. package/dist/types/lib/caret.d.ts +0 -4
  108. package/dist/types/lib/caret.d.ts.map +1 -1
  109. package/dist/types/lib/collapse.d.ts +2 -0
  110. package/dist/types/lib/collapse.d.ts.map +1 -1
  111. package/dist/types/lib/field-focus.d.ts +0 -4
  112. package/dist/types/lib/field-focus.d.ts.map +1 -1
  113. package/package.json +1 -1
  114. package/src/components/accordion/AccordionContent.vue +2 -11
  115. package/src/components/alert-dialog/AlertDialog.vue +24 -36
  116. package/src/components/alert-dialog/alert-dialog.variants.ts +17 -0
  117. package/src/components/alert-dialog/composables/useAlertDialogConfirm.ts +29 -0
  118. package/src/components/alert-dialog/composables/useConfirmDelay.ts +37 -0
  119. package/src/components/anchor/Anchor.vue +1 -0
  120. package/src/components/avatar/AvatarGroup.vue +3 -8
  121. package/src/components/avatar/utils/children.ts +7 -0
  122. package/src/components/checkbox-group/CheckboxGroup.vue +3 -3
  123. package/src/components/code-block/CodeBlock.vue +15 -30
  124. package/src/components/code-block/code-block.variants.ts +21 -0
  125. package/src/components/code-block/composables/useCodeHighlight.ts +30 -0
  126. package/src/components/collapsible/CollapsibleContent.vue +2 -11
  127. package/src/components/combobox/Combobox.vue +3 -3
  128. package/src/components/combobox/ComboboxList.vue +3 -3
  129. package/src/components/dialog/Dialog.vue +70 -39
  130. package/src/components/dialog/dialog.variants.ts +9 -3
  131. package/src/components/dropdown-menu/DropdownMenu.vue +16 -4
  132. package/src/components/highlight/Highlight.vue +5 -4
  133. package/src/components/highlight/composables/useHighlightMotion.ts +22 -0
  134. package/src/components/image/ImageGroup.vue +2 -30
  135. package/src/components/image/composables/useImageGroupState.ts +35 -0
  136. package/src/components/input/Input.vue +3 -3
  137. package/src/components/input/InputBase.vue +5 -5
  138. package/src/components/input/input.variants.ts +13 -3
  139. package/src/components/input-group/InputGroup.vue +11 -4
  140. package/src/components/input-group/context.ts +2 -1
  141. package/src/components/input-group/input-group.variants.ts +8 -1
  142. package/src/components/lightbox/LightboxThumbs.vue +1 -0
  143. package/src/components/listbox/Listbox.vue +26 -29
  144. package/src/components/listbox/ListboxOptionContent.vue +28 -0
  145. package/src/components/listbox/listbox.variants.ts +6 -1
  146. package/src/components/multi-combobox/MultiCombobox.vue +14 -52
  147. package/src/components/multi-combobox/composables/useMultiCombobox.ts +63 -0
  148. package/src/components/multi-select/MultiSelect.vue +3 -4
  149. package/src/components/number-input/NumberInput.vue +8 -7
  150. package/src/components/number-input/number-input.variants.ts +5 -1
  151. package/src/components/password-input/PasswordInput.vue +3 -3
  152. package/src/components/popover/Popover.vue +21 -5
  153. package/src/components/popover/PopoverContent.vue +25 -0
  154. package/src/components/popover/composables/usePopoverCloseFocus.ts +17 -0
  155. package/src/components/radio-group/RadioGroup.vue +3 -3
  156. package/src/components/scroll-area/ScrollArea.vue +7 -5
  157. package/src/components/scroll-area/composables/useScrollFocus.ts +39 -0
  158. package/src/components/scroll-area/scroll-restore.ts +0 -5
  159. package/src/components/search-input/SearchInput.vue +3 -3
  160. package/src/components/segmented-control/SegmentedControl.vue +9 -4
  161. package/src/components/select/Select.vue +68 -25
  162. package/src/components/select/SelectList.vue +3 -3
  163. package/src/components/select/composables/useClearTransition.ts +25 -0
  164. package/src/components/select/select.variants.ts +24 -0
  165. package/src/components/select/types.ts +10 -8
  166. package/src/components/tabs/TabsTrigger.vue +6 -1
  167. package/src/components/textarea/Textarea.vue +2 -41
  168. package/src/components/textarea/composables/useTextareaSizing.ts +54 -0
  169. package/src/components/textarea/textarea.variants.ts +5 -4
  170. package/src/lib/anchored-overlay.ts +110 -0
  171. package/src/lib/caret.ts +0 -4
  172. package/src/lib/collapse.ts +21 -1
  173. package/src/lib/field-focus.ts +0 -4
  174. package/src/styles/interaction.css +4 -2
  175. package/src/styles/typography.css +9 -4
@@ -0,0 +1,110 @@
1
+ import { computed, nextTick, shallowRef, watch, type Ref } from 'vue'
2
+ import type { DropdownMenuContentEmits } from 'reka-ui'
3
+
4
+ export function useAnchoredOverlay(
5
+ props: { anchor?: HTMLElement | null; modal: boolean },
6
+ open: Ref<boolean | undefined>,
7
+ emit: <K extends keyof DropdownMenuContentEmits>(
8
+ event: K,
9
+ ...args: DropdownMenuContentEmits[K]
10
+ ) => void,
11
+ openAutoFocus?: (event: Event) => void,
12
+ ) {
13
+ const trigger = shallowRef<{ $el: HTMLElement } | null>(null)
14
+ const triggerElement = computed(() =>
15
+ trigger.value?.$el?.nodeType === 1 ? trigger.value.$el : undefined,
16
+ )
17
+ const retainedAnchor = shallowRef<HTMLElement>()
18
+ const reference = computed(
19
+ () =>
20
+ props.anchor ??
21
+ (open.value
22
+ ? (triggerElement.value ?? retainedAnchor.value)
23
+ : (retainedAnchor.value ?? triggerElement.value)),
24
+ )
25
+ const visible = computed({
26
+ get: () => !!open.value && !!(props.anchor || triggerElement.value),
27
+ set: value => {
28
+ open.value = value
29
+ },
30
+ })
31
+
32
+ watch(
33
+ () => props.anchor,
34
+ anchor => {
35
+ if (anchor) retainedAnchor.value = anchor
36
+ },
37
+ { immediate: true, flush: 'sync' },
38
+ )
39
+
40
+ let previousFocus: HTMLElement | null = null
41
+ let interactedOutside = false
42
+
43
+ function once<E extends Event>(handler: (event: E) => void) {
44
+ const handled = new WeakSet<E>()
45
+ return (event: E) => {
46
+ if (handled.has(event)) return
47
+ handled.add(event)
48
+ handler(event)
49
+ }
50
+ }
51
+
52
+ watch(
53
+ visible,
54
+ active => {
55
+ if (!active) return
56
+ const document = props.anchor?.ownerDocument ?? triggerElement.value?.ownerDocument
57
+ previousFocus = document?.activeElement as HTMLElement | null
58
+ interactedOutside = false
59
+ },
60
+ { immediate: true, flush: 'sync' },
61
+ )
62
+
63
+ const onCloseAutoFocus = once((event: Event) => {
64
+ emit('closeAutoFocus', event)
65
+ const cancelled = event.defaultPrevented
66
+ event.preventDefault()
67
+ const panel = event.target as HTMLElement
68
+ const target = triggerElement.value ?? previousFocus
69
+ const restore = !cancelled && !interactedOutside
70
+ nextTick(() => {
71
+ const active = panel.ownerDocument.activeElement
72
+ if (
73
+ restore &&
74
+ !visible.value &&
75
+ target?.isConnected &&
76
+ (active === panel.ownerDocument.body || panel.contains(active))
77
+ )
78
+ target.focus({ preventScroll: true })
79
+ if (!visible.value) retainedAnchor.value = undefined
80
+ })
81
+ })
82
+
83
+ const onInteractOutside = once((event: DropdownMenuContentEmits['interactOutside'][0]) => {
84
+ if (!triggerElement.value && props.anchor?.contains(event.target as Node))
85
+ event.preventDefault()
86
+ emit('interactOutside', event)
87
+ const original = event.detail.originalEvent
88
+ const rightClick =
89
+ 'button' in original && (original.button === 2 || (original.button === 0 && original.ctrlKey))
90
+ if (!event.defaultPrevented && (!props.modal || rightClick)) interactedOutside = true
91
+ })
92
+
93
+ return {
94
+ trigger,
95
+ reference,
96
+ visible,
97
+ events: {
98
+ ...(openAutoFocus ? { onOpenAutoFocus: once(openAutoFocus) } : {}),
99
+ onCloseAutoFocus,
100
+ onInteractOutside,
101
+ onPointerDownOutside: once((event: DropdownMenuContentEmits['pointerDownOutside'][0]) =>
102
+ emit('pointerDownOutside', event),
103
+ ),
104
+ onFocusOutside: once((event: DropdownMenuContentEmits['focusOutside'][0]) =>
105
+ emit('focusOutside', event),
106
+ ),
107
+ onEscapeKeyDown: once((event: KeyboardEvent) => emit('escapeKeyDown', event)),
108
+ },
109
+ }
110
+ }
package/src/lib/caret.ts CHANGED
@@ -22,10 +22,6 @@ const MIRRORED = [
22
22
  'border-left-width',
23
23
  ]
24
24
 
25
- /**
26
- * 量出 textarea 光标所在行的顶边(相对 textarea 自身的边框盒)。
27
- * 原生没有光标几何 API,只能用同排版的镜像块把光标前的文字排一遍。
28
- */
29
25
  export function caretTop(node: HTMLTextAreaElement, at = node.selectionEnd): number {
30
26
  const style = getComputedStyle(node)
31
27
  const mirror = node.ownerDocument.createElement('div')
@@ -1,4 +1,10 @@
1
- import { getCurrentInstance, onBeforeUpdate, onMounted } from 'vue'
1
+ import {
2
+ getCurrentInstance,
3
+ onBeforeUpdate,
4
+ onMounted,
5
+ shallowRef,
6
+ type ComponentPublicInstance,
7
+ } from 'vue'
2
8
 
3
9
  export type CollapseAxis = 'y' | 'x'
4
10
 
@@ -43,3 +49,17 @@ export function useCollapseHooks(axis: CollapseAxis = 'y') {
43
49
 
44
50
  return collapseHooks(axis, () => parent)
45
51
  }
52
+
53
+ export function useCollapseGap() {
54
+ const content = shallowRef<ComponentPublicInstance | null>(null)
55
+
56
+ function measure() {
57
+ const el = content.value?.$el as Element | undefined
58
+ if (el instanceof Element) writeCollapseGap(el, el.parentElement)
59
+ }
60
+
61
+ onMounted(measure)
62
+ onBeforeUpdate(measure)
63
+
64
+ return content
65
+ }
@@ -8,10 +8,6 @@ function controlOf(node: Element) {
8
8
  : null
9
9
  }
10
10
 
11
- /**
12
- * 点击输入面里非交互的部分(附属格、前后缀、空白)时把焦点交给最近的输入区,返回被聚焦的输入区;点击落在交互元素上或者没有可聚焦的输入区时返回 null。
13
- * 点击所在的段自己含输入区时只认它、不动光标(段内的处理器已经定过位);否则先向后找,再向前找;落在点击位置之后的输入区把光标放到开头,之前的放到末尾。
14
- */
15
11
  export function focusFieldFrom(root: HTMLElement, target: HTMLElement) {
16
12
  if (target.closest(INTERACTIVE)) return null
17
13
  const segments = Array.from(root.children)
@@ -155,7 +155,7 @@
155
155
  }
156
156
 
157
157
  &:focus-visible,
158
- &:has(:is(input, textarea, [data-hn-segment]):focus-visible) {
158
+ &:has(:is(input, textarea, [data-hn-segment], [data-hn-select-trigger]):focus-visible) {
159
159
  --hn-field-ring-w: 2px;
160
160
  }
161
161
 
@@ -170,7 +170,9 @@
170
170
  }
171
171
 
172
172
  &[data-invalid]:focus-visible,
173
- &[data-invalid]:has(:is(input, textarea, [data-hn-segment]):focus-visible) {
173
+ &[data-invalid]:has(
174
+ :is(input, textarea, [data-hn-segment], [data-hn-select-trigger]):focus-visible
175
+ ) {
174
176
  --hn-field-ring-w: 1px;
175
177
  }
176
178
  }
@@ -74,14 +74,19 @@
74
74
  }
75
75
  }
76
76
 
77
+ @utility hn-pre-content {
78
+ padding: 1em 1.25em;
79
+ }
80
+
77
81
  @utility hn-pre {
82
+ @apply hn-pre-content;
78
83
  font-family: var(--hn-font-mono);
79
84
  background-color: var(--hn-bg-inset);
80
85
  border-radius: var(--hn-radius-lg);
81
- padding: 1em 1.25em;
82
86
 
83
87
  &:focus-visible,
84
- &:has(> [data-overlayscrollbars-initialize]:focus-visible) {
88
+ &:has(> [data-overlayscrollbars-initialize]:focus-visible),
89
+ &:has(> [data-overlayscrollbars-initialize] > [data-overlayscrollbars-contents]:focus-visible) {
85
90
  outline: var(--hn-focus-ring-width) solid var(--hn-focus-ring);
86
91
  outline-offset: var(--hn-focus-ring-offset);
87
92
  }
@@ -144,7 +149,7 @@
144
149
  & ol,
145
150
  & dl,
146
151
  & blockquote,
147
- & pre,
152
+ & pre:not(:where(.hn-pre-content)),
148
153
  & table,
149
154
  & figure {
150
155
  margin-block: 0.75em 0;
@@ -228,7 +233,7 @@
228
233
  @apply hn-code;
229
234
  }
230
235
 
231
- & pre {
236
+ & pre:not(:where(.hn-pre-content)) {
232
237
  @apply hn-pre;
233
238
  overflow-x: auto;
234
239
  }