reka-ui 2.9.7 → 2.9.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/dist/Autocomplete/AutocompleteInput.cjs +12 -16
  2. package/dist/Autocomplete/AutocompleteInput.cjs.map +1 -1
  3. package/dist/Autocomplete/AutocompleteInput.js +13 -17
  4. package/dist/Autocomplete/AutocompleteInput.js.map +1 -1
  5. package/dist/ColorField/ColorFieldInput.cjs +10 -2
  6. package/dist/ColorField/ColorFieldInput.cjs.map +1 -1
  7. package/dist/ColorField/ColorFieldInput.js +10 -2
  8. package/dist/ColorField/ColorFieldInput.js.map +1 -1
  9. package/dist/Combobox/ComboboxInput.cjs +27 -9
  10. package/dist/Combobox/ComboboxInput.cjs.map +1 -1
  11. package/dist/Combobox/ComboboxInput.js +28 -10
  12. package/dist/Combobox/ComboboxInput.js.map +1 -1
  13. package/dist/DateField/DateFieldInput.cjs +4 -1
  14. package/dist/DateField/DateFieldInput.cjs.map +1 -1
  15. package/dist/DateField/DateFieldInput.js +4 -1
  16. package/dist/DateField/DateFieldInput.js.map +1 -1
  17. package/dist/DateField/DateFieldRoot.cjs +1 -0
  18. package/dist/DateField/DateFieldRoot.cjs.map +1 -1
  19. package/dist/DateField/DateFieldRoot.js +1 -0
  20. package/dist/DateField/DateFieldRoot.js.map +1 -1
  21. package/dist/DatePicker/DatePickerRoot.cjs +15 -1
  22. package/dist/DatePicker/DatePickerRoot.cjs.map +1 -1
  23. package/dist/DatePicker/DatePickerRoot.js +15 -1
  24. package/dist/DatePicker/DatePickerRoot.js.map +1 -1
  25. package/dist/DateRangeField/DateRangeFieldInput.cjs +4 -1
  26. package/dist/DateRangeField/DateRangeFieldInput.cjs.map +1 -1
  27. package/dist/DateRangeField/DateRangeFieldInput.js +4 -1
  28. package/dist/DateRangeField/DateRangeFieldInput.js.map +1 -1
  29. package/dist/DateRangeField/DateRangeFieldRoot.cjs +1 -0
  30. package/dist/DateRangeField/DateRangeFieldRoot.cjs.map +1 -1
  31. package/dist/DateRangeField/DateRangeFieldRoot.js +1 -0
  32. package/dist/DateRangeField/DateRangeFieldRoot.js.map +1 -1
  33. package/dist/Dialog/DialogOverlayImpl.cjs +6 -1
  34. package/dist/Dialog/DialogOverlayImpl.cjs.map +1 -1
  35. package/dist/Dialog/DialogOverlayImpl.js +7 -2
  36. package/dist/Dialog/DialogOverlayImpl.js.map +1 -1
  37. package/dist/DropdownMenu/DropdownMenuFilter.cjs +19 -2
  38. package/dist/DropdownMenu/DropdownMenuFilter.cjs.map +1 -1
  39. package/dist/DropdownMenu/DropdownMenuFilter.js +19 -2
  40. package/dist/DropdownMenu/DropdownMenuFilter.js.map +1 -1
  41. package/dist/FocusScope/FocusScope.cjs +2 -0
  42. package/dist/FocusScope/FocusScope.cjs.map +1 -1
  43. package/dist/FocusScope/FocusScope.js +2 -0
  44. package/dist/FocusScope/FocusScope.js.map +1 -1
  45. package/dist/Listbox/ListboxFilter.cjs +29 -10
  46. package/dist/Listbox/ListboxFilter.cjs.map +1 -1
  47. package/dist/Listbox/ListboxFilter.js +30 -11
  48. package/dist/Listbox/ListboxFilter.js.map +1 -1
  49. package/dist/Listbox/ListboxItem.cjs +7 -2
  50. package/dist/Listbox/ListboxItem.cjs.map +1 -1
  51. package/dist/Listbox/ListboxItem.js +7 -2
  52. package/dist/Listbox/ListboxItem.js.map +1 -1
  53. package/dist/Listbox/ListboxRoot.cjs +12 -6
  54. package/dist/Listbox/ListboxRoot.cjs.map +1 -1
  55. package/dist/Listbox/ListboxRoot.js +12 -6
  56. package/dist/Listbox/ListboxRoot.js.map +1 -1
  57. package/dist/Menu/MenuItemImpl.cjs +1 -1
  58. package/dist/Menu/MenuItemImpl.cjs.map +1 -1
  59. package/dist/Menu/MenuItemImpl.js +1 -1
  60. package/dist/Menu/MenuItemImpl.js.map +1 -1
  61. package/dist/NavigationMenu/NavigationMenuContentImpl.cjs +1 -0
  62. package/dist/NavigationMenu/NavigationMenuContentImpl.cjs.map +1 -1
  63. package/dist/NavigationMenu/NavigationMenuContentImpl.js +1 -0
  64. package/dist/NavigationMenu/NavigationMenuContentImpl.js.map +1 -1
  65. package/dist/NavigationMenu/NavigationMenuRoot.cjs +16 -3
  66. package/dist/NavigationMenu/NavigationMenuRoot.cjs.map +1 -1
  67. package/dist/NavigationMenu/NavigationMenuRoot.js +16 -3
  68. package/dist/NavigationMenu/NavigationMenuRoot.js.map +1 -1
  69. package/dist/NumberField/NumberFieldInput.cjs +46 -13
  70. package/dist/NumberField/NumberFieldInput.cjs.map +1 -1
  71. package/dist/NumberField/NumberFieldInput.js +47 -14
  72. package/dist/NumberField/NumberFieldInput.js.map +1 -1
  73. package/dist/PinInput/PinInputInput.cjs +37 -2
  74. package/dist/PinInput/PinInputInput.cjs.map +1 -1
  75. package/dist/PinInput/PinInputInput.js +37 -2
  76. package/dist/PinInput/PinInputInput.js.map +1 -1
  77. package/dist/ScrollArea/ScrollAreaScrollbarX.cjs +3 -0
  78. package/dist/ScrollArea/ScrollAreaScrollbarX.cjs.map +1 -1
  79. package/dist/ScrollArea/ScrollAreaScrollbarX.js +4 -1
  80. package/dist/ScrollArea/ScrollAreaScrollbarX.js.map +1 -1
  81. package/dist/ScrollArea/ScrollAreaScrollbarY.cjs +3 -0
  82. package/dist/ScrollArea/ScrollAreaScrollbarY.cjs.map +1 -1
  83. package/dist/ScrollArea/ScrollAreaScrollbarY.js +4 -1
  84. package/dist/ScrollArea/ScrollAreaScrollbarY.js.map +1 -1
  85. package/dist/Select/SelectContent.cjs +15 -2
  86. package/dist/Select/SelectContent.cjs.map +1 -1
  87. package/dist/Select/SelectContent.js +16 -3
  88. package/dist/Select/SelectContent.js.map +1 -1
  89. package/dist/TagsInput/TagsInputInput.cjs +12 -13
  90. package/dist/TagsInput/TagsInputInput.cjs.map +1 -1
  91. package/dist/TagsInput/TagsInputInput.js +13 -14
  92. package/dist/TagsInput/TagsInputInput.js.map +1 -1
  93. package/dist/TagsInput/TagsInputRoot.cjs +1 -0
  94. package/dist/TagsInput/TagsInputRoot.cjs.map +1 -1
  95. package/dist/TagsInput/TagsInputRoot.js +1 -0
  96. package/dist/TagsInput/TagsInputRoot.js.map +1 -1
  97. package/dist/TimeField/TimeFieldInput.cjs +4 -1
  98. package/dist/TimeField/TimeFieldInput.cjs.map +1 -1
  99. package/dist/TimeField/TimeFieldInput.js +4 -1
  100. package/dist/TimeField/TimeFieldInput.js.map +1 -1
  101. package/dist/TimeField/TimeFieldRoot.cjs +1 -0
  102. package/dist/TimeField/TimeFieldRoot.cjs.map +1 -1
  103. package/dist/TimeField/TimeFieldRoot.js +1 -0
  104. package/dist/TimeField/TimeFieldRoot.js.map +1 -1
  105. package/dist/TimeRangeField/TimeRangeFieldInput.cjs +4 -1
  106. package/dist/TimeRangeField/TimeRangeFieldInput.cjs.map +1 -1
  107. package/dist/TimeRangeField/TimeRangeFieldInput.js +4 -1
  108. package/dist/TimeRangeField/TimeRangeFieldInput.js.map +1 -1
  109. package/dist/TimeRangeField/TimeRangeFieldRoot.cjs +1 -0
  110. package/dist/TimeRangeField/TimeRangeFieldRoot.cjs.map +1 -1
  111. package/dist/TimeRangeField/TimeRangeFieldRoot.js +1 -0
  112. package/dist/TimeRangeField/TimeRangeFieldRoot.js.map +1 -1
  113. package/dist/date/useDateField.cjs +38 -0
  114. package/dist/date/useDateField.cjs.map +1 -1
  115. package/dist/date/useDateField.js +38 -0
  116. package/dist/date/useDateField.js.map +1 -1
  117. package/dist/index.cjs +1 -0
  118. package/dist/index.js +1 -0
  119. package/dist/index2.d.ts.map +1 -1
  120. package/dist/index3.d.cts +24 -16
  121. package/dist/index3.d.cts.map +1 -1
  122. package/dist/index3.d.ts +13 -5
  123. package/dist/index3.d.ts.map +1 -1
  124. package/dist/index4.d.cts +655 -655
  125. package/dist/index4.d.cts.map +1 -1
  126. package/dist/index4.d.ts +684 -684
  127. package/dist/index4.d.ts.map +1 -1
  128. package/dist/internal.cjs +1 -0
  129. package/dist/internal.d.cts +2 -2
  130. package/dist/internal.d.cts.map +1 -1
  131. package/dist/internal.d.ts +2 -2
  132. package/dist/internal.d.ts.map +1 -1
  133. package/dist/internal.js +1 -0
  134. package/dist/shared/useComposing.cjs +30 -0
  135. package/dist/shared/useComposing.cjs.map +1 -0
  136. package/dist/shared/useComposing.js +24 -0
  137. package/dist/shared/useComposing.js.map +1 -0
  138. package/dist/shared.cjs +2 -0
  139. package/dist/shared.d.cts +2 -2
  140. package/dist/shared.d.ts +2 -2
  141. package/dist/shared.js +2 -1
  142. package/package.json +4 -4
  143. package/src/Autocomplete/AutocompleteInput.vue +13 -17
  144. package/src/Calendar/CalendarRoot.vue +1 -1
  145. package/src/ColorField/ColorFieldInput.vue +11 -0
  146. package/src/Combobox/ComboboxInput.vue +37 -7
  147. package/src/DateField/DateFieldInput.vue +6 -0
  148. package/src/DateField/DateFieldRoot.vue +3 -0
  149. package/src/DatePicker/DatePickerRoot.vue +18 -2
  150. package/src/DateRangeField/DateRangeFieldInput.vue +6 -0
  151. package/src/DateRangeField/DateRangeFieldRoot.vue +4 -1
  152. package/src/Dialog/DialogOverlayImpl.vue +1 -0
  153. package/src/DropdownMenu/DropdownMenuFilter.vue +20 -1
  154. package/src/FocusScope/FocusScope.vue +5 -0
  155. package/src/Listbox/ListboxFilter.vue +39 -8
  156. package/src/Listbox/ListboxItem.vue +2 -2
  157. package/src/Listbox/ListboxRoot.vue +17 -4
  158. package/src/Menu/MenuItemImpl.vue +1 -1
  159. package/src/MonthPicker/MonthPickerRoot.vue +1 -1
  160. package/src/NavigationMenu/NavigationMenuContentImpl.vue +3 -0
  161. package/src/NavigationMenu/NavigationMenuRoot.vue +19 -3
  162. package/src/NavigationMenu/__test__/NavigationMenuUnmountOnHideFalse.vue +45 -0
  163. package/src/NumberField/NumberFieldInput.vue +45 -8
  164. package/src/PinInput/PinInputInput.vue +44 -1
  165. package/src/ScrollArea/ScrollAreaScrollbarX.vue +6 -1
  166. package/src/ScrollArea/ScrollAreaScrollbarY.vue +6 -1
  167. package/src/Select/SelectContent.vue +19 -3
  168. package/src/Select/__test__/SelectUnmountCleanup.vue +43 -0
  169. package/src/TagsInput/TagsInputInput.vue +16 -14
  170. package/src/TagsInput/TagsInputRoot.vue +3 -0
  171. package/src/TimeField/TimeFieldInput.vue +6 -0
  172. package/src/TimeField/TimeFieldRoot.vue +3 -0
  173. package/src/TimeRangeField/TimeRangeFieldInput.vue +6 -0
  174. package/src/TimeRangeField/TimeRangeFieldRoot.vue +3 -0
  175. package/src/YearPicker/YearPickerRoot.vue +1 -1
  176. package/src/shared/date/useDateField.ts +75 -1
  177. package/src/shared/index.ts +1 -0
  178. package/src/shared/useComposing.ts +18 -0
