reka-ui 2.5.0 → 2.6.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 (173) hide show
  1. package/dist/Calendar/CalendarCellTrigger.cjs +20 -48
  2. package/dist/Calendar/CalendarCellTrigger.cjs.map +1 -1
  3. package/dist/Calendar/CalendarCellTrigger.js +21 -49
  4. package/dist/Calendar/CalendarCellTrigger.js.map +1 -1
  5. package/dist/Calendar/CalendarRoot.cjs +3 -2
  6. package/dist/Calendar/CalendarRoot.cjs.map +1 -1
  7. package/dist/Calendar/CalendarRoot.js +3 -2
  8. package/dist/Calendar/CalendarRoot.js.map +1 -1
  9. package/dist/Combobox/ComboboxCancel.cjs +1 -0
  10. package/dist/Combobox/ComboboxCancel.cjs.map +1 -1
  11. package/dist/Combobox/ComboboxCancel.js +1 -0
  12. package/dist/Combobox/ComboboxCancel.js.map +1 -1
  13. package/dist/Combobox/ComboboxInput.cjs +1 -1
  14. package/dist/Combobox/ComboboxInput.cjs.map +1 -1
  15. package/dist/Combobox/ComboboxInput.js +1 -1
  16. package/dist/Combobox/ComboboxInput.js.map +1 -1
  17. package/dist/Combobox/ComboboxRoot.cjs +12 -4
  18. package/dist/Combobox/ComboboxRoot.cjs.map +1 -1
  19. package/dist/Combobox/ComboboxRoot.js +12 -4
  20. package/dist/Combobox/ComboboxRoot.js.map +1 -1
  21. package/dist/Listbox/ListboxContent.cjs +5 -3
  22. package/dist/Listbox/ListboxContent.cjs.map +1 -1
  23. package/dist/Listbox/ListboxContent.js +5 -3
  24. package/dist/Listbox/ListboxContent.js.map +1 -1
  25. package/dist/Listbox/ListboxItem.cjs +2 -3
  26. package/dist/Listbox/ListboxItem.cjs.map +1 -1
  27. package/dist/Listbox/ListboxItem.js +2 -3
  28. package/dist/Listbox/ListboxItem.js.map +1 -1
  29. package/dist/Menu/MenuCheckboxItem.cjs +4 -1
  30. package/dist/Menu/MenuCheckboxItem.cjs.map +1 -1
  31. package/dist/Menu/MenuCheckboxItem.js +5 -2
  32. package/dist/Menu/MenuCheckboxItem.js.map +1 -1
  33. package/dist/Menu/MenuRadioGroup.cjs +4 -1
  34. package/dist/Menu/MenuRadioGroup.cjs.map +1 -1
  35. package/dist/Menu/MenuRadioGroup.js +5 -2
  36. package/dist/Menu/MenuRadioGroup.js.map +1 -1
  37. package/dist/Menu/MenuRadioItem.cjs +5 -1
  38. package/dist/Menu/MenuRadioItem.cjs.map +1 -1
  39. package/dist/Menu/MenuRadioItem.js +5 -1
  40. package/dist/Menu/MenuRadioItem.js.map +1 -1
  41. package/dist/NavigationMenu/NavigationMenuTrigger.cjs +1 -1
  42. package/dist/NavigationMenu/NavigationMenuTrigger.cjs.map +1 -1
  43. package/dist/NavigationMenu/NavigationMenuTrigger.js +1 -1
  44. package/dist/NavigationMenu/NavigationMenuTrigger.js.map +1 -1
  45. package/dist/NavigationMenu/NavigationMenuViewport.cjs +7 -8
  46. package/dist/NavigationMenu/NavigationMenuViewport.cjs.map +1 -1
  47. package/dist/NavigationMenu/NavigationMenuViewport.js +8 -9
  48. package/dist/NavigationMenu/NavigationMenuViewport.js.map +1 -1
  49. package/dist/PinInput/PinInputInput.cjs +1 -1
  50. package/dist/PinInput/PinInputInput.cjs.map +1 -1
  51. package/dist/PinInput/PinInputInput.js +1 -1
  52. package/dist/PinInput/PinInputInput.js.map +1 -1
  53. package/dist/PinInput/PinInputRoot.cjs +2 -1
  54. package/dist/PinInput/PinInputRoot.cjs.map +1 -1
  55. package/dist/PinInput/PinInputRoot.js +2 -1
  56. package/dist/PinInput/PinInputRoot.js.map +1 -1
  57. package/dist/Presence/usePresence.cjs +1 -1
  58. package/dist/Presence/usePresence.cjs.map +1 -1
  59. package/dist/Presence/usePresence.js +1 -1
  60. package/dist/Presence/usePresence.js.map +1 -1
  61. package/dist/RangeCalendar/RangeCalendarCellTrigger.cjs +28 -53
  62. package/dist/RangeCalendar/RangeCalendarCellTrigger.cjs.map +1 -1
  63. package/dist/RangeCalendar/RangeCalendarCellTrigger.js +30 -55
  64. package/dist/RangeCalendar/RangeCalendarCellTrigger.js.map +1 -1
  65. package/dist/RangeCalendar/RangeCalendarNext.cjs +7 -3
  66. package/dist/RangeCalendar/RangeCalendarNext.cjs.map +1 -1
  67. package/dist/RangeCalendar/RangeCalendarNext.js +8 -4
  68. package/dist/RangeCalendar/RangeCalendarNext.js.map +1 -1
  69. package/dist/RangeCalendar/RangeCalendarPrev.cjs +7 -3
  70. package/dist/RangeCalendar/RangeCalendarPrev.cjs.map +1 -1
  71. package/dist/RangeCalendar/RangeCalendarPrev.js +8 -4
  72. package/dist/RangeCalendar/RangeCalendarPrev.js.map +1 -1
  73. package/dist/RangeCalendar/RangeCalendarRoot.cjs +3 -2
  74. package/dist/RangeCalendar/RangeCalendarRoot.cjs.map +1 -1
  75. package/dist/RangeCalendar/RangeCalendarRoot.js +3 -2
  76. package/dist/RangeCalendar/RangeCalendarRoot.js.map +1 -1
  77. package/dist/ScrollArea/ScrollAreaScrollbar.cjs.map +1 -1
  78. package/dist/ScrollArea/ScrollAreaScrollbar.js.map +1 -1
  79. package/dist/Select/BubbleSelect.cjs +10 -1
  80. package/dist/Select/BubbleSelect.cjs.map +1 -1
  81. package/dist/Select/BubbleSelect.js +10 -1
  82. package/dist/Select/BubbleSelect.js.map +1 -1
  83. package/dist/Splitter/SplitterPanel.cjs +4 -5
  84. package/dist/Splitter/SplitterPanel.cjs.map +1 -1
  85. package/dist/Splitter/SplitterPanel.js +4 -5
  86. package/dist/Splitter/SplitterPanel.js.map +1 -1
  87. package/dist/TagsInput/TagsInputInput.cjs +4 -0
  88. package/dist/TagsInput/TagsInputInput.cjs.map +1 -1
  89. package/dist/TagsInput/TagsInputInput.js +4 -0
  90. package/dist/TagsInput/TagsInputInput.js.map +1 -1
  91. package/dist/TagsInput/TagsInputItem.cjs +1 -1
  92. package/dist/TagsInput/TagsInputItem.js +1 -1
  93. package/dist/Toast/ToastProvider.cjs +6 -1
  94. package/dist/Toast/ToastProvider.cjs.map +1 -1
  95. package/dist/Toast/ToastProvider.js +6 -1
  96. package/dist/Toast/ToastProvider.js.map +1 -1
  97. package/dist/Toast/ToastRootImpl.cjs +6 -3
  98. package/dist/Toast/ToastRootImpl.cjs.map +1 -1
  99. package/dist/Toast/ToastRootImpl.js +6 -3
  100. package/dist/Toast/ToastRootImpl.js.map +1 -1
  101. package/dist/ToggleGroup/ToggleGroupItem.cjs +3 -4
  102. package/dist/ToggleGroup/ToggleGroupItem.cjs.map +1 -1
  103. package/dist/ToggleGroup/ToggleGroupItem.js +3 -4
  104. package/dist/ToggleGroup/ToggleGroupItem.js.map +1 -1
  105. package/dist/VisuallyHidden/VisuallyHidden.cjs +3 -1
  106. package/dist/VisuallyHidden/VisuallyHidden.cjs.map +1 -1
  107. package/dist/VisuallyHidden/VisuallyHidden.js +3 -1
  108. package/dist/VisuallyHidden/VisuallyHidden.js.map +1 -1
  109. package/dist/constant/components.cjs +2 -0
  110. package/dist/constant/components.cjs.map +1 -1
  111. package/dist/constant/components.js +2 -0
  112. package/dist/constant/components.js.map +1 -1
  113. package/dist/constant.d.cts +1 -1
  114. package/dist/constant.d.cts.map +1 -1
  115. package/dist/constant.d.ts +1 -1
  116. package/dist/constant.d.ts.map +1 -1
  117. package/dist/index.cjs +4 -3
  118. package/dist/index.d.cts +824 -791
  119. package/dist/index.d.cts.map +1 -1
  120. package/dist/index.d.ts +841 -808
  121. package/dist/index.d.ts.map +1 -1
  122. package/dist/index.js +3 -4
  123. package/dist/shared/useDirection.cjs +5 -0
  124. package/dist/shared/useDirection.cjs.map +1 -1
  125. package/dist/shared/useDirection.js +5 -0
  126. package/dist/shared/useDirection.js.map +1 -1
  127. package/dist/shared/useGraceArea.cjs +1 -1
  128. package/dist/shared/useGraceArea.cjs.map +1 -1
  129. package/dist/shared/useGraceArea.js +1 -1
  130. package/dist/shared/useGraceArea.js.map +1 -1
  131. package/dist/shared/useLocale.cjs +5 -0
  132. package/dist/shared/useLocale.cjs.map +1 -1
  133. package/dist/shared/useLocale.js +5 -0
  134. package/dist/shared/useLocale.js.map +1 -1
  135. package/package.json +4 -4
  136. package/src/Calendar/CalendarCellTrigger.vue +25 -75
  137. package/src/Calendar/CalendarRoot.vue +4 -1
  138. package/src/Combobox/ComboboxCancel.vue +3 -0
  139. package/src/Combobox/ComboboxInput.vue +3 -2
  140. package/src/Combobox/ComboboxRoot.vue +10 -2
  141. package/src/ContextMenu/ContextMenuRoot.vue +1 -1
  142. package/src/Listbox/ListboxContent.vue +18 -2
  143. package/src/Listbox/ListboxItem.vue +2 -4
  144. package/src/Menu/MenuCheckboxItem.vue +6 -2
  145. package/src/Menu/MenuRadioGroup.vue +6 -3
  146. package/src/Menu/MenuRadioItem.vue +6 -1
  147. package/src/NavigationMenu/NavigationMenuTrigger.vue +6 -2
  148. package/src/NavigationMenu/NavigationMenuViewport.vue +10 -8
  149. package/src/PinInput/PinInputInput.vue +1 -1
  150. package/src/PinInput/PinInputRoot.vue +2 -1
  151. package/src/Presence/usePresence.ts +2 -2
  152. package/src/RangeCalendar/RangeCalendarCellTrigger.vue +27 -76
  153. package/src/RangeCalendar/RangeCalendarNext.vue +2 -1
  154. package/src/RangeCalendar/RangeCalendarPrev.vue +2 -1
  155. package/src/RangeCalendar/RangeCalendarRoot.vue +4 -1
  156. package/src/ScrollArea/ScrollAreaScrollbar.vue +2 -2
  157. package/src/Select/BubbleSelect.vue +11 -0
  158. package/src/Splitter/SplitterPanel.vue +5 -5
  159. package/src/TagsInput/TagsInputInput.vue +5 -0
  160. package/src/TagsInput/TagsInputRoot.vue +1 -1
  161. package/src/Toast/ToastProvider.vue +8 -1
  162. package/src/Toast/ToastRootImpl.vue +9 -2
  163. package/src/ToggleGroup/ToggleGroupItem.vue +1 -2
  164. package/src/VisuallyHidden/VisuallyHidden.vue +6 -1
  165. package/src/index.ts +2 -0
  166. package/src/shared/useDirection.ts +5 -0
  167. package/src/shared/useGraceArea.ts +1 -1
  168. package/src/shared/useLocale.ts +5 -0
  169. package/dist/Calendar/utils.cjs +0 -15
  170. package/dist/Calendar/utils.cjs.map +0 -1
  171. package/dist/Calendar/utils.js +0 -9
  172. package/dist/Calendar/utils.js.map +0 -1
  173. package/src/Calendar/utils.ts +0 -5
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { Ref } from 'vue'
3
3
  import type { MenuGroupProps } from './MenuGroup.vue'
