@hina-ui/vue 1.3.0 → 1.4.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 (223) hide show
  1. package/dist/index.js +4326 -2130
  2. package/dist/index.js.map +1 -1
  3. package/dist/types/components/alert-dialog/AlertDialog.vue.d.ts +2 -2
  4. package/dist/types/components/alert-dialog/AlertDialog.vue.d.ts.map +1 -1
  5. package/dist/types/components/dialog/Dialog.vue.d.ts.map +1 -1
  6. package/dist/types/components/dialog/ModalContent.vue.d.ts +21 -0
  7. package/dist/types/components/dialog/ModalContent.vue.d.ts.map +1 -0
  8. package/dist/types/components/dropdown-menu/DropdownMenu.vue.d.ts.map +1 -1
  9. package/dist/types/components/file-upload/FileUpload.vue.d.ts +1 -1
  10. package/dist/types/components/file-upload/FileUpload.vue.d.ts.map +1 -1
  11. package/dist/types/components/hover-card/HoverCard.vue.d.ts +7 -7
  12. package/dist/types/components/hover-card/HoverCard.vue.d.ts.map +1 -1
  13. package/dist/types/components/hover-card/HoverCardAnchor.vue.d.ts +27 -0
  14. package/dist/types/components/hover-card/HoverCardAnchor.vue.d.ts.map +1 -0
  15. package/dist/types/components/hover-card/composables/useHoverCardAnchor.d.ts +17 -0
  16. package/dist/types/components/hover-card/composables/useHoverCardAnchor.d.ts.map +1 -0
  17. package/dist/types/components/image/Image.vue.d.ts +8 -3
  18. package/dist/types/components/image/Image.vue.d.ts.map +1 -1
  19. package/dist/types/components/image/composables/useImage.d.ts.map +1 -1
  20. package/dist/types/components/image/composables/useImageGroupState.d.ts.map +1 -1
  21. package/dist/types/components/image/image.variants.d.ts +23 -1
  22. package/dist/types/components/image/image.variants.d.ts.map +1 -1
  23. package/dist/types/components/lightbox/Lightbox.vue.d.ts.map +1 -1
  24. package/dist/types/components/lightbox/LightboxChrome.vue.d.ts +4 -0
  25. package/dist/types/components/lightbox/LightboxChrome.vue.d.ts.map +1 -1
  26. package/dist/types/components/lightbox/LightboxToolbar.vue.d.ts +4 -0
  27. package/dist/types/components/lightbox/LightboxToolbar.vue.d.ts.map +1 -1
  28. package/dist/types/components/lightbox/composables/useLightboxFrames.d.ts +4 -1
  29. package/dist/types/components/lightbox/composables/useLightboxFrames.d.ts.map +1 -1
  30. package/dist/types/components/lightbox/composables/useLightboxLarge.d.ts +1 -0
  31. package/dist/types/components/lightbox/composables/useLightboxLarge.d.ts.map +1 -1
  32. package/dist/types/components/lightbox/composables/useLightboxLayout.d.ts +17 -0
  33. package/dist/types/components/lightbox/composables/useLightboxLayout.d.ts.map +1 -0
  34. package/dist/types/components/lightbox/composables/useLightboxMotion.d.ts.map +1 -1
  35. package/dist/types/components/lightbox/composables/useLightboxPhase.d.ts +1 -1
  36. package/dist/types/components/lightbox/composables/useLightboxPhase.d.ts.map +1 -1
  37. package/dist/types/components/lightbox/composables/useLightboxPose.d.ts.map +1 -1
  38. package/dist/types/components/lightbox/composables/useLightboxRotation.d.ts +5 -1
  39. package/dist/types/components/lightbox/composables/useLightboxRotation.d.ts.map +1 -1
  40. package/dist/types/components/lightbox/composables/useLightboxZoom.d.ts +10 -1
  41. package/dist/types/components/lightbox/composables/useLightboxZoom.d.ts.map +1 -1
  42. package/dist/types/components/lightbox/lightbox.variants.d.ts +2 -0
  43. package/dist/types/components/lightbox/lightbox.variants.d.ts.map +1 -0
  44. package/dist/types/components/lightbox/types.d.ts +7 -1
  45. package/dist/types/components/lightbox/types.d.ts.map +1 -1
  46. package/dist/types/components/lightbox/utils/clip.d.ts +16 -0
  47. package/dist/types/components/lightbox/utils/clip.d.ts.map +1 -0
  48. package/dist/types/components/lightbox/utils/pose.d.ts +4 -4
  49. package/dist/types/components/lightbox/utils/pose.d.ts.map +1 -1
  50. package/dist/types/components/lightbox/utils/source.d.ts +4 -0
  51. package/dist/types/components/lightbox/utils/source.d.ts.map +1 -0
  52. package/dist/types/components/lightbox/utils/zoom.d.ts +8 -4
  53. package/dist/types/components/lightbox/utils/zoom.d.ts.map +1 -1
  54. package/dist/types/components/pagination/Pagination.vue.d.ts +59 -0
  55. package/dist/types/components/pagination/Pagination.vue.d.ts.map +1 -0
  56. package/dist/types/components/pagination/PaginationContent.vue.d.ts +23 -0
  57. package/dist/types/components/pagination/PaginationContent.vue.d.ts.map +1 -0
  58. package/dist/types/components/pagination/PaginationControl.vue.d.ts +10 -0
  59. package/dist/types/components/pagination/PaginationControl.vue.d.ts.map +1 -0
  60. package/dist/types/components/pagination/PaginationEllipsis.vue.d.ts +23 -0
  61. package/dist/types/components/pagination/PaginationEllipsis.vue.d.ts.map +1 -0
  62. package/dist/types/components/pagination/PaginationInfo.vue.d.ts +24 -0
  63. package/dist/types/components/pagination/PaginationInfo.vue.d.ts.map +1 -0
  64. package/dist/types/components/pagination/PaginationJump.vue.d.ts +7 -0
  65. package/dist/types/components/pagination/PaginationJump.vue.d.ts.map +1 -0
  66. package/dist/types/components/pagination/PaginationPage.vue.d.ts +20 -0
  67. package/dist/types/components/pagination/PaginationPage.vue.d.ts.map +1 -0
  68. package/dist/types/components/pagination/PaginationPages.vue.d.ts +27 -0
  69. package/dist/types/components/pagination/PaginationPages.vue.d.ts.map +1 -0
  70. package/dist/types/components/pagination/PaginationPopup.vue.d.ts +8 -0
  71. package/dist/types/components/pagination/PaginationPopup.vue.d.ts.map +1 -0
  72. package/dist/types/components/pagination/PaginationSize.vue.d.ts +7 -0
  73. package/dist/types/components/pagination/PaginationSize.vue.d.ts.map +1 -0
  74. package/dist/types/components/pagination/composables/usePagination.d.ts +25 -0
  75. package/dist/types/components/pagination/composables/usePagination.d.ts.map +1 -0
  76. package/dist/types/components/pagination/composables/usePaginationEllipsis.d.ts +34 -0
  77. package/dist/types/components/pagination/composables/usePaginationEllipsis.d.ts.map +1 -0
  78. package/dist/types/components/pagination/composables/usePaginationJump.d.ts +8 -0
  79. package/dist/types/components/pagination/composables/usePaginationJump.d.ts.map +1 -0
  80. package/dist/types/components/pagination/composables/usePaginationPageTooltip.d.ts +3 -0
  81. package/dist/types/components/pagination/composables/usePaginationPageTooltip.d.ts.map +1 -0
  82. package/dist/types/components/pagination/composables/usePaginationWindow.d.ts +188 -0
  83. package/dist/types/components/pagination/composables/usePaginationWindow.d.ts.map +1 -0
  84. package/dist/types/components/pagination/context.d.ts +19 -0
  85. package/dist/types/components/pagination/context.d.ts.map +1 -0
  86. package/dist/types/components/pagination/pagination.variants.d.ts +68 -0
  87. package/dist/types/components/pagination/pagination.variants.d.ts.map +1 -0
  88. package/dist/types/components/pagination/types.d.ts +23 -0
  89. package/dist/types/components/pagination/types.d.ts.map +1 -0
  90. package/dist/types/components/pagination/utils/ranges.d.ts +3 -0
  91. package/dist/types/components/pagination/utils/ranges.d.ts.map +1 -0
  92. package/dist/types/components/popover/Popover.vue.d.ts.map +1 -1
  93. package/dist/types/components/range-slider/RangeSlider.vue.d.ts +1 -0
  94. package/dist/types/components/range-slider/RangeSlider.vue.d.ts.map +1 -1
  95. package/dist/types/components/scroll-area/composables/useLayerLock.d.ts.map +1 -1
  96. package/dist/types/components/slider/Slider.vue.d.ts +1 -0
  97. package/dist/types/components/slider/Slider.vue.d.ts.map +1 -1
  98. package/dist/types/components/slider/slider.variants.d.ts.map +1 -1
  99. package/dist/types/components/tooltip/Tooltip.vue.d.ts +4 -15
  100. package/dist/types/components/tooltip/Tooltip.vue.d.ts.map +1 -1
  101. package/dist/types/components/tooltip/TooltipBubble.vue.d.ts +20 -0
  102. package/dist/types/components/tooltip/TooltipBubble.vue.d.ts.map +1 -0
  103. package/dist/types/components/tooltip/TooltipDirectiveRoot.d.ts +33 -0
  104. package/dist/types/components/tooltip/TooltipDirectiveRoot.d.ts.map +1 -0
  105. package/dist/types/components/tooltip/composables/useTooltipTarget.d.ts +2 -0
  106. package/dist/types/components/tooltip/composables/useTooltipTarget.d.ts.map +1 -0
  107. package/dist/types/components/tooltip/directive.d.ts +4 -0
  108. package/dist/types/components/tooltip/directive.d.ts.map +1 -0
  109. package/dist/types/components/tooltip/types.d.ts +14 -0
  110. package/dist/types/components/tooltip/types.d.ts.map +1 -0
  111. package/dist/types/components/tooltip/utils/directiveContext.d.ts +10 -0
  112. package/dist/types/components/tooltip/utils/directiveContext.d.ts.map +1 -0
  113. package/dist/types/components/tree-select/TreeSelect.vue.d.ts +6 -1
  114. package/dist/types/components/tree-select/TreeSelect.vue.d.ts.map +1 -1
  115. package/dist/types/components/tree-select/TreeSelectSearch.vue.d.ts +22 -0
  116. package/dist/types/components/tree-select/TreeSelectSearch.vue.d.ts.map +1 -0
  117. package/dist/types/components/tree-select/composables/useTreeSelect.d.ts +35 -0
  118. package/dist/types/components/tree-select/composables/useTreeSelect.d.ts.map +1 -0
  119. package/dist/types/components/tree-select/tree-select.variants.d.ts +1 -1
  120. package/dist/types/components/tree-select/tree-select.variants.d.ts.map +1 -1
  121. package/dist/types/components/tree-select/utils/filterTree.d.ts +7 -0
  122. package/dist/types/components/tree-select/utils/filterTree.d.ts.map +1 -0
  123. package/dist/types/index.d.ts +10 -0
  124. package/dist/types/index.d.ts.map +1 -1
  125. package/dist/types/lib/anchored-overlay.d.ts +3 -7
  126. package/dist/types/lib/anchored-overlay.d.ts.map +1 -1
  127. package/dist/types/lib/dialog-focus.d.ts +2 -0
  128. package/dist/types/lib/dialog-focus.d.ts.map +1 -0
  129. package/dist/types/lib/overlay-portal.d.ts +6 -0
  130. package/dist/types/lib/overlay-portal.d.ts.map +1 -0
  131. package/dist/types/lib/overlay-positioner.d.ts +3 -0
  132. package/dist/types/lib/overlay-positioner.d.ts.map +1 -0
  133. package/dist/types/lib/pointer-corridor.d.ts +7 -0
  134. package/dist/types/lib/pointer-corridor.d.ts.map +1 -0
  135. package/dist/types/lib/useDirection.d.ts +7 -0
  136. package/dist/types/lib/useDirection.d.ts.map +1 -0
  137. package/dist/types/locale/en-US.d.ts.map +1 -1
  138. package/dist/types/locale/index.d.ts.map +1 -1
  139. package/dist/types/locale/types.d.ts +13 -0
  140. package/dist/types/locale/types.d.ts.map +1 -1
  141. package/dist/types/locale/zh-CN.d.ts.map +1 -1
  142. package/package.json +1 -1
  143. package/src/components/alert-dialog/AlertDialog.vue +7 -4
  144. package/src/components/badge/badge.variants.ts +1 -1
  145. package/src/components/dialog/Dialog.vue +7 -4
  146. package/src/components/dialog/ModalContent.vue +19 -0
  147. package/src/components/dropdown-menu/DropdownMenu.vue +1 -1
  148. package/src/components/hover-card/HoverCard.vue +34 -16
  149. package/src/components/hover-card/HoverCardAnchor.vue +16 -0
  150. package/src/components/hover-card/composables/useHoverCardAnchor.ts +160 -0
  151. package/src/components/image/Image.vue +11 -12
  152. package/src/components/image/composables/useImage.ts +6 -3
  153. package/src/components/image/composables/useImageGroupState.ts +9 -1
  154. package/src/components/image/image.variants.ts +13 -1
  155. package/src/components/lightbox/Lightbox.vue +23 -17
  156. package/src/components/lightbox/LightboxChrome.vue +7 -1
  157. package/src/components/lightbox/LightboxToolbar.vue +16 -2
  158. package/src/components/lightbox/composables/useLightboxFrames.ts +108 -12
  159. package/src/components/lightbox/composables/useLightboxLarge.ts +4 -1
  160. package/src/components/lightbox/composables/useLightboxLayout.ts +44 -0
  161. package/src/components/lightbox/composables/useLightboxMotion.ts +3 -1
  162. package/src/components/lightbox/composables/useLightboxPhase.ts +12 -4
  163. package/src/components/lightbox/composables/useLightboxPose.ts +20 -19
  164. package/src/components/lightbox/composables/useLightboxRotation.ts +14 -4
  165. package/src/components/lightbox/composables/useLightboxZoom.ts +51 -9
  166. package/src/components/lightbox/lightbox.variants.ts +5 -0
  167. package/src/components/lightbox/types.ts +5 -1
  168. package/src/components/lightbox/utils/clip.ts +117 -0
  169. package/src/components/lightbox/utils/pose.ts +36 -19
  170. package/src/components/lightbox/utils/source.ts +17 -0
  171. package/src/components/lightbox/utils/zoom.ts +21 -7
  172. package/src/components/pagination/Pagination.vue +118 -0
  173. package/src/components/pagination/PaginationContent.vue +29 -0
  174. package/src/components/pagination/PaginationControl.vue +42 -0
  175. package/src/components/pagination/PaginationEllipsis.vue +67 -0
  176. package/src/components/pagination/PaginationInfo.vue +18 -0
  177. package/src/components/pagination/PaginationJump.vue +32 -0
  178. package/src/components/pagination/PaginationPage.vue +34 -0
  179. package/src/components/pagination/PaginationPages.vue +43 -0
  180. package/src/components/pagination/PaginationPopup.vue +92 -0
  181. package/src/components/pagination/PaginationSize.vue +30 -0
  182. package/src/components/pagination/composables/usePagination.ts +76 -0
  183. package/src/components/pagination/composables/usePaginationEllipsis.ts +269 -0
  184. package/src/components/pagination/composables/usePaginationJump.ts +23 -0
  185. package/src/components/pagination/composables/usePaginationPageTooltip.ts +23 -0
  186. package/src/components/pagination/composables/usePaginationWindow.ts +116 -0
  187. package/src/components/pagination/context.ts +23 -0
  188. package/src/components/pagination/pagination.variants.ts +32 -0
  189. package/src/components/pagination/types.ts +19 -0
  190. package/src/components/pagination/utils/ranges.ts +12 -0
  191. package/src/components/popover/Popover.vue +6 -2
  192. package/src/components/range-slider/RangeSlider.vue +6 -0
  193. package/src/components/scroll-area/composables/useLayerLock.ts +8 -9
  194. package/src/components/scroll-area/composables/useWheelRedirect.ts +1 -1
  195. package/src/components/skeleton/LICENSE +24 -0
  196. package/src/components/slider/Slider.vue +6 -0
  197. package/src/components/slider/slider.variants.ts +1 -0
  198. package/src/components/tooltip/Tooltip.vue +10 -33
  199. package/src/components/tooltip/TooltipBubble.vue +36 -0
  200. package/src/components/tooltip/TooltipDirectiveRoot.ts +61 -0
  201. package/src/components/tooltip/composables/useTooltipTarget.ts +56 -0
  202. package/src/components/tooltip/directive.ts +54 -0
  203. package/src/components/tooltip/types.ts +15 -0
  204. package/src/components/tooltip/utils/directiveContext.ts +32 -0
  205. package/src/components/tree-select/TreeSelect.vue +90 -61
  206. package/src/components/tree-select/TreeSelectSearch.vue +48 -0
  207. package/src/components/tree-select/composables/useTreeSelect.ts +130 -0
  208. package/src/components/tree-select/tree-select.variants.ts +2 -2
  209. package/src/components/tree-select/utils/filterTree.ts +19 -0
  210. package/src/index.ts +10 -0
  211. package/src/lib/anchored-overlay.ts +2 -5
  212. package/src/lib/dialog-focus.ts +13 -0
  213. package/src/lib/overlay-portal.ts +8 -0
  214. package/src/lib/overlay-positioner.ts +25 -0
  215. package/src/lib/pointer-corridor.ts +26 -0
  216. package/src/lib/useDirection.ts +31 -0
  217. package/src/locale/en-US.ts +15 -1
  218. package/src/locale/index.ts +1 -0
  219. package/src/locale/types.ts +13 -0
  220. package/src/locale/zh-CN.ts +15 -1
  221. package/src/styles/interaction.css +26 -3
  222. package/src/styles/motion.css +14 -2
  223. package/src/styles/semantic.css +5 -1