@@ -402,6 +402,9 @@ const prevFocusableSegment = computed(() => {
402
402
  const kbd = useKbd()
403
403
 
404
404
  function handleKeydown(e: KeyboardEvent) {
405
+ // Don't navigate between segments mid-composition, arrow keys are used for IME candidate navigation
406
+ if (e.isComposing)
407
+ return
405
408
  if (!isSegmentNavigationKey(e.key))
406
409
  return
407
410
  if (e.key === kbd.ARROW_LEFT)
@@ -75,7 +75,7 @@ export interface YearPickerRootProps extends PrimitiveProps {
75
75
  /** A function that returns the previous page of the year picker. Receives the current placeholder as an argument. */
76
76
  prevPage?: (placeholder: DateValue) => DateValue
77
77
  /** The controlled selected year value of the year picker. Can be bound as `v-model`. */
78
- modelValue?: DateValue | DateValue[] | undefined
78
+ modelValue?: DateValue | DateValue[] | null
79
79
  /** Whether multiple years can be selected */
80
80
  multiple?: boolean
81
81
  /** Number of years to display per page */
@@ -7,9 +7,11 @@ import {
7
7
  } from '@internationalized/date'
8
8
  import { computed } from 'vue'
9
9
  import { getDaysInMonth, toDate } from '@/date'
10
- import { snapValueToStep, useKbd } from '@/shared'
10
+ import { getActiveElement, snapValueToStep, useKbd } from '@/shared'
11
11
  import { isAcceptableSegmentKey, isNumberString, isSegmentNavigationKey } from './segment'
12
12
 
13
+ const DIGIT_REG = /^\d$/
14
+
13
15
  type MinuteSecondIncrementProps = {
14
16
  e: KeyboardEvent
15
17
  part: keyof TimeFields
@@ -877,6 +879,13 @@ export function useDateField(props: UseDateFieldProps) {
877
879
  }
878
880
 
879
881
  function handleSegmentKeydown(e: KeyboardEvent) {
882
+ // A genuine composition keydown sets `isComposing` or reports `key === 'Process'`.
883
+ // Don't use `keyCode === 229` alone: a CJK IME (e.g. Pinyin) keeps that flag set
884
+ // while passing a directly-typed key through, so a real digit (`key === '1'`)
885
+ // would be dropped and leak into the contenteditable as raw text.
886
+ if (e.isComposing || e.key === 'Process')
887
+ return
888
+
880
889
  const disabled = props.disabled.value
881
890
  const readonly = props.readonly.value
882
891
  if (disabled || readonly)
@@ -935,9 +944,74 @@ export function useDateField(props: UseDateFieldProps) {
935
944
  }
936
945
  }
937
946
 
947
+ // Snapshot of the segment's child nodes (and their text) before the IME mutates
948
+ // the contenteditable. Vue renders the value into one text node but may keep
949
+ // empty sibling text nodes around it, so we must preserve EVERY node it owns and
950
+ // restore them verbatim on `compositionend`. Recreating nodes (textContent) would
951
+ // detach Vue's binding and freeze the segment; recreating the element isn't an
952
+ // option either, since the root captures segment elements once via
953
+ // `getSegmentElements` and a fresh node would break navigation.
954
+ let preCompositionNodes: { node: ChildNode, value: string | null }[] | null = null
955
+
956
+ function handleSegmentBeforeInput(e: InputEvent) {
957
+ // The segment's text is driven programmatically (keydown -> segmentValues ->
958
+ // Vue render), so the contenteditable must never be edited directly. Safari
959
+ // dispatches `beforeinput`/`input` BEFORE `keydown` while an IME is active,
960
+ // so a passed-through key (e.g. a digit typed while Pinyin is selected) would
961
+ // leak into the DOM as raw text before `handleSegmentKeydown` can prevent it.
962
+ // Composition input keeps `isComposing` true, so let it through and reconcile
963
+ // on `compositionend`.
964
+ if (!e.isComposing)
965
+ e.preventDefault()
966
+ }
967
+
968
+ function handleSegmentCompositionStart(e: CompositionEvent) {
969
+ const el = e.target as HTMLElement
970
+ preCompositionNodes = Array.from(el.childNodes, node => ({ node, value: node.nodeValue }))
971
+ }
972
+
973
+ function handleSegmentCompositionEnd(e: CompositionEvent) {
974
+ const el = e.target as HTMLElement
975
+ const original = preCompositionNodes
976
+ preCompositionNodes = null
977
+
978
+ // Restore Vue's original nodes (with their text) and drop anything the IME
979
+ // inserted, keeping Vue's bindings intact so later renders still patch the DOM.
980
+ // When no composition was tracked (e.g. synthetic events in tests) leave it be.
981
+ if (original) {
982
+ for (const { node, value } of original)
983
+ node.nodeValue = value
984
+ el.replaceChildren(...original.map(o => o.node))
985
+ }
986
+
987
+ const data = e.data
988
+ if (!data)
989
+ return
990
+
991
+ for (const char of data) {
992
+ if (!DIGIT_REG.test(char))
993
+ continue
994
+
995
+ // Dispatch to the focused segment so subsequent digits follow focus
996
+ // after `focusNext()` advances to the next segment (e.g. "34" → 3 in day, 4 in month).
997
+ const target = getActiveElement()
998
+ if (!(target instanceof HTMLElement))
999
+ break
1000
+
1001
+ target.dispatchEvent(new KeyboardEvent('keydown', {
1002
+ key: char,
1003
+ bubbles: true,
1004
+ cancelable: true,
1005
+ }))
1006
+ }
1007
+ }
1008
+
938
1009
  return {
939
1010
  handleSegmentClick,
940
1011
  handleSegmentKeydown,
1012
+ handleSegmentBeforeInput,
1013
+ handleSegmentCompositionStart,
1014
+ handleSegmentCompositionEnd,
941
1015
  handleSegmentFocusOut,
942
1016
  attributes,
943
1017
  }
@@ -14,6 +14,7 @@ export { renderSlotFragments } from './renderSlotFragments'
14
14
  export { trapFocus } from './trap-focus'
15
15
  export { useArrowNavigation } from './useArrowNavigation'
16
16
  export { useBodyScrollLock } from './useBodyScrollLock'
17
+ export { useComposing } from './useComposing'
17
18
  export { type Formatter, useDateFormatter } from './useDateFormatter'
18
19
  export { useDirection } from './useDirection'
19
20
  export { useEmitAsProps } from './useEmitAsProps'
@@ -0,0 +1,18 @@
1
+ import { nextTick, ref } from 'vue'
2
+
3
+ export function useComposing(onEnd?: (event: CompositionEvent) => void) {
4
+ const isComposing = ref(false)
5
+
6
+ function handleCompositionStart() {
7
+ isComposing.value = true
8
+ }
9
+
10
+ function handleCompositionEnd(event: CompositionEvent) {
11
+ nextTick(() => {
12
+ isComposing.value = false
13
+ onEnd?.(event)
14
+ })
15
+ }
16
+
17
+ return { isComposing, handleCompositionStart, handleCompositionEnd }
18
+ }