4
- import { createContext } from '@/shared'
4
+ import { createContext, useForwardProps } from '@/shared'
5
5
 
6
6
  interface MenuRadioGroupContext {
7
7
  modelValue: Ref<string>
@@ -23,7 +23,7 @@ export const [injectMenuRadioGroupContext, provideMenuRadioGroupContext]
23
23
  </script>
24
24
 
25
25
  <script setup lang="ts">
26
- import { useVModel } from '@vueuse/core'
26
+ import { reactiveOmit, useVModel } from '@vueuse/core'
27
27
  import MenuGroup from './MenuGroup.vue'
28
28
 
29
29
  const props = withDefaults(defineProps<MenuRadioGroupProps>(), {
@@ -38,6 +38,9 @@ defineSlots<{
38
38
  }) => any
39
39
  }>()
40
40
 
41
+ const delegatedProps = reactiveOmit(props, ['modelValue'])
42
+ const forwarded = useForwardProps(delegatedProps)
43
+
41
44
  const modelValue = useVModel(props, 'modelValue', emits)
42
45
 
43
46
  provideMenuRadioGroupContext({
@@ -49,7 +52,7 @@ provideMenuRadioGroupContext({
49
52
  </script>
50
53
 
51
54
  <template>
52
- <MenuGroup v-bind="props">
55
+ <MenuGroup v-bind="forwarded">
53
56
  <slot :model-value="modelValue" />
54
57
  </MenuGroup>
55
58
  </template>
@@ -3,6 +3,8 @@ import type {
3
3
  MenuItemEmits,
4
4
  MenuItemProps,
5
5
  } from './MenuItem.vue'
6
+ import { reactiveOmit } from '@vueuse/shared'
7
+ import { useForwardProps } from '@/shared'
6
8
 
7
9
  export type MenuRadioItemEmits = MenuItemEmits
8
10
 
@@ -22,6 +24,9 @@ import { getCheckedState } from './utils'
22
24
  const props = defineProps<MenuRadioItemProps>()
23
25
  const emits = defineEmits<MenuRadioItemEmits>()
24
26
 
27
+ const delegatedProps = reactiveOmit(props, ['value'])
28
+ const forwarded = useForwardProps(delegatedProps)
29
+
25
30
  const { value } = toRefs(props)
26
31
  const radioGroupContext = injectMenuRadioGroupContext()
27
32
  const modelValue = computed(
@@ -34,7 +39,7 @@ provideMenuItemIndicatorContext({ modelValue })
34
39
  <template>
35
40
  <MenuItem
36
41
  role="menuitemradio"
37
- v-bind="props"
42
+ v-bind="forwarded"
38
43
  :aria-checked="modelValue"
39
44
  :data-state="getCheckedState(modelValue)"
40
45
  @select="
@@ -87,9 +87,13 @@ function handlePointerLeave(ev: PointerEvent) {
87
87
  }
88
88
  }
89
89
 
90
- function handleClick(event: PointerEvent) {
91
- if (event.pointerType === 'mouse' && menuContext.disableClickTrigger.value)
90
+ function handleClick(event: MouseEvent | PointerEvent) {
91
+ if (
92
+ (!('pointerType' in event) || event.pointerType === 'mouse')
93
+ && menuContext.disableClickTrigger.value
94
+ ) {
92
95
  return
96
+ }
93
97
 
94
98
  // if open via pointermove, we prevent click event
95
99
  if (hasPointerMoveOpenedRef.value)
@@ -18,7 +18,7 @@ export interface NavigationMenuViewportProps extends PrimitiveProps {
18
18
 
19
19
  <script setup lang="ts">
20
20
  import { useResizeObserver } from '@vueuse/core'
21
- import { computed, ref, watch } from 'vue'
21
+ import { computed, nextTick, ref, watch } from 'vue'
22
22
  import { Presence } from '@/Presence'
23
23
  import {
24
24
  Primitive,
@@ -51,14 +51,16 @@ watch(currentElement, () => {
51
51
  const content = ref<HTMLElement>()
52
52
 
53
53
  watch([modelValue, open], () => {
54
- if (!currentElement.value)
55
- return
56
-
57
- requestAnimationFrame(() => {
58
- const el = (currentElement.value as HTMLElement)?.querySelector('[data-state=open]') as HTMLElement | undefined
59
- content.value = el
54
+ nextTick(() => {
55
+ if (!currentElement.value)
56
+ return
57
+
58
+ requestAnimationFrame(() => {
59
+ const el = (currentElement.value as HTMLElement)?.querySelector('[data-state=open]') as HTMLElement | undefined
60
+ content.value = el
61
+ })
60
62
  })
61
- }, { immediate: true, flush: 'post' })
63
+ }, { immediate: true })
62
64
 
63
65
  function updatePosition() {
64
66
  if (content.value && activeTrigger.value && rootNavigationMenu.value) {
@@ -42,7 +42,7 @@ function handleInput(event: InputEvent) {
42
42
  return
43
43
  }
44
44
 
45
- target.value = event.data ?? ''
45
+ target.value = event.data || target.value.slice(-1)
46
46
  updateModelValueAt(props.index, target.value)
47
47
 
48
48
  const nextEl = inputElements.value[props.index + 1]
@@ -92,7 +92,8 @@ const dir = useDirection(propDir)
92
92
 
93
93
  const modelValue = useVModel(props, 'modelValue', emits, {
94
94
  defaultValue: props.defaultValue ?? [] as any,
95
- passive: (props.modelValue === undefined) as false,
95
+ passive: true,
96
+ deep: true,
96
97
  }) as Ref<PinInputValue<Type>>
97
98
 
98
99
  const currentModelValue = computed(() => Array.isArray(modelValue.value) ? [...modelValue.value] : [])
@@ -1,8 +1,8 @@
1
1
  import type { Ref } from 'vue'
2
+ import { useStateMachine } from '@/shared'
2
3
  import { defaultWindow } from '@vueuse/core'
3
4
  import { isClient } from '@vueuse/shared'
4
5
  import { computed, nextTick, onUnmounted, ref, watch } from 'vue'
5
- import { useStateMachine } from '@/shared'
6
6
 
7
7
  export function usePresence(
8
8
  present: Ref<boolean>,
@@ -93,7 +93,7 @@ export function usePresence(
93
93
  const handleAnimationEnd = (event: AnimationEvent) => {
94
94
  const currentAnimationName = getAnimationName(node.value)
95
95
  const isCurrentAnimation = currentAnimationName.includes(
96
- event.animationName,
96
+ CSS.escape(event.animationName),
97
97
  )
98
98
  const directionName = state.value === 'mounted' ? 'enter' : 'leave'
99
99
  if (event.target === node.value && isCurrentAnimation) {
@@ -9,8 +9,7 @@ import {
9
9
  isToday,
10
10
  } from '@internationalized/date'
11
11
  import { computed, nextTick } from 'vue'
12
- import { getSelectableCells } from '@/Calendar/utils'
13
- import { getDaysInMonth, isBetweenInclusive, toDate } from '@/date'
12
+ import { isBetweenInclusive, toDate } from '@/date'
14
13
  import { useKbd } from '@/shared'
15
14
 
16
15
  export interface RangeCalendarCellTriggerProps extends PrimitiveProps {
@@ -179,101 +178,52 @@ function handleArrowKey(e: KeyboardEvent) {
179
178
  const sign = rootContext.dir.value === 'rtl' ? -1 : 1
180
179
  switch (e.code) {
181
180
  case kbd.ARROW_RIGHT:
182
- shiftFocus(currentElement.value, sign)
181
+ shiftFocus(props.day, sign)
183
182
  break
184
183
  case kbd.ARROW_LEFT:
185
- shiftFocus(currentElement.value, -sign)
184
+ shiftFocus(props.day, -sign)
186
185
  break
187
186
  case kbd.ARROW_UP:
188
- shiftFocus(currentElement.value, -indexIncrementation)
187
+ shiftFocus(props.day, -indexIncrementation)
189
188
  break
190
189
  case kbd.ARROW_DOWN:
191
- shiftFocus(currentElement.value, indexIncrementation)
190
+ shiftFocus(props.day, indexIncrementation)
192
191
  break
193
192
  case kbd.ENTER:
194
193
  case kbd.SPACE_CODE:
195
194
  changeDate(e, props.day)
196
195
  }
197
196
 
198
- function shiftFocus(node: HTMLElement, add: number) {
199
- const allCollectionItems: HTMLElement[] = getSelectableCells(parentElement)
200
- if (!allCollectionItems.length)
201
- return
202
-
203
- const index = allCollectionItems.indexOf(node)
204
- const newIndex = index + add
197
+ function shiftFocus(day: DateValue, add: number) {
198
+ const candidateDayValue = day.add({ days: add })
205
199
 
206
- if (newIndex >= 0 && newIndex < allCollectionItems.length) {
207
- if (allCollectionItems[newIndex].hasAttribute('data-disabled')) {
208
- shiftFocus(allCollectionItems[newIndex], add)
209
- }
210
- allCollectionItems[newIndex].focus()
200
+ if ((rootContext.minValue.value && candidateDayValue.compare(rootContext.minValue.value) < 0) || (rootContext.maxValue.value && candidateDayValue.compare(rootContext.maxValue.value) > 0))
211
201
  return
212
- }
213
202
 
214
- if (newIndex < 0) {
215
- if (rootContext.isPrevButtonDisabled())
216
- return
217
- rootContext.prevPage()
218
- nextTick(() => {
219
- const newCollectionItems: HTMLElement[] = getSelectableCells(parentElement)
220
- if (!newCollectionItems.length)
203
+ const candidateDay = parentElement.querySelector<HTMLElement>(`[data-value='${candidateDayValue.toString()}']:not([data-outside-view])`)
204
+ // If the date is not found it means we must change the page
205
+ if (!candidateDay) {
206
+ if (add > 0) {
207
+ if (rootContext.isNextButtonDisabled())
221
208
  return
222
- if (!rootContext.pagedNavigation.value && rootContext.numberOfMonths.value > 1) {
223
- // Placeholder is set to first month of the new page
224
- const numberOfDays = getDaysInMonth(rootContext.placeholder.value)
225
- const computedIndex = numberOfDays - Math.abs(newIndex)
226
- if (newCollectionItems[computedIndex].hasAttribute('data-disabled')) {
227
- shiftFocus(newCollectionItems[computedIndex], add)
228
- }
229
- newCollectionItems[
230
- computedIndex
231
- ].focus()
209
+ rootContext.nextPage()
210
+ }
211
+ else {
212
+ if (rootContext.isPrevButtonDisabled())
232
213
  return
233
- }
234
- const computedIndex = newCollectionItems.length - Math.abs(newIndex)
235
- if (newCollectionItems[computedIndex].hasAttribute('data-disabled')) {
236
- shiftFocus(newCollectionItems[computedIndex], add)
237
- }
238
- newCollectionItems[
239
- computedIndex
240
- ].focus()
214
+ rootContext.prevPage()
215
+ }
216
+ nextTick(() => {
217
+ shiftFocus(day, add)
241
218
  })
242
219
  return
243
220
  }
244
221
 
245
- if (newIndex >= allCollectionItems.length) {
246
- if (rootContext.isNextButtonDisabled())
247
- return
248
- rootContext.nextPage()
249
- nextTick(() => {
250
- const newCollectionItems: HTMLElement[] = getSelectableCells(parentElement)
251
- if (!newCollectionItems.length)
252
- return
253
-
254
- if (!rootContext.pagedNavigation.value && rootContext.numberOfMonths.value > 1) {
255
- // Placeholder is set to first month of the new page
256
- const numberOfDays = getDaysInMonth(
257
- rootContext.placeholder.value.add({ months: rootContext.numberOfMonths.value - 1 }),
258
- )
259
-
260
- const computedIndex = newIndex - allCollectionItems.length + (newCollectionItems.length - numberOfDays)
261
-
262
- if (newCollectionItems[computedIndex].hasAttribute('data-disabled')) {
263
- shiftFocus(newCollectionItems[computedIndex], add)
264
- }
265
- newCollectionItems[computedIndex].focus()
266
- return
267
- }
268
-
269
- const computedIndex = newIndex - allCollectionItems.length
270
- if (newCollectionItems[computedIndex].hasAttribute('data-disabled')) {
271
- shiftFocus(newCollectionItems[computedIndex], add)
272
- }
273
-
274
- newCollectionItems[computedIndex].focus()
275
- })
222
+ if (candidateDay && candidateDay.hasAttribute('data-disabled')) {
223
+ return shiftFocus(candidateDayValue, add)
276
224
  }
225
+ rootContext.onPlaceholderChange(candidateDayValue)
226
+ candidateDay?.focus()
277
227
  }
278
228
  }
279
229
  </script>
@@ -281,7 +231,8 @@ function handleArrowKey(e: KeyboardEvent) {
281
231
  <template>
282
232
  <Primitive
283
233
  ref="primitiveElement"
284
- v-bind="props"
234
+ :as="as"
235
+ :as-child="asChild"
285
236
  role="button"
286
237
  :aria-label="labelText"
287
238
  data-reka-calendar-cell-trigger
@@ -30,7 +30,8 @@ const rootContext = injectRangeCalendarRootContext()
30
30
 
31
31
  <template>
32
32
  <Primitive
33
- v-bind="props"
33
+ :as="as"
34
+ :as-child="asChild"
34
35
  aria-label="Next page"
35
36
  :type="as === 'button' ? 'button' : undefined"
36
37
  :aria-disabled="disabled || undefined"
@@ -30,7 +30,8 @@ const rootContext = injectRangeCalendarRootContext()
30
30
 
31
31
  <template>
32
32
  <Primitive
33
- v-bind="props"
33
+ :as="as"
34
+ :as-child="asChild"
34
35
  aria-label="Previous page"
35
36
  :type="as === 'button' ? 'button' : undefined"
36
37
  :aria-disabled="disabled || undefined"
@@ -66,6 +66,8 @@ type RangeCalendarRootContext = {
66
66
  disableDaysOutsideCurrentView: Ref<boolean>
67
67
  fixedDate: Ref<'start' | 'end' | undefined>
68
68
  maximumDays: Ref<number | undefined>
69
+ minValue: Ref<DateValue | undefined>
70
+ maxValue: Ref<DateValue | undefined>
69
71
  }
70
72
 
71
73
  export interface RangeCalendarRootProps extends PrimitiveProps {
@@ -435,6 +437,8 @@ provideRangeCalendarRootContext({
435
437
  disableDaysOutsideCurrentView,
436
438
  fixedDate,
437
439
  maximumDays,
440
+ minValue,
441
+ maxValue,
438
442
  })
439
443
 
440
444
  onMounted(() => {
@@ -448,7 +452,6 @@ onMounted(() => {
448
452
  ref="primitiveElement"
449
453
  :as="as"
450
454
  :as-child="asChild"
451
- role="application"
452
455
  :aria-label="fullCalendarLabel"
453
456
  :data-readonly="readonly ? '' : undefined"
454
457
  :data-disabled="disabled ? '' : undefined"
@@ -13,7 +13,7 @@ export interface ScrollAreaScrollbarProps extends PrimitiveProps {
13
13
  forceMount?: boolean
14
14
  }
15
15
 
16
- export interface ScrollAreaScollbarContext {
16
+ export interface ScrollAreaScrollbarContext {
17
17
  as: Ref<PrimitiveProps['as']>
18
18
  orientation: Ref<'vertical' | 'horizontal'>
19
19
  forceMount?: Ref<boolean>
@@ -22,7 +22,7 @@ export interface ScrollAreaScollbarContext {
22
22
  }
23
23
 
24
24
  export const [injectScrollAreaScrollbarContext, provideScrollAreaScrollbarContext]
25
- = createContext<ScrollAreaScollbarContext>('ScrollAreaScrollbar')
25
+ = createContext<ScrollAreaScrollbarContext>('ScrollAreaScrollbar')
26
26
  </script>
27
27
 
28
28
  <script setup lang="ts">
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, watch } from 'vue'
3
3
  import { VisuallyHidden } from '@/VisuallyHidden'
4
+ import { injectSelectRootContext } from './SelectRoot.vue'
4
5
 
5
6
  interface BubbleSelectProps {
6
7
  autocomplete?: string
@@ -16,6 +17,7 @@ interface BubbleSelectProps {
16
17
 
17
18
  const props = defineProps<BubbleSelectProps>()
18
19
  const selectElement = ref<HTMLElement>()
20
+ const rootContext = injectSelectRootContext()
19
21
 
20
22
  // This would bubble "change" event to form, with the target as Select element.
21
23
  watch(() => props.value, (cur, prev) => {
@@ -32,6 +34,14 @@ watch(() => props.value, (cur, prev) => {
32
34
  }
33
35
  })
34
36
 
37
+ /**
38
+ * Form autofill will trigger an `input` event on the `select` element.
39
+ * We listen to that event and update our internal state to support it.
40
+ */
41
+ function handleInput(event: Event) {
42
+ rootContext.onValueChange((event.target as HTMLSelectElement).value)
43
+ }
44
+
35
45
  /**
36
46
  * We purposefully use a `select` here to support form autofill as much
37
47
  * as possible.
@@ -49,6 +59,7 @@ watch(() => props.value, (cur, prev) => {
49
59
  <select
50
60
  ref="selectElement"
51
61
  v-bind="props"
62
+ @input="handleInput"
52
63
  >
53
64
  <slot />
54
65
  </select>
@@ -127,11 +127,11 @@ watch(() => panelDataRef.value.constraints, (constraints, prevConstraints) => {
127
127
  }, { deep: true })
128
128
 
129
129
  onMounted(() => {
130
- const panelData = panelDataRef.value
131
- registerPanel(panelData)
132
- onUnmounted(() => {
133
- unregisterPanel(panelData)
134
- })
130
+ registerPanel(panelDataRef.value)
131
+ })
132
+
133
+ onUnmounted(() => {
134
+ unregisterPanel(panelDataRef.value)
135
135
  })
136
136
 
137
137
  const style = computed(() => getPanelStyle(panelDataRef.value, props.defaultSize))
@@ -86,6 +86,11 @@ function handleInput(event: InputEvent) {
86
86
  const target = event.target as HTMLInputElement
87
87
  target.value = target.value.replace(delimiter, '')
88
88
 
89
+ if (target.value.trim() === '') {
90
+ target.value = ''
91
+ return
92
+ }
93
+
89
94
  const isAdded = context.onAddValue(target.value)
90
95
  if (isAdded)
91
96
  target.value = ''
@@ -5,7 +5,7 @@ import type { Direction, FormFieldProps } from '@/shared/types'
5
5
  import { computed, ref, toRefs } from 'vue'
6
6
  import { createContext, useArrowNavigation, useDirection, useFormControl, useForwardExpose } from '@/shared'
7
7
 
8
- export type AcceptableInputValue = string | Record<string, any>
8
+ export type AcceptableInputValue = string | number | bigint | Record<string, any>
9
9
 
10
10
  export interface TagsInputRootProps<T = AcceptableInputValue> extends PrimitiveProps, FormFieldProps {
11
11
  /** The controlled value of the tags input. Can be bind as `v-model`. */
@@ -7,6 +7,7 @@ import { createContext } from '@/shared'
7
7
  type ToastProviderContext = {
8
8
  label: Ref<string>
9
9
  duration: Ref<number>
10
+ disableSwipe: Ref<boolean>
10
11
  swipeDirection: Ref<SwipeDirection>
11
12
  swipeThreshold: Ref<number>
12
13
  toastCount: Ref<number>
@@ -30,6 +31,11 @@ export interface ToastProviderProps {
30
31
  * @defaultValue 5000
31
32
  */
32
33
  duration?: number
34
+ /**
35
+ * Whether to disable the ability to swipe to close the toast.
36
+ * @defaultValue false
37
+ */
38
+ disableSwipe?: boolean
33
39
  /**
34
40
  * Direction of pointer swipe that should close the toast.
35
41
  * @defaultValue 'right'
@@ -59,7 +65,7 @@ const props = withDefaults(defineProps<ToastProviderProps>(), {
59
65
  swipeDirection: 'right',
60
66
  swipeThreshold: 50,
61
67
  })
62
- const { label, duration, swipeDirection, swipeThreshold } = toRefs(props)
68
+ const { label, duration, disableSwipe, swipeDirection, swipeThreshold } = toRefs(props)
63
69
  useCollection({ isProvider: true })
64
70
 
65
71
  const viewport = ref<HTMLElement>()
@@ -75,6 +81,7 @@ if (props.label && typeof props.label === 'string' && !props.label.trim()) {
75
81
  provideToastProviderContext({
76
82
  label,
77
83
  duration,
84
+ disableSwipe,
78
85
  swipeDirection,
79
86
  swipeThreshold,
80
87
  toastCount,
@@ -203,12 +203,17 @@ provideToastRootContext({ onClose: handleClose })
203
203
  :as-child="asChild"
204
204
  :data-state="open ? 'open' : 'closed'"
205
205
  :data-swipe-direction="providerContext.swipeDirection.value"
206
- :style="{ userSelect: 'none', touchAction: 'none' }"
206
+ :style="providerContext.disableSwipe.value
207
+ ? undefined
208
+ : { userSelect: 'none', touchAction: 'none' }"
207
209
  @pointerdown.left="(event: PointerEvent) => {
210
+ if (providerContext.disableSwipe.value) return;
211
+
208
212
  pointerStartRef = { x: event.clientX, y: event.clientY };
209
213
  }"
210
214
  @pointermove="(event: PointerEvent) => {
211
- if (!pointerStartRef) return;
215
+ if (providerContext.disableSwipe.value || !pointerStartRef) return;
216
+
212
217
  const x = event.clientX - pointerStartRef.x;
213
218
  const y = event.clientY - pointerStartRef.y;
214
219
  const hasSwipeMoveStarted = Boolean(swipeDeltaRef);
@@ -237,6 +242,8 @@ provideToastRootContext({ onClose: handleClose })
237
242
  }
238
243
  }"
239
244
  @pointerup="(event: PointerEvent) => {
245
+ if (providerContext.disableSwipe.value) return;
246
+
240
247
  const delta = swipeDeltaRef;
241
248
  const target = event.target as HTMLElement;
242
249
  if (target.hasPointerCapture(event.pointerId)) {
@@ -33,8 +33,7 @@ const { forwardRef } = useForwardExpose()
33
33
  <component
34
34
  :is="rootContext.rovingFocus.value ? RovingFocusItem : Primitive"
35
35
  as-child
36
- :focusable="!disabled"
37
- :active="pressed"
36
+ v-bind="rootContext.rovingFocus.value ? { focusable: !disabled, active: pressed } : {}"
38
37
  >
39
38
  <Toggle
40
39
  v-bind="props"
@@ -20,7 +20,7 @@ withDefaults(defineProps<VisuallyHiddenProps>(), { as: 'span', feature: 'focusab
20
20
  :data-hidden="feature === 'fully-hidden' ? '' : undefined"
21
21
  :tabindex="feature === 'fully-hidden' ? '-1' : undefined"
22
22
  :style="{
23
- // See: https://github.com/twbs/bootstrap/blob/master/scss/mixins/_screen-reader.scss
23
+ // See: https://github.com/twbs/bootstrap/blob/a360960b8dfdb4bf48f87539c2243458fa0366f7/scss/mixins/_visually-hidden.scss
24
24
  position: 'absolute',
25
25
  border: 0,
26
26
  width: '1px',
@@ -32,6 +32,11 @@ withDefaults(defineProps<VisuallyHiddenProps>(), { as: 'span', feature: 'focusab
32
32
  clipPath: 'inset(50%)',
33
33
  whiteSpace: 'nowrap',
34
34
  wordWrap: 'normal',
35
+
36
+ // Prevent causing unnecessary container scroll
37
+ // @see https://github.com/unovue/reka-ui/issues/2127
38
+ top: '-1px',
39
+ left: '-1px',
35
40
  }"
36
41
  >
37
42
  <slot />
package/src/index.ts CHANGED
@@ -43,12 +43,14 @@ export {
43
43
  type Formatter,
44
44
  useBodyScrollLock,
45
45
  useDateFormatter,
46
+ useDirection,
46
47
  useEmitAsProps,
47
48
  useFilter,
48
49
  useForwardExpose,
49
50
  useForwardProps,
50
51
  useForwardPropsEmits,
51
52
  useId,
53
+ useLocale,
52
54
  useStateMachine,
53
55
  withDefault,
54
56
  } from './shared'
@@ -3,6 +3,11 @@ import type { Direction } from './types'
3
3
  import { computed, ref } from 'vue'
4
4
  import { injectConfigProviderContext } from '@/ConfigProvider/ConfigProvider.vue'
5
5
 
6
+ /**
7
+ * The `useDirection` function provides a way to access the current direction in your application.
8
+ * @param {Ref<Direction | undefined>} [dir] - An optional ref containing the direction (ltr or rtl).
9
+ * @returns computed value that combines with the resolved direction.
10
+ */
6
11
  export function useDirection(dir?: Ref<Direction | undefined>) {
7
12
  const context = injectConfigProviderContext({
8
13
  dir: ref('ltr'),
@@ -44,7 +44,7 @@ export function useGraceArea(triggerElement: Ref<HTMLElement | undefined>, conta
44
44
  watchEffect((cleanupFn) => {
45
45
  if (pointerGraceArea.value) {
46
46
  const handleTrackPointerGrace = (event: PointerEvent) => {
47
- if (!pointerGraceArea.value || !(event.target instanceof HTMLElement))
47
+ if (!pointerGraceArea.value || !(event.target instanceof Element))
48
48
  return
49
49
 
50
50
  const target = event.target
@@ -2,6 +2,11 @@ import type { Ref } from 'vue'
2
2
  import { computed, ref } from 'vue'
3
3
  import { injectConfigProviderContext } from '@/ConfigProvider/ConfigProvider.vue'
4
4
 
5
+ /**
6
+ * The `useLocale` function provides a way to access the current locale in your application.
7
+ * @param {Ref<string | undefined>} [locale] - An optional ref containing the locale.
8
+ * @returns A computed ref holding the resolved locale.
9
+ */
5
10
  export function useLocale(locale?: Ref<string | undefined>) {
6
11
  const context = injectConfigProviderContext({
7
12
  locale: ref('en'),
@@ -1,15 +0,0 @@
1
-
2
- //#region src/Calendar/utils.ts
3
- const SELECTOR = "[data-reka-calendar-cell-trigger]:not([data-outside-view]):not([data-outside-visible-view])";
4
- function getSelectableCells(calendar) {
5
- return Array.from(calendar.querySelectorAll(SELECTOR)) ?? [];
6
- }
7
-
8
- //#endregion
9
- Object.defineProperty(exports, 'getSelectableCells', {
10
- enumerable: true,
11
- get: function () {
12
- return getSelectableCells;
13
- }
14
- });
15
- //# sourceMappingURL=utils.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.cjs","names":["calendar: HTMLElement"],"sources":["../../src/Calendar/utils.ts"],"sourcesContent":[],"mappings":";;AAAA,MAAa,WACT;AACJ,SAAgB,mBAAmBA,UAAsC;AACvE,QAAO,MAAM,KAAK,SAAS,iBAAiB,SAAS,CAAC,IAAI,CAAE;AAC7D"}
@@ -1,9 +0,0 @@
1
- //#region src/Calendar/utils.ts
2
- const SELECTOR = "[data-reka-calendar-cell-trigger]:not([data-outside-view]):not([data-outside-visible-view])";
3
- function getSelectableCells(calendar) {
4
- return Array.from(calendar.querySelectorAll(SELECTOR)) ?? [];
5
- }
6
-
7
- //#endregion
8
- export { getSelectableCells };
9
- //# sourceMappingURL=utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","names":["calendar: HTMLElement"],"sources":["../../src/Calendar/utils.ts"],"sourcesContent":[],"mappings":";AAAA,MAAa,WACT;AACJ,SAAgB,mBAAmBA,UAAsC;AACvE,QAAO,MAAM,KAAK,SAAS,iBAAiB,SAAS,CAAC,IAAI,CAAE;AAC7D"}
@@ -1,5 +0,0 @@
1
- export const SELECTOR
2
- = '[data-reka-calendar-cell-trigger]:not([data-outside-view]):not([data-outside-visible-view])'
3
- export function getSelectableCells(calendar: HTMLElement): HTMLElement[] {
4
- return Array.from(calendar.querySelectorAll(SELECTOR)) ?? []
5
- }