@hina-ui/vue 1.3.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +4336 -2180
- package/dist/index.js.map +1 -1
- package/dist/types/components/dialog/Dialog.vue.d.ts +3 -1
- package/dist/types/components/dialog/Dialog.vue.d.ts.map +1 -1
- package/dist/types/components/drawer/Drawer.vue.d.ts +21 -14
- package/dist/types/components/drawer/Drawer.vue.d.ts.map +1 -1
- package/dist/types/components/drawer/drawer.variants.d.ts +10 -1
- package/dist/types/components/drawer/drawer.variants.d.ts.map +1 -1
- package/dist/types/components/dropdown-menu/DropdownMenu.vue.d.ts +4 -1
- package/dist/types/components/dropdown-menu/DropdownMenu.vue.d.ts.map +1 -1
- package/dist/types/components/hover-card/HoverCard.vue.d.ts +10 -7
- package/dist/types/components/hover-card/HoverCard.vue.d.ts.map +1 -1
- package/dist/types/components/hover-card/HoverCardAnchor.vue.d.ts +29 -0
- package/dist/types/components/hover-card/HoverCardAnchor.vue.d.ts.map +1 -0
- package/dist/types/components/hover-card/composables/useHoverCardAnchor.d.ts +22 -0
- package/dist/types/components/hover-card/composables/useHoverCardAnchor.d.ts.map +1 -0
- package/dist/types/components/image/Image.vue.d.ts +3 -1
- package/dist/types/components/image/Image.vue.d.ts.map +1 -1
- package/dist/types/components/image/composables/useImageGroupState.d.ts.map +1 -1
- package/dist/types/components/image/image.variants.d.ts +1 -1
- package/dist/types/components/lightbox/Lightbox.vue.d.ts.map +1 -1
- package/dist/types/components/lightbox/LightboxChrome.vue.d.ts +4 -0
- package/dist/types/components/lightbox/LightboxChrome.vue.d.ts.map +1 -1
- package/dist/types/components/lightbox/LightboxToolbar.vue.d.ts +4 -0
- package/dist/types/components/lightbox/LightboxToolbar.vue.d.ts.map +1 -1
- package/dist/types/components/lightbox/composables/useLightboxFrames.d.ts +4 -1
- package/dist/types/components/lightbox/composables/useLightboxFrames.d.ts.map +1 -1
- package/dist/types/components/lightbox/composables/useLightboxLarge.d.ts +1 -0
- package/dist/types/components/lightbox/composables/useLightboxLarge.d.ts.map +1 -1
- package/dist/types/components/lightbox/composables/useLightboxLayout.d.ts +17 -0
- package/dist/types/components/lightbox/composables/useLightboxLayout.d.ts.map +1 -0
- package/dist/types/components/lightbox/composables/useLightboxPhase.d.ts +1 -1
- package/dist/types/components/lightbox/composables/useLightboxPhase.d.ts.map +1 -1
- package/dist/types/components/lightbox/composables/useLightboxPose.d.ts.map +1 -1
- package/dist/types/components/lightbox/composables/useLightboxRotation.d.ts +5 -1
- package/dist/types/components/lightbox/composables/useLightboxRotation.d.ts.map +1 -1
- package/dist/types/components/lightbox/composables/useLightboxZoom.d.ts +10 -1
- package/dist/types/components/lightbox/composables/useLightboxZoom.d.ts.map +1 -1
- package/dist/types/components/lightbox/lightbox.variants.d.ts +2 -0
- package/dist/types/components/lightbox/lightbox.variants.d.ts.map +1 -0
- package/dist/types/components/lightbox/types.d.ts +7 -1
- package/dist/types/components/lightbox/types.d.ts.map +1 -1
- package/dist/types/components/lightbox/utils/pose.d.ts +2 -2
- package/dist/types/components/lightbox/utils/pose.d.ts.map +1 -1
- package/dist/types/components/lightbox/utils/source.d.ts +4 -0
- package/dist/types/components/lightbox/utils/source.d.ts.map +1 -0
- package/dist/types/components/lightbox/utils/zoom.d.ts +8 -4
- package/dist/types/components/lightbox/utils/zoom.d.ts.map +1 -1
- package/dist/types/components/pagination/Pagination.vue.d.ts +59 -0
- package/dist/types/components/pagination/Pagination.vue.d.ts.map +1 -0
- package/dist/types/components/pagination/PaginationContent.vue.d.ts +23 -0
- package/dist/types/components/pagination/PaginationContent.vue.d.ts.map +1 -0
- package/dist/types/components/pagination/PaginationControl.vue.d.ts +10 -0
- package/dist/types/components/pagination/PaginationControl.vue.d.ts.map +1 -0
- package/dist/types/components/pagination/PaginationEllipsis.vue.d.ts +23 -0
- package/dist/types/components/pagination/PaginationEllipsis.vue.d.ts.map +1 -0
- package/dist/types/components/pagination/PaginationInfo.vue.d.ts +24 -0
- package/dist/types/components/pagination/PaginationInfo.vue.d.ts.map +1 -0
- package/dist/types/components/pagination/PaginationJump.vue.d.ts +7 -0
- package/dist/types/components/pagination/PaginationJump.vue.d.ts.map +1 -0
- package/dist/types/components/pagination/PaginationPage.vue.d.ts +20 -0
- package/dist/types/components/pagination/PaginationPage.vue.d.ts.map +1 -0
- package/dist/types/components/pagination/PaginationPages.vue.d.ts +27 -0
- package/dist/types/components/pagination/PaginationPages.vue.d.ts.map +1 -0
- package/dist/types/components/pagination/PaginationPopup.vue.d.ts +8 -0
- package/dist/types/components/pagination/PaginationPopup.vue.d.ts.map +1 -0
- package/dist/types/components/pagination/PaginationSize.vue.d.ts +7 -0
- package/dist/types/components/pagination/PaginationSize.vue.d.ts.map +1 -0
- package/dist/types/components/pagination/composables/usePagination.d.ts +25 -0
- package/dist/types/components/pagination/composables/usePagination.d.ts.map +1 -0
- package/dist/types/components/pagination/composables/usePaginationEllipsis.d.ts +34 -0
- package/dist/types/components/pagination/composables/usePaginationEllipsis.d.ts.map +1 -0
- package/dist/types/components/pagination/composables/usePaginationJump.d.ts +8 -0
- package/dist/types/components/pagination/composables/usePaginationJump.d.ts.map +1 -0
- package/dist/types/components/pagination/composables/usePaginationPageTooltip.d.ts +3 -0
- package/dist/types/components/pagination/composables/usePaginationPageTooltip.d.ts.map +1 -0
- package/dist/types/components/pagination/composables/usePaginationWindow.d.ts +188 -0
- package/dist/types/components/pagination/composables/usePaginationWindow.d.ts.map +1 -0
- package/dist/types/components/pagination/context.d.ts +19 -0
- package/dist/types/components/pagination/context.d.ts.map +1 -0
- package/dist/types/components/pagination/pagination.variants.d.ts +68 -0
- package/dist/types/components/pagination/pagination.variants.d.ts.map +1 -0
- package/dist/types/components/pagination/types.d.ts +23 -0
- package/dist/types/components/pagination/types.d.ts.map +1 -0
- package/dist/types/components/pagination/utils/ranges.d.ts +3 -0
- package/dist/types/components/pagination/utils/ranges.d.ts.map +1 -0
- package/dist/types/components/popover/Popover.vue.d.ts +4 -1
- package/dist/types/components/popover/Popover.vue.d.ts.map +1 -1
- package/dist/types/components/range-slider/RangeSlider.vue.d.ts +1 -0
- package/dist/types/components/range-slider/RangeSlider.vue.d.ts.map +1 -1
- package/dist/types/components/sheet/Sheet.vue.d.ts +21 -14
- package/dist/types/components/sheet/Sheet.vue.d.ts.map +1 -1
- package/dist/types/components/sheet/sheet.variants.d.ts +54 -3
- package/dist/types/components/sheet/sheet.variants.d.ts.map +1 -1
- package/dist/types/components/slider/Slider.vue.d.ts +1 -0
- package/dist/types/components/slider/Slider.vue.d.ts.map +1 -1
- package/dist/types/components/slider/slider.variants.d.ts.map +1 -1
- package/dist/types/components/tooltip/Tooltip.vue.d.ts +4 -15
- package/dist/types/components/tooltip/Tooltip.vue.d.ts.map +1 -1
- package/dist/types/components/tooltip/TooltipBubble.vue.d.ts +20 -0
- package/dist/types/components/tooltip/TooltipBubble.vue.d.ts.map +1 -0
- package/dist/types/components/tooltip/TooltipDirectiveRoot.d.ts +33 -0
- package/dist/types/components/tooltip/TooltipDirectiveRoot.d.ts.map +1 -0
- package/dist/types/components/tooltip/composables/useTooltipTarget.d.ts +2 -0
- package/dist/types/components/tooltip/composables/useTooltipTarget.d.ts.map +1 -0
- package/dist/types/components/tooltip/directive.d.ts +4 -0
- package/dist/types/components/tooltip/directive.d.ts.map +1 -0
- package/dist/types/components/tooltip/types.d.ts +14 -0
- package/dist/types/components/tooltip/types.d.ts.map +1 -0
- package/dist/types/components/tooltip/utils/directiveContext.d.ts +10 -0
- package/dist/types/components/tooltip/utils/directiveContext.d.ts.map +1 -0
- package/dist/types/components/tree-select/TreeSelect.vue.d.ts +6 -1
- package/dist/types/components/tree-select/TreeSelect.vue.d.ts.map +1 -1
- package/dist/types/components/tree-select/TreeSelectSearch.vue.d.ts +22 -0
- package/dist/types/components/tree-select/TreeSelectSearch.vue.d.ts.map +1 -0
- package/dist/types/components/tree-select/composables/useTreeSelect.d.ts +35 -0
- package/dist/types/components/tree-select/composables/useTreeSelect.d.ts.map +1 -0
- package/dist/types/components/tree-select/tree-select.variants.d.ts +1 -1
- package/dist/types/components/tree-select/tree-select.variants.d.ts.map +1 -1
- package/dist/types/components/tree-select/utils/filterTree.d.ts +7 -0
- package/dist/types/components/tree-select/utils/filterTree.d.ts.map +1 -0
- package/dist/types/index.d.ts +10 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/anchored-overlay.d.ts +12 -2
- package/dist/types/lib/anchored-overlay.d.ts.map +1 -1
- package/dist/types/lib/overlay-anchor.d.ts +16 -0
- package/dist/types/lib/overlay-anchor.d.ts.map +1 -0
- package/dist/types/lib/overlay-positioner.d.ts +3 -0
- package/dist/types/lib/overlay-positioner.d.ts.map +1 -0
- package/dist/types/lib/pointer-corridor.d.ts +7 -0
- package/dist/types/lib/pointer-corridor.d.ts.map +1 -0
- package/dist/types/lib/scroll-viewport.d.ts +9 -0
- package/dist/types/lib/scroll-viewport.d.ts.map +1 -0
- package/dist/types/lib/useDirection.d.ts +7 -0
- package/dist/types/lib/useDirection.d.ts.map +1 -0
- package/dist/types/locale/en-US.d.ts.map +1 -1
- package/dist/types/locale/index.d.ts.map +1 -1
- package/dist/types/locale/types.d.ts +13 -0
- package/dist/types/locale/types.d.ts.map +1 -1
- package/dist/types/locale/zh-CN.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/badge/badge.variants.ts +1 -1
- package/src/components/dialog/Dialog.vue +5 -1
- package/src/components/drawer/Drawer.vue +69 -32
- package/src/components/drawer/drawer.variants.ts +6 -2
- package/src/components/dropdown-menu/DropdownMenu.vue +18 -5
- package/src/components/hover-card/HoverCard.vue +39 -16
- package/src/components/hover-card/HoverCardAnchor.vue +18 -0
- package/src/components/hover-card/composables/useHoverCardAnchor.ts +151 -0
- package/src/components/image/Image.vue +2 -0
- package/src/components/image/composables/useImageGroupState.ts +9 -1
- package/src/components/image/image.variants.ts +1 -1
- package/src/components/lightbox/Lightbox.vue +23 -17
- package/src/components/lightbox/LightboxChrome.vue +7 -1
- package/src/components/lightbox/LightboxToolbar.vue +16 -2
- package/src/components/lightbox/composables/useLightboxFrames.ts +108 -12
- package/src/components/lightbox/composables/useLightboxLarge.ts +4 -1
- package/src/components/lightbox/composables/useLightboxLayout.ts +44 -0
- package/src/components/lightbox/composables/useLightboxPhase.ts +12 -4
- package/src/components/lightbox/composables/useLightboxPose.ts +17 -19
- package/src/components/lightbox/composables/useLightboxRotation.ts +14 -4
- package/src/components/lightbox/composables/useLightboxZoom.ts +51 -9
- package/src/components/lightbox/lightbox.variants.ts +5 -0
- package/src/components/lightbox/types.ts +5 -1
- package/src/components/lightbox/utils/pose.ts +13 -6
- package/src/components/lightbox/utils/source.ts +17 -0
- package/src/components/lightbox/utils/zoom.ts +21 -7
- package/src/components/pagination/Pagination.vue +118 -0
- package/src/components/pagination/PaginationContent.vue +29 -0
- package/src/components/pagination/PaginationControl.vue +42 -0
- package/src/components/pagination/PaginationEllipsis.vue +67 -0
- package/src/components/pagination/PaginationInfo.vue +18 -0
- package/src/components/pagination/PaginationJump.vue +32 -0
- package/src/components/pagination/PaginationPage.vue +34 -0
- package/src/components/pagination/PaginationPages.vue +43 -0
- package/src/components/pagination/PaginationPopup.vue +92 -0
- package/src/components/pagination/PaginationSize.vue +30 -0
- package/src/components/pagination/composables/usePagination.ts +76 -0
- package/src/components/pagination/composables/usePaginationEllipsis.ts +269 -0
- package/src/components/pagination/composables/usePaginationJump.ts +23 -0
- package/src/components/pagination/composables/usePaginationPageTooltip.ts +23 -0
- package/src/components/pagination/composables/usePaginationWindow.ts +116 -0
- package/src/components/pagination/context.ts +23 -0
- package/src/components/pagination/pagination.variants.ts +32 -0
- package/src/components/pagination/types.ts +19 -0
- package/src/components/pagination/utils/ranges.ts +12 -0
- package/src/components/popover/Popover.vue +17 -7
- package/src/components/range-slider/RangeSlider.vue +6 -0
- package/src/components/sheet/Sheet.vue +67 -24
- package/src/components/sheet/sheet.variants.ts +17 -4
- package/src/components/slider/Slider.vue +6 -0
- package/src/components/slider/slider.variants.ts +1 -0
- package/src/components/tooltip/Tooltip.vue +10 -33
- package/src/components/tooltip/TooltipBubble.vue +36 -0
- package/src/components/tooltip/TooltipDirectiveRoot.ts +61 -0
- package/src/components/tooltip/composables/useTooltipTarget.ts +56 -0
- package/src/components/tooltip/directive.ts +54 -0
- package/src/components/tooltip/types.ts +15 -0
- package/src/components/tooltip/utils/directiveContext.ts +32 -0
- package/src/components/tree-select/TreeSelect.vue +90 -61
- package/src/components/tree-select/TreeSelectSearch.vue +48 -0
- package/src/components/tree-select/composables/useTreeSelect.ts +130 -0
- package/src/components/tree-select/tree-select.variants.ts +2 -2
- package/src/components/tree-select/utils/filterTree.ts +19 -0
- package/src/index.ts +10 -1
- package/src/lib/anchored-overlay.ts +28 -19
- package/src/lib/overlay-anchor.ts +65 -0
- package/src/lib/overlay-positioner.ts +25 -0
- package/src/lib/pointer-corridor.ts +26 -0
- package/src/lib/scroll-viewport.ts +8 -0
- package/src/lib/useDirection.ts +31 -0
- package/src/locale/en-US.ts +15 -1
- package/src/locale/index.ts +1 -0
- package/src/locale/types.ts +13 -0
- package/src/locale/zh-CN.ts +15 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { computed, ref, type Ref } from 'vue'
|
|
2
|
+
import { useEventListener, useMutationObserver, useResizeObserver } from '@vueuse/core'
|
|
3
|
+
|
|
4
|
+
export function usePaginationPageTooltip(
|
|
5
|
+
label: Readonly<Ref<HTMLElement | null>>,
|
|
6
|
+
blocked: Readonly<Ref<boolean>>,
|
|
7
|
+
) {
|
|
8
|
+
const content = ref('')
|
|
9
|
+
|
|
10
|
+
function measure() {
|
|
11
|
+
const element = label.value
|
|
12
|
+
content.value =
|
|
13
|
+
element && element.scrollWidth > element.clientWidth
|
|
14
|
+
? (element.textContent?.trim() ?? '')
|
|
15
|
+
: ''
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
useResizeObserver(label, measure)
|
|
19
|
+
useMutationObserver(label, measure, { childList: true, characterData: true, subtree: true })
|
|
20
|
+
useEventListener(() => label.value?.ownerDocument.fonts, 'loadingdone', measure)
|
|
21
|
+
|
|
22
|
+
return computed(() => (blocked.value ? false : content.value))
|
|
23
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { computed, nextTick, ref, shallowRef, watch } from 'vue'
|
|
2
|
+
import { useEventListener, useResizeObserver } from '@vueuse/core'
|
|
3
|
+
import type ScrollArea from '../../scroll-area/ScrollArea.vue'
|
|
4
|
+
import type { PaginationEllipsisController } from './usePaginationEllipsis'
|
|
5
|
+
|
|
6
|
+
export function usePaginationWindow(controller: PaginationEllipsisController) {
|
|
7
|
+
const scroll = shallowRef<InstanceType<typeof ScrollArea>>()
|
|
8
|
+
const rowsHost = shallowRef<HTMLElement>()
|
|
9
|
+
const viewport = computed(() => scroll.value?.viewport)
|
|
10
|
+
const top = ref(0)
|
|
11
|
+
const height = ref(224)
|
|
12
|
+
const rowHeight = ref(36)
|
|
13
|
+
const rowGap = ref(0)
|
|
14
|
+
const rowStep = computed(() => rowHeight.value + rowGap.value)
|
|
15
|
+
const activePage = ref(1)
|
|
16
|
+
const range = controller.displayRange
|
|
17
|
+
const count = computed(() => (range.value ? range.value.to - range.value.from + 1 : 0))
|
|
18
|
+
const extent = computed(() => Math.max(0, count.value * rowStep.value - rowGap.value))
|
|
19
|
+
const rows = computed(() => {
|
|
20
|
+
if (!range.value) return []
|
|
21
|
+
const start = Math.max(0, Math.floor(top.value / rowStep.value) - 3)
|
|
22
|
+
const end = Math.min(count.value, start + Math.ceil(height.value / rowStep.value) + 7)
|
|
23
|
+
const values = Array.from(
|
|
24
|
+
{ length: Math.max(0, end - start) },
|
|
25
|
+
(_, i) => start + i + range.value!.from,
|
|
26
|
+
)
|
|
27
|
+
if (
|
|
28
|
+
activePage.value >= range.value.from &&
|
|
29
|
+
activePage.value <= range.value.to &&
|
|
30
|
+
!values.includes(activePage.value)
|
|
31
|
+
)
|
|
32
|
+
values.push(activePage.value)
|
|
33
|
+
return values.map(page => ({ page, top: (page - range.value!.from) * rowStep.value }))
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
function measure() {
|
|
37
|
+
if (viewport.value) height.value = viewport.value.clientHeight || 224
|
|
38
|
+
const button = rowsHost.value?.querySelector<HTMLElement>('[data-hn-pagination-choice]')
|
|
39
|
+
if (button) {
|
|
40
|
+
rowHeight.value = button.offsetHeight
|
|
41
|
+
rowGap.value = Number.parseFloat(getComputedStyle(rowsHost.value!).rowGap) || 0
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function focusPage(page: number) {
|
|
46
|
+
if (!range.value || !controller.open.value) return
|
|
47
|
+
activePage.value = Math.min(range.value.to, Math.max(range.value.from, page))
|
|
48
|
+
const element = viewport.value
|
|
49
|
+
if (element) {
|
|
50
|
+
const offset = (activePage.value - range.value.from) * rowStep.value
|
|
51
|
+
if (offset < element.scrollTop) element.scrollTop = offset
|
|
52
|
+
else if (offset + rowHeight.value > element.scrollTop + element.clientHeight)
|
|
53
|
+
element.scrollTop = offset + rowHeight.value - element.clientHeight
|
|
54
|
+
top.value = element.scrollTop
|
|
55
|
+
}
|
|
56
|
+
await nextTick()
|
|
57
|
+
rowsHost.value
|
|
58
|
+
?.querySelector<HTMLElement>('[data-hn-pagination-choice="' + activePage.value + '"]')
|
|
59
|
+
?.focus({ preventScroll: true })
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function keydown(event: KeyboardEvent) {
|
|
63
|
+
if (!range.value) return
|
|
64
|
+
const step = Math.max(1, Math.floor(height.value / rowStep.value))
|
|
65
|
+
const targets: Record<string, number> = {
|
|
66
|
+
ArrowDown: activePage.value + 1,
|
|
67
|
+
ArrowUp: activePage.value - 1,
|
|
68
|
+
Home: range.value.from,
|
|
69
|
+
End: range.value.to,
|
|
70
|
+
PageDown: activePage.value + step,
|
|
71
|
+
PageUp: activePage.value - step,
|
|
72
|
+
}
|
|
73
|
+
const target = targets[event.key]
|
|
74
|
+
if (target === undefined) return
|
|
75
|
+
event.preventDefault()
|
|
76
|
+
event.stopPropagation()
|
|
77
|
+
void focusPage(target)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
watch(
|
|
81
|
+
[range, controller.open],
|
|
82
|
+
() => {
|
|
83
|
+
if (!controller.open.value || !range.value) return
|
|
84
|
+
activePage.value = range.value.from
|
|
85
|
+
top.value = 0
|
|
86
|
+
if (viewport.value) viewport.value.scrollTop = 0
|
|
87
|
+
},
|
|
88
|
+
{ immediate: true },
|
|
89
|
+
)
|
|
90
|
+
watch(
|
|
91
|
+
[controller.focusRequest, viewport],
|
|
92
|
+
async ([request, element]) => {
|
|
93
|
+
if (!request || !element || !range.value) return
|
|
94
|
+
await nextTick()
|
|
95
|
+
measure()
|
|
96
|
+
await focusPage(request.edge === 'first' ? range.value.from : range.value.to)
|
|
97
|
+
controller.focusRequest.value = undefined
|
|
98
|
+
},
|
|
99
|
+
{ flush: 'post' },
|
|
100
|
+
)
|
|
101
|
+
useResizeObserver(
|
|
102
|
+
() => rowsHost.value?.querySelector<HTMLElement>('[data-hn-pagination-choice]'),
|
|
103
|
+
measure,
|
|
104
|
+
)
|
|
105
|
+
useResizeObserver(rowsHost, measure)
|
|
106
|
+
useResizeObserver(viewport, measure)
|
|
107
|
+
useEventListener(
|
|
108
|
+
viewport,
|
|
109
|
+
'scroll',
|
|
110
|
+
() => {
|
|
111
|
+
top.value = viewport.value?.scrollTop ?? 0
|
|
112
|
+
},
|
|
113
|
+
{ passive: true },
|
|
114
|
+
)
|
|
115
|
+
return { scroll, rowsHost, activePage, extent, rows, keydown }
|
|
116
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { inject, provide, type InjectionKey, type Ref } from 'vue'
|
|
2
|
+
import type { PaginationState } from './types'
|
|
3
|
+
|
|
4
|
+
export interface PaginationContext {
|
|
5
|
+
state: Readonly<Ref<PaginationState>>
|
|
6
|
+
blocked: Readonly<Ref<boolean>>
|
|
7
|
+
size: Readonly<Ref<'sm' | 'md' | 'lg'>>
|
|
8
|
+
direction: Readonly<Ref<'ltr' | 'rtl'>>
|
|
9
|
+
siblingCount: Readonly<Ref<number>>
|
|
10
|
+
showFirstLast: Readonly<Ref<boolean>>
|
|
11
|
+
options: Readonly<Ref<Array<{ value: number; label: string }>>>
|
|
12
|
+
update: (page: number) => void
|
|
13
|
+
resize: (pageSize: number) => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const key: InjectionKey<PaginationContext> = Symbol('HnPagination')
|
|
17
|
+
|
|
18
|
+
export const providePagination = (context: PaginationContext) => provide(key, context)
|
|
19
|
+
export function usePaginationContext() {
|
|
20
|
+
const context = inject(key)
|
|
21
|
+
if (!context) throw new Error('Pagination parts require a Pagination parent')
|
|
22
|
+
return context
|
|
23
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { tv } from '../../lib/tv'
|
|
2
|
+
|
|
3
|
+
export const pagination = tv({
|
|
4
|
+
base: 'flex w-full shrink-0 flex-wrap items-center gap-x-4 gap-y-3',
|
|
5
|
+
variants: {
|
|
6
|
+
align: {
|
|
7
|
+
start: 'justify-start',
|
|
8
|
+
center: 'justify-center',
|
|
9
|
+
end: 'justify-end',
|
|
10
|
+
between: 'justify-between',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
export const paginationList = tv({
|
|
16
|
+
base: 'relative isolate flex max-w-full flex-wrap items-center gap-1',
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export const paginationItem = tv({
|
|
20
|
+
base: 'min-w-0 px-0 tabular-nums [&>span]:min-w-0',
|
|
21
|
+
variants: {
|
|
22
|
+
size: {
|
|
23
|
+
sm: 'size-[var(--hn-control-h-sm)]',
|
|
24
|
+
md: 'size-[var(--hn-control-h-md)]',
|
|
25
|
+
lg: 'size-[var(--hn-control-h-lg)]',
|
|
26
|
+
},
|
|
27
|
+
selected: { true: 'bg-accent text-accent-on' },
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: { size: 'md' },
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
export const paginationArrow = tv({ variants: { dir: { ltr: '', rtl: 'rotate-180' } } })
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface PaginationChange {
|
|
2
|
+
page: number
|
|
3
|
+
pageSize: number
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface PaginationState extends PaginationChange {
|
|
7
|
+
total: number
|
|
8
|
+
pageCount: number
|
|
9
|
+
from: number
|
|
10
|
+
to: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type PaginationEntry = { type: 'page'; value: number } | { type: 'ellipsis' }
|
|
14
|
+
export type PaginationSide = 'prev' | 'next'
|
|
15
|
+
export interface PaginationRange {
|
|
16
|
+
side: PaginationSide
|
|
17
|
+
from: number
|
|
18
|
+
to: number
|
|
19
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PaginationEntry, PaginationRange } from '../types'
|
|
2
|
+
|
|
3
|
+
export function paginationRanges(items: PaginationEntry[]): PaginationRange[] {
|
|
4
|
+
return items.flatMap((item, index) => {
|
|
5
|
+
if (item.type !== 'ellipsis') return []
|
|
6
|
+
const previous = items[index - 1]
|
|
7
|
+
const next = items[index + 1]
|
|
8
|
+
if (previous?.type !== 'page' || next?.type !== 'page' || next.value <= previous.value + 1)
|
|
9
|
+
return []
|
|
10
|
+
return [{ side: index === 1 ? 'prev' : 'next', from: previous.value + 1, to: next.value - 1 }]
|
|
11
|
+
})
|
|
12
|
+
}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import type { OverlayAnchor, OverlayPositionStrategy } from '../../lib/overlay-anchor'
|
|
2
3
|
import { computed } from 'vue'
|
|
3
4
|
import { PopoverRoot, PopoverTrigger, PopoverPortal, type PopoverContentEmits } from 'reka-ui'
|
|
4
5
|
import PopoverContent from './PopoverContent.vue'
|
|
5
6
|
import { useAnchoredOverlay } from '../../lib/anchored-overlay'
|
|
6
7
|
import Card from '../card/Card.vue'
|
|
7
|
-
import { useOverlayPortal } from '../../lib/overlay-portal'
|
|
8
8
|
import { cn } from '../../lib/cn'
|
|
9
9
|
|
|
10
10
|
defineOptions({ name: 'HnPopover', inheritAttrs: false })
|
|
11
11
|
|
|
12
12
|
const props = withDefaults(
|
|
13
13
|
defineProps<{
|
|
14
|
-
anchor?:
|
|
14
|
+
anchor?: OverlayAnchor | null
|
|
15
|
+
updatePositionStrategy?: OverlayPositionStrategy
|
|
15
16
|
modal?: boolean
|
|
16
17
|
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
17
18
|
align?: 'start' | 'center' | 'end'
|
|
@@ -19,18 +20,26 @@
|
|
|
19
20
|
padded?: boolean
|
|
20
21
|
class?: string
|
|
21
22
|
}>(),
|
|
22
|
-
{
|
|
23
|
+
{
|
|
24
|
+
updatePositionStrategy: 'optimized',
|
|
25
|
+
side: 'bottom',
|
|
26
|
+
align: 'center',
|
|
27
|
+
sideOffset: 8,
|
|
28
|
+
padded: true,
|
|
29
|
+
modal: true,
|
|
30
|
+
},
|
|
23
31
|
)
|
|
24
32
|
|
|
25
33
|
const open = defineModel<boolean>('open')
|
|
26
34
|
const emit = defineEmits<PopoverContentEmits>()
|
|
27
35
|
defineSlots<{ default?(): unknown; content?(): unknown }>()
|
|
28
|
-
const { trigger, reference, visible, events } = useAnchoredOverlay(
|
|
29
|
-
|
|
36
|
+
const { trigger, content, present, reference, visible, events } = useAnchoredOverlay(
|
|
37
|
+
props,
|
|
38
|
+
open,
|
|
39
|
+
emit,
|
|
40
|
+
event => emit('openAutoFocus', event),
|
|
30
41
|
)
|
|
31
42
|
|
|
32
|
-
const { content, present } = useOverlayPortal(visible)
|
|
33
|
-
|
|
34
43
|
const pressOrigin = computed(() => {
|
|
35
44
|
if (props.side === 'left') return 'right'
|
|
36
45
|
if (props.side === 'right') return 'left'
|
|
@@ -54,6 +63,7 @@
|
|
|
54
63
|
<PopoverContent
|
|
55
64
|
v-bind="{ ...$attrs, ...events }"
|
|
56
65
|
:reference="reference"
|
|
66
|
+
:update-position-strategy="props.updatePositionStrategy"
|
|
57
67
|
as-child
|
|
58
68
|
:side="props.side"
|
|
59
69
|
:align="props.align"
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { useFieldControl } from '../form-field/context'
|
|
6
6
|
import { useUiLocale } from '../../locale'
|
|
7
7
|
import { useSliderChrome } from '../slider/composables/useSliderChrome'
|
|
8
|
+
import { useDirection } from '../../lib/useDirection'
|
|
8
9
|
import SliderHandle from '../slider/SliderHandle.vue'
|
|
9
10
|
import SliderMarks from '../slider/SliderMarks.vue'
|
|
10
11
|
import {
|
|
@@ -22,6 +23,7 @@
|
|
|
22
23
|
min?: number
|
|
23
24
|
max?: number
|
|
24
25
|
step?: number
|
|
26
|
+
dir?: 'ltr' | 'rtl'
|
|
25
27
|
minSteps?: number
|
|
26
28
|
marks?: Array<{ value: number; label?: string }>
|
|
27
29
|
label?: 'auto' | 'always' | 'none'
|
|
@@ -37,6 +39,7 @@
|
|
|
37
39
|
|
|
38
40
|
const model = defineModel<[number, number]>()
|
|
39
41
|
|
|
42
|
+
const { root, direction, rootDirection } = useDirection(() => props.dir)
|
|
40
43
|
const t = useUiLocale()
|
|
41
44
|
const { labelledBy, invalid, disabled, describedBy } = useFieldControl({
|
|
42
45
|
disabled: () => props.disabled,
|
|
@@ -66,6 +69,7 @@
|
|
|
66
69
|
|
|
67
70
|
<template>
|
|
68
71
|
<span
|
|
72
|
+
ref="root"
|
|
69
73
|
data-hn-range-slider
|
|
70
74
|
data-hn-state-group
|
|
71
75
|
role="group"
|
|
@@ -73,6 +77,7 @@
|
|
|
73
77
|
:aria-labelledby="labelledBy"
|
|
74
78
|
:aria-describedby="describedBy"
|
|
75
79
|
:aria-invalid="invalid || undefined"
|
|
80
|
+
:dir="rootDirection"
|
|
76
81
|
:data-disabled="disabled ? '' : undefined"
|
|
77
82
|
:data-dragging="dragging ? '' : undefined"
|
|
78
83
|
:style="position"
|
|
@@ -81,6 +86,7 @@
|
|
|
81
86
|
v-on="listeners"
|
|
82
87
|
>
|
|
83
88
|
<SliderRoot
|
|
89
|
+
:dir="direction"
|
|
84
90
|
:model-value="values"
|
|
85
91
|
:min="props.min"
|
|
86
92
|
:max="props.max"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed
|
|
2
|
+
import { computed } from 'vue'
|
|
3
3
|
import {
|
|
4
4
|
DialogClose,
|
|
5
5
|
DialogContent,
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
DialogTitle,
|
|
11
11
|
DialogTrigger,
|
|
12
12
|
} from 'reka-ui'
|
|
13
|
+
import { useOverlayPortal } from '../../lib/overlay-portal'
|
|
14
|
+
import { useScrollViewport } from '../../lib/scroll-viewport'
|
|
13
15
|
import { cn } from '../../lib/cn'
|
|
14
|
-
import { useUiLocale } from '../../locale'
|
|
15
16
|
import Card from '../card/Card.vue'
|
|
16
17
|
import CloseButton from '../close-button/CloseButton.vue'
|
|
17
18
|
import Heading from '../heading/Heading.vue'
|
|
@@ -26,16 +27,29 @@
|
|
|
26
27
|
defineProps<{
|
|
27
28
|
title: string
|
|
28
29
|
description?: string
|
|
30
|
+
header?: boolean
|
|
31
|
+
closable?: boolean
|
|
29
32
|
handle?: boolean
|
|
30
33
|
locked?: boolean
|
|
31
34
|
class?: string
|
|
32
35
|
}>(),
|
|
33
|
-
{ handle: true, locked: false },
|
|
36
|
+
{ header: true, closable: true, handle: true, locked: false },
|
|
34
37
|
)
|
|
35
38
|
|
|
39
|
+
const slots = defineSlots<{
|
|
40
|
+
default?(): unknown
|
|
41
|
+
icon?(): unknown
|
|
42
|
+
title?(): unknown
|
|
43
|
+
body?(props: { close: () => void }): unknown
|
|
44
|
+
content?(props: { close: () => void }): unknown
|
|
45
|
+
footer?(props: { close: () => void }): unknown
|
|
46
|
+
}>()
|
|
47
|
+
|
|
48
|
+
const { scrollArea, viewport } = useScrollViewport()
|
|
49
|
+
defineExpose({ viewport })
|
|
50
|
+
|
|
36
51
|
const open = defineModel<boolean>('open')
|
|
37
|
-
const
|
|
38
|
-
const panel = shallowRef<{ $el: HTMLElement } | null>(null)
|
|
52
|
+
const { content: panel, present } = useOverlayPortal(open)
|
|
39
53
|
|
|
40
54
|
const { dragging, offset, onPointerDown } = useDragToDismiss(() => panel.value?.$el ?? null, {
|
|
41
55
|
enabled: () => !props.locked,
|
|
@@ -63,54 +77,83 @@
|
|
|
63
77
|
<DialogTrigger v-if="$slots.default" as-child>
|
|
64
78
|
<slot />
|
|
65
79
|
</DialogTrigger>
|
|
66
|
-
<DialogPortal>
|
|
80
|
+
<DialogPortal v-if="present">
|
|
67
81
|
<DialogOverlay class="hn-scrim" />
|
|
68
82
|
<DialogContent as-child @escape-key-down="guard" @interact-outside="guard">
|
|
69
83
|
<Card
|
|
70
84
|
ref="panel"
|
|
85
|
+
v-bind="props.description ? {} : { 'aria-describedby': undefined }"
|
|
71
86
|
data-hn-sheet
|
|
72
87
|
:data-dragging="dragging ? '' : undefined"
|
|
73
88
|
:padded="false"
|
|
74
89
|
:style="style"
|
|
75
|
-
:class="
|
|
90
|
+
:class="
|
|
91
|
+
cn(sheetPanel({ grip: props.header || props.handle, padded: !slots.body }), props.class)
|
|
92
|
+
"
|
|
76
93
|
>
|
|
94
|
+
<template v-if="!props.header || slots.body">
|
|
95
|
+
<DialogTitle as-child>
|
|
96
|
+
<Heading :level="2" class="sr-only">{{ props.title }}</Heading>
|
|
97
|
+
</DialogTitle>
|
|
98
|
+
<DialogDescription v-if="props.description" class="sr-only">
|
|
99
|
+
{{ props.description }}
|
|
100
|
+
</DialogDescription>
|
|
101
|
+
</template>
|
|
77
102
|
<div
|
|
103
|
+
v-if="props.handle || (props.header && !slots.body)"
|
|
78
104
|
data-hn-sheet-grip
|
|
79
105
|
:data-dragging="dragging ? '' : undefined"
|
|
80
|
-
:class="sheetGrip()"
|
|
106
|
+
:class="sheetGrip({ standalone: !!slots.body })"
|
|
81
107
|
@pointerdown="onPointerDown"
|
|
82
108
|
>
|
|
83
109
|
<div
|
|
84
110
|
v-if="props.handle"
|
|
85
111
|
aria-hidden="true"
|
|
86
112
|
:data-disabled="props.locked ? '' : undefined"
|
|
87
|
-
:class="sheetHandle()"
|
|
113
|
+
:class="sheetHandle({ header: props.header && !slots.body })"
|
|
88
114
|
/>
|
|
89
|
-
<div
|
|
115
|
+
<div
|
|
116
|
+
v-if="props.header && !slots.body"
|
|
117
|
+
class="flex items-start justify-between gap-4 px-(--hn-panel-p)"
|
|
118
|
+
>
|
|
90
119
|
<div class="flex min-w-0 flex-col gap-1.5">
|
|
91
|
-
<
|
|
92
|
-
<
|
|
93
|
-
|
|
120
|
+
<div class="flex min-w-0 items-center gap-2">
|
|
121
|
+
<span
|
|
122
|
+
v-if="slots.icon"
|
|
123
|
+
class="text-muted flex shrink-0 [&_svg]:size-5"
|
|
124
|
+
aria-hidden="true"
|
|
125
|
+
>
|
|
126
|
+
<slot name="icon" />
|
|
127
|
+
</span>
|
|
128
|
+
<DialogTitle as-child>
|
|
129
|
+
<Heading :level="2" size="lg" class="min-w-0">
|
|
130
|
+
<slot name="title">{{ props.title }}</slot>
|
|
131
|
+
</Heading>
|
|
132
|
+
</DialogTitle>
|
|
133
|
+
</div>
|
|
94
134
|
<DialogDescription v-if="props.description" as-child>
|
|
95
135
|
<Text tone="muted">{{ props.description }}</Text>
|
|
96
136
|
</DialogDescription>
|
|
97
137
|
</div>
|
|
98
|
-
<DialogClose v-if="!props.handle" as-child>
|
|
138
|
+
<DialogClose v-if="!props.handle && props.closable" as-child>
|
|
99
139
|
<CloseButton :disabled="props.locked" class="-mt-1.5 -me-1.5 shrink-0" />
|
|
100
140
|
</DialogClose>
|
|
101
141
|
</div>
|
|
102
142
|
</div>
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
143
|
+
<slot v-if="slots.body" name="body" :close="close" />
|
|
144
|
+
<template v-else>
|
|
145
|
+
<ScrollArea v-if="$slots.content" ref="scrollArea" class="min-h-0 grow">
|
|
146
|
+
<div class="px-(--hn-panel-p) py-1">
|
|
147
|
+
<slot name="content" :close="close" />
|
|
148
|
+
</div>
|
|
149
|
+
</ScrollArea>
|
|
150
|
+
<div
|
|
151
|
+
v-if="$slots.footer"
|
|
152
|
+
class="flex shrink-0 justify-end gap-(--hn-inline-gap) px-(--hn-panel-p)"
|
|
153
|
+
>
|
|
154
|
+
<slot name="footer" :close="close" />
|
|
106
155
|
</div>
|
|
107
|
-
</
|
|
108
|
-
<div
|
|
109
|
-
v-if="$slots.footer"
|
|
110
|
-
class="flex shrink-0 justify-end gap-(--hn-inline-gap) px-(--hn-panel-p)"
|
|
111
|
-
>
|
|
112
|
-
<slot name="footer" :close="close" />
|
|
113
|
-
</div>
|
|
156
|
+
</template>
|
|
114
157
|
</Card>
|
|
115
158
|
</DialogContent>
|
|
116
159
|
</DialogPortal>
|
|
@@ -3,17 +3,30 @@ import { tv } from '../../lib/tv'
|
|
|
3
3
|
export const sheetPanel = tv({
|
|
4
4
|
base: [
|
|
5
5
|
'hn-anim-sheet-bottom hn-transition pointer-events-auto fixed inset-x-0 bottom-0 z-(--hn-z-overlay)',
|
|
6
|
-
'mx-auto flex max-h-[calc(100dvh-3rem)] w-full flex-col
|
|
7
|
-
'rounded-t-xl rounded-b-none border-b-0
|
|
8
|
-
'pb-[max(var(--hn-panel-p),env(safe-area-inset-bottom))]',
|
|
6
|
+
'mx-auto flex max-h-[calc(100dvh-3rem)] w-full flex-col sm:max-w-xl',
|
|
7
|
+
'rounded-t-xl rounded-b-none border-b-0 shadow-lg outline-none',
|
|
9
8
|
'data-dragging:transition-none',
|
|
10
9
|
],
|
|
10
|
+
variants: {
|
|
11
|
+
padded: { true: 'gap-4 pb-[max(var(--hn-panel-p),env(safe-area-inset-bottom))]' },
|
|
12
|
+
grip: { true: '', false: '' },
|
|
13
|
+
},
|
|
14
|
+
compoundVariants: [
|
|
15
|
+
{ padded: true, grip: true, class: 'pt-2' },
|
|
16
|
+
{ padded: true, grip: false, class: 'pt-(--hn-panel-p)' },
|
|
17
|
+
],
|
|
18
|
+
defaultVariants: { grip: true, padded: true },
|
|
11
19
|
})
|
|
12
20
|
|
|
13
21
|
export const sheetGrip = tv({
|
|
14
22
|
base: 'flex shrink-0 cursor-grab touch-none flex-col select-none data-dragging:cursor-grabbing',
|
|
23
|
+
variants: { standalone: { true: 'py-2' } },
|
|
15
24
|
})
|
|
16
25
|
|
|
17
26
|
export const sheetHandle = tv({
|
|
18
|
-
base: 'bg-line-strong hn-transition-base mx-auto
|
|
27
|
+
base: 'bg-line-strong hn-transition-base mx-auto h-1.5 w-10 rounded-full data-disabled:opacity-50',
|
|
28
|
+
variants: {
|
|
29
|
+
header: { true: 'mb-3', false: '' },
|
|
30
|
+
},
|
|
31
|
+
defaultVariants: { header: true },
|
|
19
32
|
})
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { useFieldControl } from '../form-field/context'
|
|
6
6
|
import { useUiLocale } from '../../locale'
|
|
7
7
|
import { useSliderChrome } from './composables/useSliderChrome'
|
|
8
|
+
import { useDirection } from '../../lib/useDirection'
|
|
8
9
|
import SliderHandle from './SliderHandle.vue'
|
|
9
10
|
import SliderMarks from './SliderMarks.vue'
|
|
10
11
|
import {
|
|
@@ -22,6 +23,7 @@
|
|
|
22
23
|
min?: number
|
|
23
24
|
max?: number
|
|
24
25
|
step?: number
|
|
26
|
+
dir?: 'ltr' | 'rtl'
|
|
25
27
|
marks?: Array<{ value: number; label?: string }>
|
|
26
28
|
label?: 'auto' | 'always' | 'none'
|
|
27
29
|
format?: (value: number) => string
|
|
@@ -36,6 +38,7 @@
|
|
|
36
38
|
|
|
37
39
|
const model = defineModel<number>()
|
|
38
40
|
|
|
41
|
+
const { root, direction, rootDirection } = useDirection(() => props.dir)
|
|
39
42
|
const t = useUiLocale()
|
|
40
43
|
const { labelledBy, invalid, disabled, describedBy } = useFieldControl({
|
|
41
44
|
disabled: () => props.disabled,
|
|
@@ -60,8 +63,10 @@
|
|
|
60
63
|
|
|
61
64
|
<template>
|
|
62
65
|
<span
|
|
66
|
+
ref="root"
|
|
63
67
|
data-hn-slider
|
|
64
68
|
data-hn-state-group
|
|
69
|
+
:dir="rootDirection"
|
|
65
70
|
:data-disabled="disabled ? '' : undefined"
|
|
66
71
|
:data-dragging="dragging ? '' : undefined"
|
|
67
72
|
:style="position"
|
|
@@ -70,6 +75,7 @@
|
|
|
70
75
|
v-on="listeners"
|
|
71
76
|
>
|
|
72
77
|
<SliderRoot
|
|
78
|
+
:dir="direction"
|
|
73
79
|
:model-value="values"
|
|
74
80
|
:min="props.min"
|
|
75
81
|
:max="props.max"
|
|
@@ -18,6 +18,7 @@ export const sliderRoot = tv({
|
|
|
18
18
|
base: [
|
|
19
19
|
'bg-line-strong relative flex h-[var(--hn-slider-h)] w-full cursor-pointer touch-none rounded-full select-none',
|
|
20
20
|
'data-disabled:pointer-events-none',
|
|
21
|
+
'[&[dir=rtl]>[role=slider]]:[--reka-slider-thumb-transform:translateX(50%)]',
|
|
21
22
|
],
|
|
22
23
|
})
|
|
23
24
|
|
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { TooltipRoot, TooltipTrigger
|
|
3
|
-
import
|
|
2
|
+
import { TooltipRoot, TooltipTrigger } from 'reka-ui'
|
|
3
|
+
import TooltipBubble from './TooltipBubble.vue'
|
|
4
|
+
import type { TooltipProps } from './types'
|
|
4
5
|
|
|
5
6
|
defineOptions({ name: 'HnTooltip' })
|
|
6
7
|
|
|
7
|
-
const props = withDefaults(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
align?: 'start' | 'center' | 'end'
|
|
12
|
-
sideOffset?: number
|
|
13
|
-
open?: boolean
|
|
14
|
-
disabled?: boolean
|
|
15
|
-
class?: string
|
|
16
|
-
}>(),
|
|
17
|
-
{ side: 'top', align: 'center', sideOffset: 8, open: undefined, disabled: false },
|
|
18
|
-
)
|
|
8
|
+
const props = withDefaults(defineProps<TooltipProps>(), {
|
|
9
|
+
open: undefined,
|
|
10
|
+
disabled: false,
|
|
11
|
+
})
|
|
19
12
|
</script>
|
|
20
13
|
|
|
21
14
|
<template>
|
|
@@ -23,24 +16,8 @@
|
|
|
23
16
|
<TooltipTrigger as-child>
|
|
24
17
|
<slot />
|
|
25
18
|
</TooltipTrigger>
|
|
26
|
-
<
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
:align="props.align"
|
|
30
|
-
:side-offset="props.sideOffset"
|
|
31
|
-
:aria-label="props.content"
|
|
32
|
-
:update-position-strategy="props.open === undefined ? 'optimized' : 'always'"
|
|
33
|
-
:class="
|
|
34
|
-
cn(
|
|
35
|
-
'hn-anim-pop [--hn-pop-in:var(--hn-duration-fast)] bg-neutral-solid text-neutral-solid-on z-(--hn-z-overlay)',
|
|
36
|
-
'max-w-xs rounded-md px-2.5 py-1 text-xs shadow-md',
|
|
37
|
-
props.class,
|
|
38
|
-
)
|
|
39
|
-
"
|
|
40
|
-
>
|
|
41
|
-
<slot name="content">{{ props.content }}</slot>
|
|
42
|
-
<TooltipArrow :width="10" :height="5" class="fill-neutral-solid" />
|
|
43
|
-
</TooltipContent>
|
|
44
|
-
</TooltipPortal>
|
|
19
|
+
<TooltipBubble v-bind="props">
|
|
20
|
+
<slot name="content">{{ props.content }}</slot>
|
|
21
|
+
</TooltipBubble>
|
|
45
22
|
</TooltipRoot>
|
|
46
23
|
</template>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { TooltipPortal, TooltipContent, TooltipArrow } from 'reka-ui'
|
|
3
|
+
import { cn } from '../../lib/cn'
|
|
4
|
+
import type { TooltipProps } from './types'
|
|
5
|
+
|
|
6
|
+
defineOptions({ name: 'HnTooltipBubble' })
|
|
7
|
+
|
|
8
|
+
const props = withDefaults(defineProps<TooltipProps>(), {
|
|
9
|
+
side: 'top',
|
|
10
|
+
align: 'center',
|
|
11
|
+
sideOffset: 8,
|
|
12
|
+
open: undefined,
|
|
13
|
+
})
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<template>
|
|
17
|
+
<TooltipPortal>
|
|
18
|
+
<TooltipContent
|
|
19
|
+
:side="props.side"
|
|
20
|
+
:align="props.align"
|
|
21
|
+
:side-offset="props.sideOffset"
|
|
22
|
+
:aria-label="props.content"
|
|
23
|
+
:update-position-strategy="props.open === undefined ? 'optimized' : 'always'"
|
|
24
|
+
:class="
|
|
25
|
+
cn(
|
|
26
|
+
'hn-anim-pop [--hn-pop-in:var(--hn-duration-fast)] bg-neutral-solid text-neutral-solid-on z-(--hn-z-overlay)',
|
|
27
|
+
'max-w-xs rounded-md px-2.5 py-1 text-xs shadow-md',
|
|
28
|
+
props.class,
|
|
29
|
+
)
|
|
30
|
+
"
|
|
31
|
+
>
|
|
32
|
+
<slot>{{ props.content }}</slot>
|
|
33
|
+
<TooltipArrow :width="10" :height="5" class="fill-neutral-solid" />
|
|
34
|
+
</TooltipContent>
|
|
35
|
+
</TooltipPortal>
|
|
36
|
+
</template>
|