@@ -0,0 +1,7 @@
1
+ type Point = {
2
+ x: number;
3
+ y: number;
4
+ };
5
+ export declare function inPointerCorridor(point: Point, first: DOMRect, second: DOMRect): boolean;
6
+ export {};
7
+ //# sourceMappingURL=pointer-corridor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointer-corridor.d.ts","sourceRoot":"","sources":["../../../src/lib/pointer-corridor.ts"],"names":[],"mappings":"AAAA,KAAK,KAAK,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAIrC,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,WAqB9E"}
@@ -0,0 +1,7 @@
1
+ import { type Direction } from 'reka-ui';
2
+ export declare function useDirection(dir: () => Direction | undefined): {
3
+ root: import("vue").ShallowRef<HTMLElement | undefined, HTMLElement | undefined>;
4
+ direction: import("vue").ComputedRef<Direction>;
5
+ rootDirection: import("vue").ComputedRef<Direction | undefined>;
6
+ };
7
+ //# sourceMappingURL=useDirection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDirection.d.ts","sourceRoot":"","sources":["../../../src/lib/useDirection.ts"],"names":[],"mappings":"AACA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,SAAS,CAAA;AAErE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,SAAS,GAAG,SAAS;;;;EA2B5D"}
@@ -1 +1 @@
1
- {"version":3,"file":"en-US.d.ts","sourceRoot":"","sources":["../../../src/locale/en-US.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,eAAO,MAAM,IAAI,EAAE,UAqJlB,CAAA"}
1
+ {"version":3,"file":"en-US.d.ts","sourceRoot":"","sources":["../../../src/locale/en-US.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,eAAO,MAAM,IAAI,EAAE,UAmKlB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/locale/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,WAAW,EAEhB,KAAK,gBAAgB,EACtB,MAAM,KAAK,CAAA;AACZ,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AA2C5D,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,gBAAgB,CAAC,iBAAiB,CAAC,GAC5C,WAAW,CAAC,UAAU,CAAC,CAIzB;AAED,wBAAgB,WAAW,IAAI,WAAW,CAAC,UAAU,CAAC,CAErD;AAED,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/locale/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,WAAW,EAEhB,KAAK,gBAAgB,EACtB,MAAM,KAAK,CAAA;AACZ,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AA4C5D,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,gBAAgB,CAAC,iBAAiB,CAAC,GAC5C,WAAW,CAAC,UAAU,CAAC,CAIzB;AAED,wBAAgB,WAAW,IAAI,WAAW,CAAC,UAAU,CAAC,CAErD;AAED,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA"}
@@ -14,6 +14,15 @@ export interface UiMessages {
14
14
  next: string;
15
15
  };
16
16
  pagination: {
17
+ rangeLabel: (from: number, to: number, total: number) => string;
18
+ pageCountLabel: (page: number, count: number) => string;
19
+ pageSizeLabel: string;
20
+ pageSizeOption: (n: number) => string;
21
+ jumpLabel: string;
22
+ previousPagesLabel: (n: number) => string;
23
+ nextPagesLabel: (n: number) => string;
24
+ choosePage: string;
25
+ choosePageHint: string;
17
26
  navLabel: string;
18
27
  prev: string;
19
28
  next: string;
@@ -77,6 +86,7 @@ export interface UiMessages {
77
86
  zoomIn: string;
78
87
  zoomOut: string;
79
88
  resetZoom: string;
89
+ actualSize: string;
80
90
  rotate: string;
81
91
  download: string;
82
92
  loadingLarge: string;
@@ -92,6 +102,9 @@ export interface UiMessages {
92
102
  show: string;
93
103
  hide: string;
94
104
  };
105
+ treeSelect: {
106
+ search: string;
107
+ };
95
108
  combobox: {
96
109
  placeholder: string;
97
110
  toggle: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/locale/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/locale/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"zh-CN.d.ts","sourceRoot":"","sources":["../../../src/locale/zh-CN.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,eAAO,MAAM,IAAI,EAAE,UAqJlB,CAAA"}
1
+ {"version":3,"file":"zh-CN.d.ts","sourceRoot":"","sources":["../../../src/locale/zh-CN.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,eAAO,MAAM,IAAI,EAAE,UAmKlB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hina-ui/vue",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "An elegant, restrained Vue 3 component library built on Reka UI and Tailwind CSS v4.",
5
5
  "keywords": [
6
6
  "vue",
@@ -1,7 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import {
3
3
  AlertDialogCancel,
4
- AlertDialogContent,
5
4
  AlertDialogDescription,
6
5
  AlertDialogOverlay,
7
6
  AlertDialogPortal,
@@ -9,8 +8,10 @@
9
8
  AlertDialogTitle,
10
9
  AlertDialogTrigger,
11
10
  } from 'reka-ui'
11
+ import { useOverlayPortal } from '../../lib/overlay-portal'
12
12
  import { cn } from '../../lib/cn'
13
13
  import { useUiLocale } from '../../locale'
14
+ import ModalContent from '../dialog/ModalContent.vue'
14
15
  import Button from '../button/Button.vue'
15
16
  import Card from '../card/Card.vue'
16
17
  import { dialogCard, dialogWrapper } from '../dialog/dialog.variants'
@@ -45,6 +46,7 @@
45
46
  const emit = defineEmits<{ cancel: []; error: [error: unknown] }>()
46
47
 
47
48
  const open = defineModel<boolean>('open')
49
+ const { content, present } = useOverlayPortal(open)
48
50
  const t = useUiLocale()
49
51
  const remaining = useConfirmDelay(open, () => props.confirmDelay)
50
52
  const { busy, guard, confirm } = useAlertDialogConfirm(
@@ -60,11 +62,12 @@
60
62
  <AlertDialogTrigger v-if="$slots.default" as-child>
61
63
  <slot />
62
64
  </AlertDialogTrigger>
63
- <AlertDialogPortal>
65
+ <AlertDialogPortal v-if="present">
64
66
  <AlertDialogOverlay class="hn-scrim" />
65
67
  <div :class="dialogWrapper({ placement: props.placement ?? 'auto' })">
66
- <AlertDialogContent as-child @escape-key-down="guard">
68
+ <ModalContent alert as-child @escape-key-down="guard">
67
69
  <Card
70
+ ref="content"
68
71
  :padded="false"
69
72
  data-hn-alert-dialog
70
73
  :aria-busy="busy || undefined"
@@ -98,7 +101,7 @@
98
101
  </Button>
99
102
  </div>
100
103
  </Card>
101
- </AlertDialogContent>
104
+ </ModalContent>
102
105
  </div>
103
106
  </AlertDialogPortal>
104
107
  </AlertDialogRoot>
@@ -2,7 +2,7 @@ import { tv, type VariantProps } from '../../lib/tv'
2
2
 
3
3
  export const badge = tv({
4
4
  base: [
5
- 'absolute z-[1] inline-flex items-center justify-center rounded-full will-change-transform',
5
+ 'pointer-events-none absolute z-[1] inline-flex items-center justify-center rounded-full will-change-transform',
6
6
  'font-medium leading-none whitespace-nowrap select-none',
7
7
  ],
8
8
  variants: {
@@ -4,16 +4,17 @@
4
4
  DialogTrigger,
5
5
  DialogPortal,
6
6
  DialogOverlay,
7
- DialogContent,
8
7
  DialogTitle,
9
8
  DialogDescription,
10
9
  DialogClose,
11
10
  } from 'reka-ui'
11
+ import ModalContent from './ModalContent.vue'
12
12
  import CloseButton from '../close-button/CloseButton.vue'
13
13
  import Card from '../card/Card.vue'
14
14
  import ScrollArea from '../scroll-area/ScrollArea.vue'
15
15
  import Heading from '../heading/Heading.vue'
16
16
  import Text from '../text/Text.vue'
17
+ import { useOverlayPortal } from '../../lib/overlay-portal'
17
18
  import { cn } from '../../lib/cn'
18
19
  import { dialogWrapper, dialogCard, type DialogVariants } from './dialog.variants'
19
20
 
@@ -47,6 +48,7 @@
47
48
  }
48
49
 
49
50
  const open = defineModel<boolean>('open')
51
+ const { content, present } = useOverlayPortal(open)
50
52
 
51
53
  function close() {
52
54
  open.value = false
@@ -58,11 +60,12 @@
58
60
  <DialogTrigger v-if="$slots.default" as-child>
59
61
  <slot />
60
62
  </DialogTrigger>
61
- <DialogPortal>
63
+ <DialogPortal v-if="present">
62
64
  <DialogOverlay class="hn-scrim" />
63
65
  <div :class="dialogWrapper({ placement: props.placement ?? 'auto' })">
64
- <DialogContent as-child @escape-key-down="guard" @interact-outside="guard">
66
+ <ModalContent as-child @escape-key-down="guard" @interact-outside="guard">
65
67
  <Card
68
+ ref="content"
66
69
  v-bind="props.description ? {} : { 'aria-describedby': undefined }"
67
70
  :padded="false"
68
71
  :class="
@@ -127,7 +130,7 @@
127
130
  </div>
128
131
  </template>
129
132
  </Card>
130
- </DialogContent>
133
+ </ModalContent>
131
134
  </div>
132
135
  </DialogPortal>
133
136
  </DialogRoot>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import { AlertDialogContent, DialogContent } from 'reka-ui'
3
+ import { useDialogCloseFocus } from '../../lib/dialog-focus'
4
+
5
+ defineOptions({ name: 'HnModalContent' })
6
+
7
+ const props = defineProps<{ alert?: boolean }>()
8
+ const emit = defineEmits<{ closeAutoFocus: [event: Event] }>()
9
+ const closeAutoFocus = useDialogCloseFocus(event => emit('closeAutoFocus', event))
10
+ </script>
11
+
12
+ <template>
13
+ <component
14
+ :is="props.alert ? AlertDialogContent : DialogContent"
15
+ @close-auto-focus="closeAutoFocus"
16
+ >
17
+ <slot />
18
+ </component>
19
+ </template>
@@ -45,7 +45,7 @@
45
45
  <DropdownMenuRoot v-model:open="visible" :modal="props.modal" :dir="props.dir">
46
46
  <DropdownMenuTrigger
47
47
  v-if="$slots.default"
48
- ref="trigger"
48
+ :ref="trigger"
49
49
  as-child
50
50
  class="group/hn-disclosure"
51
51
  :style="{ transformOrigin: pressOrigin }"
@@ -2,11 +2,13 @@
2
2
  import { HoverCardContent, HoverCardPortal, HoverCardRoot, HoverCardTrigger } from 'reka-ui'
3
3
  import { cn } from '../../lib/cn'
4
4
  import Card from '../card/Card.vue'
5
+ import HoverCardAnchor from './HoverCardAnchor.vue'
5
6
 
6
7
  defineOptions({ name: 'HnHoverCard' })
7
8
 
8
9
  const props = withDefaults(
9
10
  defineProps<{
11
+ anchor?: HTMLElement | null
10
12
  side?: 'top' | 'right' | 'bottom' | 'left'
11
13
  align?: 'start' | 'center' | 'end'
12
14
  sideOffset?: number
@@ -14,6 +16,7 @@
14
16
  closeDelay?: number
15
17
  padded?: boolean
16
18
  class?: string
19
+ positionerClass?: string
17
20
  }>(),
18
21
  {
19
22
  side: 'bottom',
@@ -25,29 +28,44 @@
25
28
  },
26
29
  )
27
30
 
31
+ defineSlots<{ default?(): unknown; content?(): unknown }>()
32
+
28
33
  const open = defineModel<boolean>('open')
29
34
  </script>
30
35
 
31
36
  <template>
32
37
  <HoverCardRoot v-model:open="open" :open-delay="props.openDelay" :close-delay="props.closeDelay">
33
- <HoverCardTrigger as-child>
38
+ <HoverCardTrigger v-if="$slots.default" as-child>
34
39
  <slot />
35
40
  </HoverCardTrigger>
36
- <HoverCardPortal>
37
- <HoverCardContent
38
- as-child
39
- :side="props.side"
40
- :align="props.align"
41
- :side-offset="props.sideOffset"
42
- >
43
- <Card
44
- data-hn-hover-card
45
- :padded="props.padded"
46
- :class="cn('hn-anim-pop z-(--hn-z-overlay) max-w-sm shadow-md outline-none', props.class)"
41
+ <HoverCardAnchor
42
+ v-slot="{ reference, contentRef, present }"
43
+ :anchor="props.anchor"
44
+ :external="!$slots.default"
45
+ :close-delay="props.closeDelay"
46
+ :positioner-class="props.positionerClass"
47
+ >
48
+ <HoverCardPortal v-if="present">
49
+ <HoverCardContent
50
+ :reference="reference"
51
+ as-child
52
+ :side="props.side"
53
+ :align="props.align"
54
+ :side-offset="props.sideOffset"
47
55
  >
48
- <slot name="content" />
49
- </Card>
50
- </HoverCardContent>
51
- </HoverCardPortal>
56
+ <Card
57
+ :ref="contentRef"
58
+ data-hn-hover-card
59
+ :inert="!open"
60
+ :padded="props.padded"
61
+ :class="
62
+ cn('hn-anim-pop z-(--hn-z-overlay) max-w-sm shadow-md outline-none', props.class)
63
+ "
64
+ >
65
+ <slot name="content" />
66
+ </Card>
67
+ </HoverCardContent>
68
+ </HoverCardPortal>
69
+ </HoverCardAnchor>
52
70
  </HoverCardRoot>
53
71
  </template>
@@ -0,0 +1,16 @@
1
+ <script setup lang="ts">
2
+ import { useHoverCardAnchor } from './composables/useHoverCardAnchor'
3
+
4
+ defineOptions({ name: 'HnHoverCardAnchor' })
5
+ const props = defineProps<{
6
+ anchor?: HTMLElement | null
7
+ external: boolean
8
+ closeDelay: number
9
+ positionerClass?: string
10
+ }>()
11
+ const { reference, contentRef, present } = useHoverCardAnchor(props)
12
+ </script>
13
+
14
+ <template>
15
+ <slot :reference="reference" :content-ref="contentRef" :present="present" />
16
+ </template>
@@ -0,0 +1,160 @@
1
+ import { computed, onScopeDispose, shallowRef, watch, type ComponentPublicInstance } from 'vue'
2
+ import { useEventListener, useRafFn } from '@vueuse/core'
3
+ import { injectHoverCardRootContext } from 'reka-ui'
4
+ import { useOverlayPortal } from '../../../lib/overlay-portal'
5
+ import { useOverlayPositionerClass } from '../../../lib/overlay-positioner'
6
+ import { inPointerCorridor } from '../../../lib/pointer-corridor'
7
+
8
+ interface HoverCardAnchorOptions {
9
+ anchor?: HTMLElement | null
10
+ external: boolean
11
+ closeDelay: number
12
+ positionerClass?: string
13
+ }
14
+
15
+ export function useHoverCardAnchor(props: HoverCardAnchorOptions) {
16
+ const root = injectHoverCardRootContext()
17
+ const original = { onOpen: root.onOpen, onClose: root.onClose, onDismiss: root.onDismiss }
18
+ const anchor = computed(() => (props.external ? (props.anchor ?? undefined) : undefined))
19
+ const { content, present } = useOverlayPortal(root.open)
20
+ useOverlayPositionerClass(content, () => props.positionerClass)
21
+ const panel = computed(() =>
22
+ props.external ? (content.value?.$el as HTMLElement | undefined) : undefined,
23
+ )
24
+ const liveAnchor = shallowRef<HTMLElement>()
25
+ const retained = shallowRef<{
26
+ getBoundingClientRect: () => DOMRect
27
+ contextElement: HTMLElement
28
+ }>()
29
+ const reference = computed(() =>
30
+ props.external ? (liveAnchor.value ?? retained.value) : undefined,
31
+ )
32
+ let timer: ReturnType<typeof setTimeout> | undefined
33
+ let tracking = false
34
+
35
+ function cancel() {
36
+ clearTimeout(timer)
37
+ timer = undefined
38
+ }
39
+
40
+ function dismiss() {
41
+ cancel()
42
+ tracking = false
43
+ root.onOpenChange(false)
44
+ }
45
+
46
+ function close() {
47
+ if (
48
+ timer !== undefined ||
49
+ !root.open.value ||
50
+ root.hasSelectionRef.value ||
51
+ root.isPointerDownOnContentRef.value
52
+ )
53
+ return
54
+ timer = setTimeout(dismiss, props.closeDelay)
55
+ }
56
+
57
+ function keep() {
58
+ tracking = false
59
+ cancel()
60
+ }
61
+
62
+ function track(event: Event) {
63
+ const pointer = event as PointerEvent
64
+ if (!root.open.value || !tracking || pointer.pointerType === 'touch') return
65
+ const target = pointer.target as Node | null
66
+ if (target && (anchor.value?.contains(target) || panel.value?.contains(target))) return keep()
67
+ const a = anchor.value?.getBoundingClientRect()
68
+ const b = panel.value?.getBoundingClientRect()
69
+ if (a && b && inPointerCorridor({ x: pointer.clientX, y: pointer.clientY }, a, b)) cancel()
70
+ else close()
71
+ }
72
+
73
+ function leave(event: Event) {
74
+ const pointer = event as PointerEvent
75
+ if (pointer.pointerType === 'touch' || !root.open.value) return
76
+ tracking = true
77
+ const a = anchor.value?.getBoundingClientRect()
78
+ const b = panel.value?.getBoundingClientRect()
79
+ if (a && b && inPointerCorridor({ x: pointer.clientX, y: pointer.clientY }, a, b)) cancel()
80
+ else close()
81
+ }
82
+
83
+ function measure() {
84
+ const element = anchor.value
85
+ if (!element?.isConnected) {
86
+ liveAnchor.value = undefined
87
+ if (root.open.value) dismiss()
88
+ return
89
+ }
90
+ liveAnchor.value = element
91
+ const rect = element.getBoundingClientRect()
92
+ const previous = retained.value?.getBoundingClientRect()
93
+ if (
94
+ !previous ||
95
+ retained.value?.contextElement !== element ||
96
+ rect.x !== previous.x ||
97
+ rect.y !== previous.y ||
98
+ rect.width !== previous.width ||
99
+ rect.height !== previous.height
100
+ )
101
+ retained.value = { getBoundingClientRect: () => rect, contextElement: element }
102
+ }
103
+
104
+ const { pause, resume } = useRafFn(measure, { immediate: false })
105
+ root.onOpen = () => (props.external ? keep() : original.onOpen())
106
+ root.onClose = () => (props.external ? close() : original.onClose())
107
+ root.onDismiss = () => (props.external ? dismiss() : original.onDismiss())
108
+
109
+ watch(
110
+ [anchor, root.open, present],
111
+ ([element, , mounted], previous) => {
112
+ cancel()
113
+ tracking = false
114
+ pause()
115
+ if (!props.external || !mounted) {
116
+ liveAnchor.value = undefined
117
+ return
118
+ }
119
+ if (element !== previous?.[0]) {
120
+ root.hasSelectionRef.value = false
121
+ root.isPointerDownOnContentRef.value = false
122
+ }
123
+ measure()
124
+ resume()
125
+ },
126
+ { immediate: true, flush: 'post' },
127
+ )
128
+
129
+ useEventListener(anchor, 'pointerenter', keep)
130
+ useEventListener(anchor, 'pointerleave', leave)
131
+ useEventListener(anchor, 'focusin', keep)
132
+ useEventListener(anchor, 'focusout', event => {
133
+ const target = (event as FocusEvent).relatedTarget as Node | null
134
+ if (!target || (!anchor.value?.contains(target) && !panel.value?.contains(target))) close()
135
+ })
136
+ useEventListener(panel, 'pointerenter', keep)
137
+ useEventListener(panel, 'pointerleave', leave)
138
+ useEventListener(() => anchor.value?.ownerDocument, 'pointermove', track)
139
+ useEventListener(
140
+ () => anchor.value?.ownerDocument,
141
+ 'scroll',
142
+ event => {
143
+ if (root.open.value && (event.target as Node | null)?.contains(anchor.value ?? null))
144
+ dismiss()
145
+ },
146
+ { capture: true, passive: true },
147
+ )
148
+
149
+ onScopeDispose(() => {
150
+ cancel()
151
+ Object.assign(root, original)
152
+ })
153
+
154
+ function contentRef(value: Element | ComponentPublicInstance | null) {
155
+ content.value = value as ComponentPublicInstance | null
156
+ if (!value && !root.open.value) retained.value = undefined
157
+ }
158
+
159
+ return { reference, contentRef, present }
160
+ }
@@ -1,12 +1,12 @@
1
1
  <script setup lang="ts">
2
- import { computed, onBeforeUnmount, shallowRef, useId, watch } from 'vue'
2
+ import { computed, onBeforeUnmount, shallowRef, useId, watch, type StyleValue } from 'vue'
3
3
  import { Primitive } from 'reka-ui'
4
4
  import { cn } from '../../lib/cn'
5
5
  import { useRequiredLabel } from '../../lib/a11y'
6
6
  import Skeleton from '../skeleton/Skeleton.vue'
7
7
  import Lightbox from '../lightbox/Lightbox.vue'
8
8
  import type { LightboxItem } from '../lightbox/types'
9
- import { image, type ImageVariants } from './image.variants'
9
+ import { image, imageRoot, type ImageVariants } from './image.variants'
10
10
  import { useImage } from './composables/useImage'
11
11
  import { useImageGroup } from './context'
12
12
  import { useImageResolver } from './resolver'
@@ -25,9 +25,12 @@
25
25
  skeleton?: boolean
26
26
  eager?: boolean
27
27
  preview?: boolean | string
28
+ previewSize?: LightboxItem['previewSize']
28
29
  draggable?: boolean
29
30
  class?: string
31
+ style?: StyleValue
30
32
  imageClass?: string
33
+ imageStyle?: StyleValue
31
34
  }>(),
32
35
  {
33
36
  alt: '',
@@ -62,6 +65,7 @@
62
65
  typeof props.preview === 'string' ? props.preview : (props.src ?? ''),
63
66
  'preview',
64
67
  ),
68
+ previewSize: props.previewSize,
65
69
  alt: props.alt,
66
70
  fit: props.fit,
67
71
  source: () => imageEl.value,
@@ -93,20 +97,15 @@
93
97
  ref="rootEl"
94
98
  :as="props.preview ? 'button' : 'span'"
95
99
  :type="props.preview ? 'button' : undefined"
96
- :class="
97
- cn(
98
- 'relative block overflow-hidden',
99
- props.preview && 'hn-focus-ring cursor-zoom-in',
100
- props.class,
101
- )
102
- "
103
- :style="props.ratio ? { aspectRatio: String(props.ratio) } : undefined"
100
+ :class="cn(imageRoot({ preview: !!props.preview }), props.class)"
101
+ :style="[props.ratio ? { aspectRatio: String(props.ratio) } : undefined, props.style]"
104
102
  @click="openPreview"
105
103
  >
106
104
  <img
107
105
  v-if="showImage"
108
106
  ref="imageEl"
109
107
  v-bind="$attrs"
108
+ :style="props.imageStyle"
110
109
  :src="src"
111
110
  :alt="props.alt"
112
111
  :decoding="props.eager ? 'sync' : 'async'"
@@ -114,8 +113,8 @@
114
113
  :draggable="props.draggable"
115
114
  :class="
116
115
  cn(
117
- image({ fit: props.fit }),
118
- props.lazy ? !revealed && 'opacity-0' : 'relative z-10',
116
+ image({ fit: props.fit, lazy: props.lazy }),
117
+ props.lazy && !revealed && 'opacity-0',
119
118
  props.imageClass,
120
119
  )
121
120
  "
@@ -75,7 +75,7 @@ export function useImage(
75
75
  const style = getComputedStyle(el)
76
76
  try {
77
77
  return el.animate(frames, {
78
- duration: Number.parseFloat(style.getPropertyValue('--hn-duration-base')) || 0,
78
+ duration: Number.parseFloat(style.getPropertyValue('--hn-duration-fast')) || 0,
79
79
  easing: style.getPropertyValue('--hn-ease-enter').trim() || 'linear',
80
80
  fill: 'forwards',
81
81
  })
@@ -89,16 +89,19 @@ export function useImage(
89
89
  }
90
90
 
91
91
  async function reveal() {
92
- revealed.value = true
93
-
94
92
  if (!props.lazy) {
93
+ revealed.value = true
95
94
  skeletonMounted.value = false
96
95
  return
97
96
  }
98
97
 
98
+ const img = imageEl.value
99
+ const at = src.value
99
100
  await nextTick()
100
101
  await afterPaint()
102
+ if (imageEl.value !== img || src.value !== at) return
101
103
 
104
+ revealed.value = true
102
105
  const layer = skeletonEl.value
103
106
  const anim = layer && play(layer, [{ opacity: 1 }, { opacity: 0 }])
104
107
  if (!anim) {
@@ -10,7 +10,15 @@ export function useImageGroupState() {
10
10
  function byDom(a: LightboxItem, b: LightboxItem): number {
11
11
  const first = a.source?.()
12
12
  const second = b.source?.()
13
- if (!first || !second || first === second) return 0
13
+ if (
14
+ !first ||
15
+ !second ||
16
+ first === second ||
17
+ !('compareDocumentPosition' in first) ||
18
+ !('compareDocumentPosition' in second)
19
+ ) {
20
+ return 0
21
+ }
14
22
  return first.compareDocumentPosition(second) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
15
23
  }
16
24
 
@@ -1,8 +1,20 @@
1
1
  import { tv, type VariantProps } from '../../lib/tv'
2
2
 
3
+ export const imageRoot = tv({
4
+ base: 'relative isolate block w-full overflow-hidden',
5
+ variants: {
6
+ preview: {
7
+ true: 'hn-focus-ring cursor-zoom-in',
8
+ },
9
+ },
10
+ })
11
+
3
12
  export const image = tv({
4
- base: 'block size-full',
13
+ base: 'relative z-10 block size-full',
5
14
  variants: {
15
+ lazy: {
16
+ true: 'transition-opacity duration-(--hn-duration-base) ease-enter motion-reduce:transition-none',
17
+ },
6
18
  fit: {
7
19
  cover: 'object-cover',
8
20
  contain: 'object-contain',