@charcoal-ui/react 6.0.0-rc.9 → 6.0.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 (265) hide show
  1. package/dist/_lib/compat.d.ts.map +1 -1
  2. package/dist/_lib/createDivComponent.cjs +0 -1
  3. package/dist/_lib/createDivComponent.cjs.map +1 -1
  4. package/dist/_lib/createDivComponent.d.ts +1 -1
  5. package/dist/_lib/createDivComponent.js.map +1 -1
  6. package/dist/_lib/index.cjs.map +1 -1
  7. package/dist/_lib/index.js.map +1 -1
  8. package/dist/_lib/useClassNames.cjs +0 -1
  9. package/dist/_lib/useClassNames.cjs.map +1 -1
  10. package/dist/_lib/useClassNames.js.map +1 -1
  11. package/dist/_lib/useForwardedRef.cjs +1 -1
  12. package/dist/_lib/useForwardedRef.cjs.map +1 -1
  13. package/dist/_lib/useForwardedRef.js.map +1 -1
  14. package/dist/_lib/useIsomorphicLayoutEffect.cjs +0 -1
  15. package/dist/_lib/useIsomorphicLayoutEffect.cjs.map +1 -1
  16. package/dist/_lib/useIsomorphicLayoutEffect.d.ts +2 -2
  17. package/dist/_lib/useIsomorphicLayoutEffect.d.ts.map +1 -1
  18. package/dist/_lib/useIsomorphicLayoutEffect.js.map +1 -1
  19. package/dist/components/Button/index.d.ts +1 -1
  20. package/dist/components/Button/index.d.ts.map +1 -1
  21. package/dist/components/Button/index2.cjs +1 -1
  22. package/dist/components/Button/index2.cjs.map +1 -1
  23. package/dist/components/Button/index2.js.map +1 -1
  24. package/dist/components/Carousel/CarouselItem.cjs +0 -1
  25. package/dist/components/Carousel/CarouselItem.cjs.map +1 -1
  26. package/dist/components/Carousel/CarouselItem.d.ts.map +1 -1
  27. package/dist/components/Carousel/CarouselItem.js.map +1 -1
  28. package/dist/components/Carousel/carouselStore.cjs.map +1 -1
  29. package/dist/components/Carousel/carouselStore.js.map +1 -1
  30. package/dist/components/Carousel/index.d.ts +1 -1
  31. package/dist/components/Carousel/index.d.ts.map +1 -1
  32. package/dist/components/Carousel/index2.cjs +0 -1
  33. package/dist/components/Carousel/index2.cjs.map +1 -1
  34. package/dist/components/Carousel/index2.js.map +1 -1
  35. package/dist/components/Carousel/intersectionObserver.cjs.map +1 -1
  36. package/dist/components/Carousel/intersectionObserver.js.map +1 -1
  37. package/dist/components/Carousel/resizeObserver.cjs.map +1 -1
  38. package/dist/components/Carousel/resizeObserver.js.map +1 -1
  39. package/dist/components/Carousel/store.cjs.map +1 -1
  40. package/dist/components/Carousel/store.js.map +1 -1
  41. package/dist/components/Carousel/useCarouselScroller.cjs +0 -1
  42. package/dist/components/Carousel/useCarouselScroller.cjs.map +1 -1
  43. package/dist/components/Carousel/useCarouselScroller.js.map +1 -1
  44. package/dist/components/Checkbox/CheckboxInput/index.d.ts.map +1 -1
  45. package/dist/components/Checkbox/CheckboxInput/index2.cjs +0 -1
  46. package/dist/components/Checkbox/CheckboxInput/index2.cjs.map +1 -1
  47. package/dist/components/Checkbox/CheckboxInput/index2.js.map +1 -1
  48. package/dist/components/Checkbox/CheckboxWithLabel.cjs +1 -1
  49. package/dist/components/Checkbox/CheckboxWithLabel.cjs.map +1 -1
  50. package/dist/components/Checkbox/CheckboxWithLabel.d.ts +2 -2
  51. package/dist/components/Checkbox/CheckboxWithLabel.d.ts.map +1 -1
  52. package/dist/components/Checkbox/CheckboxWithLabel.js.map +1 -1
  53. package/dist/components/Checkbox/index.d.ts.map +1 -1
  54. package/dist/components/Checkbox/index2.cjs +0 -1
  55. package/dist/components/Checkbox/index2.cjs.map +1 -1
  56. package/dist/components/Checkbox/index2.js.map +1 -1
  57. package/dist/components/Clickable/index.d.ts +1 -1
  58. package/dist/components/Clickable/index.d.ts.map +1 -1
  59. package/dist/components/Clickable/index2.cjs +1 -1
  60. package/dist/components/Clickable/index2.cjs.map +1 -1
  61. package/dist/components/Clickable/index2.js.map +1 -1
  62. package/dist/components/DropdownSelector/DropdownMenuItem/index2.cjs +0 -1
  63. package/dist/components/DropdownSelector/DropdownMenuItem/index2.cjs.map +1 -1
  64. package/dist/components/DropdownSelector/DropdownMenuItem/index2.js.map +1 -1
  65. package/dist/components/DropdownSelector/DropdownPopover.cjs +0 -1
  66. package/dist/components/DropdownSelector/DropdownPopover.cjs.map +1 -1
  67. package/dist/components/DropdownSelector/DropdownPopover.js.map +1 -1
  68. package/dist/components/DropdownSelector/ListItem/index.d.ts +1 -1
  69. package/dist/components/DropdownSelector/ListItem/index.d.ts.map +1 -1
  70. package/dist/components/DropdownSelector/ListItem/index2.cjs +0 -1
  71. package/dist/components/DropdownSelector/ListItem/index2.cjs.map +1 -1
  72. package/dist/components/DropdownSelector/ListItem/index2.js.map +1 -1
  73. package/dist/components/DropdownSelector/MenuItem/index.cjs +29 -2
  74. package/dist/components/DropdownSelector/MenuItem/index.cjs.map +1 -1
  75. package/dist/components/DropdownSelector/MenuItem/index.d.ts.map +1 -1
  76. package/dist/components/DropdownSelector/MenuItem/index.js +30 -2
  77. package/dist/components/DropdownSelector/MenuItem/index.js.map +1 -1
  78. package/dist/components/DropdownSelector/MenuItem/internals/handleFocusByKeyBoard.cjs.map +1 -1
  79. package/dist/components/DropdownSelector/MenuItem/internals/handleFocusByKeyBoard.js.map +1 -1
  80. package/dist/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.cjs +0 -1
  81. package/dist/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.cjs.map +1 -1
  82. package/dist/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.js.map +1 -1
  83. package/dist/components/DropdownSelector/MenuItemGroup/index2.cjs +0 -1
  84. package/dist/components/DropdownSelector/MenuItemGroup/index2.cjs.map +1 -1
  85. package/dist/components/DropdownSelector/MenuItemGroup/index2.js.map +1 -1
  86. package/dist/components/DropdownSelector/MenuList/MenuListContext.cjs +0 -1
  87. package/dist/components/DropdownSelector/MenuList/MenuListContext.cjs.map +1 -1
  88. package/dist/components/DropdownSelector/MenuList/MenuListContext.js.map +1 -1
  89. package/dist/components/DropdownSelector/MenuList/index2.cjs +0 -1
  90. package/dist/components/DropdownSelector/MenuList/index2.cjs.map +1 -1
  91. package/dist/components/DropdownSelector/MenuList/index2.js.map +1 -1
  92. package/dist/components/DropdownSelector/MenuList/internals/getValuesRecursive.cjs +1 -1
  93. package/dist/components/DropdownSelector/MenuList/internals/getValuesRecursive.cjs.map +1 -1
  94. package/dist/components/DropdownSelector/MenuList/internals/getValuesRecursive.js.map +1 -1
  95. package/dist/components/DropdownSelector/Popover/index.d.ts.map +1 -1
  96. package/dist/components/DropdownSelector/Popover/index2.cjs +18 -1
  97. package/dist/components/DropdownSelector/Popover/index2.cjs.map +1 -1
  98. package/dist/components/DropdownSelector/Popover/index2.js +19 -1
  99. package/dist/components/DropdownSelector/Popover/index2.js.map +1 -1
  100. package/dist/components/DropdownSelector/Popover/usePreventScroll.cjs +0 -1
  101. package/dist/components/DropdownSelector/Popover/usePreventScroll.cjs.map +1 -1
  102. package/dist/components/DropdownSelector/Popover/usePreventScroll.js.map +1 -1
  103. package/dist/components/DropdownSelector/index.d.ts.map +1 -1
  104. package/dist/components/DropdownSelector/index2.cjs +27 -10
  105. package/dist/components/DropdownSelector/index2.cjs.map +1 -1
  106. package/dist/components/DropdownSelector/index2.js +26 -9
  107. package/dist/components/DropdownSelector/index2.js.map +1 -1
  108. package/dist/components/DropdownSelector/utils/findPreviewRecursive.cjs +1 -1
  109. package/dist/components/DropdownSelector/utils/findPreviewRecursive.cjs.map +1 -1
  110. package/dist/components/DropdownSelector/utils/findPreviewRecursive.js.map +1 -1
  111. package/dist/components/FieldLabel/index.d.ts.map +1 -1
  112. package/dist/components/FieldLabel/index2.cjs +1 -1
  113. package/dist/components/FieldLabel/index2.cjs.map +1 -1
  114. package/dist/components/FieldLabel/index2.js.map +1 -1
  115. package/dist/components/HintText/index2.cjs +0 -1
  116. package/dist/components/HintText/index2.cjs.map +1 -1
  117. package/dist/components/HintText/index2.js.map +1 -1
  118. package/dist/components/Icon/index.cjs +1 -1
  119. package/dist/components/Icon/index.cjs.map +1 -1
  120. package/dist/components/Icon/index.d.ts.map +1 -1
  121. package/dist/components/Icon/index.js.map +1 -1
  122. package/dist/components/IconButton/index.d.ts +1 -1
  123. package/dist/components/IconButton/index.d.ts.map +1 -1
  124. package/dist/components/IconButton/index2.cjs +1 -1
  125. package/dist/components/IconButton/index2.cjs.map +1 -1
  126. package/dist/components/IconButton/index2.js.map +1 -1
  127. package/dist/components/LoadingSpinner/index.d.ts.map +1 -1
  128. package/dist/components/LoadingSpinner/index2.cjs +0 -1
  129. package/dist/components/LoadingSpinner/index2.cjs.map +1 -1
  130. package/dist/components/LoadingSpinner/index2.js.map +1 -1
  131. package/dist/components/Modal/Dialog/index2.cjs +1 -1
  132. package/dist/components/Modal/Dialog/index2.cjs.map +1 -1
  133. package/dist/components/Modal/Dialog/index2.js.map +1 -1
  134. package/dist/components/Modal/ModalBackgroundContext.cjs +1 -1
  135. package/dist/components/Modal/ModalBackgroundContext.cjs.map +1 -1
  136. package/dist/components/Modal/ModalBackgroundContext.js.map +1 -1
  137. package/dist/components/Modal/ModalPlumbing.d.ts +3 -3
  138. package/dist/components/Modal/ModalPlumbing2.cjs +0 -1
  139. package/dist/components/Modal/ModalPlumbing2.cjs.map +1 -1
  140. package/dist/components/Modal/ModalPlumbing2.js.map +1 -1
  141. package/dist/components/Modal/index.d.ts.map +1 -1
  142. package/dist/components/Modal/index2.cjs +1 -1
  143. package/dist/components/Modal/index2.cjs.map +1 -1
  144. package/dist/components/Modal/index2.js.map +1 -1
  145. package/dist/components/Modal/useCustomModalOverlay.cjs +1 -1
  146. package/dist/components/Modal/useCustomModalOverlay.cjs.map +1 -1
  147. package/dist/components/Modal/useCustomModalOverlay.js.map +1 -1
  148. package/dist/components/Modal/useTransitionPresence.cjs +1 -3
  149. package/dist/components/Modal/useTransitionPresence.cjs.map +1 -1
  150. package/dist/components/Modal/useTransitionPresence.js +1 -2
  151. package/dist/components/Modal/useTransitionPresence.js.map +1 -1
  152. package/dist/components/MultiSelect/context.cjs +0 -1
  153. package/dist/components/MultiSelect/context.cjs.map +1 -1
  154. package/dist/components/MultiSelect/context.js.map +1 -1
  155. package/dist/components/MultiSelect/index.d.ts +1 -1
  156. package/dist/components/MultiSelect/index.d.ts.map +1 -1
  157. package/dist/components/MultiSelect/index2.cjs +2 -2
  158. package/dist/components/MultiSelect/index2.cjs.map +1 -1
  159. package/dist/components/MultiSelect/index2.js.map +1 -1
  160. package/dist/components/Pagination/PaginationContext.cjs +0 -1
  161. package/dist/components/Pagination/PaginationContext.cjs.map +1 -1
  162. package/dist/components/Pagination/PaginationContext.js.map +1 -1
  163. package/dist/components/Pagination/helper.cjs.map +1 -1
  164. package/dist/components/Pagination/helper.js.map +1 -1
  165. package/dist/components/Pagination/index2.cjs +26 -135
  166. package/dist/components/Pagination/index2.cjs.map +1 -1
  167. package/dist/components/Pagination/index2.js +86 -182
  168. package/dist/components/Pagination/index2.js.map +1 -1
  169. package/dist/components/Radio/RadioGroup/index2.cjs +1 -1
  170. package/dist/components/Radio/RadioGroup/index2.cjs.map +1 -1
  171. package/dist/components/Radio/RadioGroup/index2.js.map +1 -1
  172. package/dist/components/Radio/RadioGroupContext.cjs.map +1 -1
  173. package/dist/components/Radio/RadioGroupContext.js.map +1 -1
  174. package/dist/components/Radio/RadioInput/index.d.ts.map +1 -1
  175. package/dist/components/Radio/RadioInput/index2.cjs +0 -1
  176. package/dist/components/Radio/RadioInput/index2.cjs.map +1 -1
  177. package/dist/components/Radio/RadioInput/index2.js.map +1 -1
  178. package/dist/components/Radio/index.d.ts.map +1 -1
  179. package/dist/components/Radio/index2.cjs +2 -2
  180. package/dist/components/Radio/index2.cjs.map +1 -1
  181. package/dist/components/Radio/index2.js.map +1 -1
  182. package/dist/components/SegmentedControl/RadioGroupContext.cjs +1 -1
  183. package/dist/components/SegmentedControl/RadioGroupContext.cjs.map +1 -1
  184. package/dist/components/SegmentedControl/RadioGroupContext.js.map +1 -1
  185. package/dist/components/SegmentedControl/index.d.ts.map +1 -1
  186. package/dist/components/SegmentedControl/index2.cjs +1 -1
  187. package/dist/components/SegmentedControl/index2.cjs.map +1 -1
  188. package/dist/components/SegmentedControl/index2.js.map +1 -1
  189. package/dist/components/Switch/SwitchInput/index.d.ts.map +1 -1
  190. package/dist/components/Switch/SwitchInput/index2.cjs +0 -1
  191. package/dist/components/Switch/SwitchInput/index2.cjs.map +1 -1
  192. package/dist/components/Switch/SwitchInput/index2.js.map +1 -1
  193. package/dist/components/Switch/SwitchWithLabel.cjs +1 -1
  194. package/dist/components/Switch/SwitchWithLabel.cjs.map +1 -1
  195. package/dist/components/Switch/SwitchWithLabel.d.ts +2 -2
  196. package/dist/components/Switch/SwitchWithLabel.d.ts.map +1 -1
  197. package/dist/components/Switch/SwitchWithLabel.js.map +1 -1
  198. package/dist/components/Switch/index.d.ts +1 -1
  199. package/dist/components/Switch/index.d.ts.map +1 -1
  200. package/dist/components/Switch/index2.cjs +0 -1
  201. package/dist/components/Switch/index2.cjs.map +1 -1
  202. package/dist/components/Switch/index2.js.map +1 -1
  203. package/dist/components/TagItem/index.d.ts +1 -1
  204. package/dist/components/TagItem/index.d.ts.map +1 -1
  205. package/dist/components/TagItem/index2.cjs +1 -1
  206. package/dist/components/TagItem/index2.cjs.map +1 -1
  207. package/dist/components/TagItem/index2.js.map +1 -1
  208. package/dist/components/TextArea/index.d.ts.map +1 -1
  209. package/dist/components/TextArea/index2.cjs +0 -1
  210. package/dist/components/TextArea/index2.cjs.map +1 -1
  211. package/dist/components/TextArea/index2.js.map +1 -1
  212. package/dist/components/TextEllipsis/helper.cjs +2 -1
  213. package/dist/components/TextEllipsis/helper.cjs.map +1 -1
  214. package/dist/components/TextEllipsis/helper.d.ts.map +1 -1
  215. package/dist/components/TextEllipsis/helper.js +1 -1
  216. package/dist/components/TextEllipsis/helper.js.map +1 -1
  217. package/dist/components/TextEllipsis/index2.cjs +14 -98
  218. package/dist/components/TextEllipsis/index2.cjs.map +1 -1
  219. package/dist/components/TextEllipsis/index2.js +14 -93
  220. package/dist/components/TextEllipsis/index2.js.map +1 -1
  221. package/dist/components/TextField/AssistiveText/index.d.ts +1 -1
  222. package/dist/components/TextField/AssistiveText/index2.cjs.map +1 -1
  223. package/dist/components/TextField/AssistiveText/index2.js.map +1 -1
  224. package/dist/components/TextField/index.d.ts +1 -1
  225. package/dist/components/TextField/index.d.ts.map +1 -1
  226. package/dist/components/TextField/index2.cjs +1 -1
  227. package/dist/components/TextField/index2.cjs.map +1 -1
  228. package/dist/components/TextField/index2.js.map +1 -1
  229. package/dist/components/TextField/useFocusWithClick.cjs +0 -1
  230. package/dist/components/TextField/useFocusWithClick.cjs.map +1 -1
  231. package/dist/components/TextField/useFocusWithClick.js.map +1 -1
  232. package/dist/core/CharcoalProvider.cjs +1 -1
  233. package/dist/core/CharcoalProvider.cjs.map +1 -1
  234. package/dist/core/CharcoalProvider.js.map +1 -1
  235. package/dist/core/SSRProvider.cjs +1 -1
  236. package/dist/core/SSRProvider.cjs.map +1 -1
  237. package/dist/core/SSRProvider.js +1 -1
  238. package/dist/core/SSRProvider.js.map +1 -1
  239. package/dist/core/SetThemeScript.cjs +0 -1
  240. package/dist/core/SetThemeScript.cjs.map +1 -1
  241. package/dist/core/SetThemeScript.js.map +1 -1
  242. package/dist/core/themeHelper.cjs +0 -1
  243. package/dist/core/themeHelper.cjs.map +1 -1
  244. package/dist/core/themeHelper.d.ts +2 -2
  245. package/dist/core/themeHelper.d.ts.map +1 -1
  246. package/dist/core/themeHelper.js.map +1 -1
  247. package/dist/index.cjs +22 -23
  248. package/dist/index.css +1000 -1000
  249. package/dist/layered.css +1000 -1000
  250. package/dist/layered.css.map +1 -1
  251. package/package.json +10 -10
  252. package/src/_lib/compat.ts +1 -7
  253. package/src/components/Carousel/index.browser.test.tsx +1 -1
  254. package/src/components/Carousel/intersectionObserver.test.ts +12 -12
  255. package/src/components/Carousel/resizeObserver.test.ts +1 -1
  256. package/src/components/DropdownSelector/MenuItem/index.tsx +40 -2
  257. package/src/components/DropdownSelector/Popover/index.tsx +20 -1
  258. package/src/components/DropdownSelector/index.browser.test.tsx +94 -0
  259. package/src/components/DropdownSelector/index.test.tsx +57 -2
  260. package/src/components/DropdownSelector/index.tsx +37 -12
  261. package/src/components/FieldLabel/index.tsx +1 -2
  262. package/src/components/Icon/index.tsx +2 -1
  263. package/src/components/Modal/__snapshots__/index.css.snap +1 -0
  264. package/src/components/TextEllipsis/TextEllipsis.story.tsx +1 -1
  265. package/src/css.d.ts +1 -0
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Apple Pencil (pointerType: 'pen') での overlay 解除テスト
3
+ *
4
+ * jsdom では検証できないため実ブラウザで実行する:
5
+ *
6
+ * 1. jsdom は inert を実装していない (`'inert' in HTMLElement.prototype` が false)。
7
+ * そのため react-aria の ariaHideOutside は aria-hidden にフォールバックし、
8
+ * 「inert 要素はポインタイベントを受け取らない」という本番の挙動が再現されない。
9
+ * 2. jsdom は PointerEvent を実装しておらず pointerType が落ちる。
10
+ *
11
+ * iOS Safari は非インタラクティブな要素へのペン入力で click を合成しないため、
12
+ * click に依存する react-aria の外側判定では overlay を閉じられない。
13
+ */
14
+ import { fireEvent, render, screen } from '@testing-library/react'
15
+ import { vi } from 'vitest'
16
+ import DropdownSelector from '.'
17
+ import DropdownMenuItem from './DropdownMenuItem'
18
+
19
+ /** Apple Pencil のタップは iOS Safari で click を伴わない */
20
+ const penTap = (element: Element) => {
21
+ const init = { pointerType: 'pen', button: 0, composed: true }
22
+ fireEvent.pointerDown(element, init)
23
+ fireEvent.pointerUp(element, init)
24
+ }
25
+
26
+ const popover = () => document.querySelector('.charcoal-popover')
27
+
28
+ const getUnderlay = () => {
29
+ const underlay = popover()?.previousElementSibling
30
+ if (!(underlay instanceof HTMLElement)) throw new Error('underlay not found')
31
+ return underlay
32
+ }
33
+
34
+ /** ブラウザが実際にヒットテストする要素。inert / pointer-events を反映する */
35
+ const hitTestOutsidePopover = () => {
36
+ const rect = popover()?.getBoundingClientRect()
37
+ if (!rect) throw new Error('popover not found')
38
+ const target = document.elementFromPoint(
39
+ Math.round(rect.left + rect.width / 2),
40
+ Math.round(rect.bottom + 40),
41
+ )
42
+ if (target === null) throw new Error('no element at point')
43
+ return target
44
+ }
45
+
46
+ const renderSelector = (inertWorkaround: boolean) =>
47
+ render(
48
+ <DropdownSelector
49
+ label="Label"
50
+ value="1"
51
+ onChange={vi.fn()}
52
+ inertWorkaround={inertWorkaround}
53
+ >
54
+ <DropdownMenuItem value="1">Option 1</DropdownMenuItem>
55
+ <DropdownMenuItem value="2">Option 2</DropdownMenuItem>
56
+ </DropdownSelector>,
57
+ )
58
+
59
+ describe.each([
60
+ ['inertWorkaround が無効', false],
61
+ ['inertWorkaround が有効', true],
62
+ ])('%s なとき', (_, inertWorkaround) => {
63
+ it('Apple Pencil で overlay の外側をタップすると閉じる', () => {
64
+ renderSelector(inertWorkaround)
65
+
66
+ penTap(screen.getByRole('button'))
67
+ expect(popover()).not.toBeNull()
68
+
69
+ penTap(hitTestOutsidePopover())
70
+
71
+ expect(popover()).toBeNull()
72
+ })
73
+
74
+ // 選択肢のタップは onChange 経由で閉じるのが仕様なので、余白部分を叩く
75
+ it('Apple Pencil で popover の余白をタップしても閉じない', () => {
76
+ renderSelector(inertWorkaround)
77
+
78
+ penTap(screen.getByRole('button'))
79
+ const inside = popover()
80
+ if (inside === null) throw new Error('popover not found')
81
+
82
+ penTap(inside)
83
+
84
+ expect(popover()).not.toBeNull()
85
+ })
86
+ })
87
+
88
+ it('underlay は inertWorkaround が無効なとき inert になる', () => {
89
+ renderSelector(false)
90
+ penTap(screen.getByRole('button'))
91
+
92
+ expect('inert' in HTMLElement.prototype).toBe(true)
93
+ expect(getUnderlay().inert).toBe(true)
94
+ })
@@ -1,8 +1,34 @@
1
- import { render, screen } from '@testing-library/react'
2
- import { vi } from 'vitest'
1
+ import { fireEvent, render, screen } from '@testing-library/react'
2
+ import { beforeAll, vi } from 'vitest'
3
3
  import DropdownSelector from '.'
4
4
  import DropdownMenuItem from './DropdownMenuItem'
5
5
 
6
+ // Apple Pencil (pointerType: 'pen') の解除は index.browser.test.tsx で検証する。
7
+ // jsdom は inert を実装しておらず、react-aria が外側を inert にする本番の挙動を
8
+ // 再現できないため、ここでペンを扱うと通ってしまい実機の退行を見逃す。
9
+
10
+ // jsdom は PointerEvent を実装しておらず pointerType が落ちるため補う
11
+ class PointerEventPolyfill extends MouseEvent {
12
+ readonly pointerType: string
13
+ constructor(type: string, init: PointerEventInit = {}) {
14
+ super(type, init)
15
+ this.pointerType = init.pointerType ?? ''
16
+ }
17
+ }
18
+
19
+ beforeAll(() => {
20
+ vi.stubGlobal('PointerEvent', PointerEventPolyfill)
21
+ })
22
+
23
+ const getUnderlay = () => {
24
+ const popover = document.querySelector('.charcoal-popover')
25
+ const underlay = popover?.previousElementSibling
26
+ if (!(underlay instanceof HTMLElement)) {
27
+ throw new Error('underlay not found')
28
+ }
29
+ return underlay
30
+ }
31
+
6
32
  describe('DropdownSelector', () => {
7
33
  describe('when `value` does not match any child `DropdownMenuItem`', () => {
8
34
  it('keeps the DOM `<select>.value` aligned with props `value` without breaking placeholder display', () => {
@@ -27,4 +53,33 @@ describe('DropdownSelector', () => {
27
53
  expect(button.textContent).toContain('Select an option')
28
54
  })
29
55
  })
56
+
57
+ describe.each([
58
+ ['inertWorkaround が無効', false],
59
+ ['inertWorkaround が有効', true],
60
+ ])('%s なとき', (_, inertWorkaround) => {
61
+ it('マウスで overlay をクリックすると閉じる', () => {
62
+ render(
63
+ <DropdownSelector
64
+ label="Label"
65
+ value="1"
66
+ onChange={vi.fn()}
67
+ inertWorkaround={inertWorkaround}
68
+ >
69
+ <DropdownMenuItem value="1">Option 1</DropdownMenuItem>
70
+ <DropdownMenuItem value="2">Option 2</DropdownMenuItem>
71
+ </DropdownSelector>,
72
+ )
73
+
74
+ fireEvent.click(screen.getByRole('button'))
75
+ expect(document.querySelector('.charcoal-popover')).not.toBeNull()
76
+
77
+ const underlay = getUnderlay()
78
+ fireEvent.pointerDown(underlay, { pointerType: 'mouse', button: 0 })
79
+ fireEvent.pointerUp(underlay, { pointerType: 'mouse', button: 0 })
80
+ fireEvent.click(underlay, { button: 0 })
81
+
82
+ expect(document.querySelector('.charcoal-popover')).toBeNull()
83
+ })
84
+ })
30
85
  })
@@ -42,6 +42,7 @@ export default function DropdownSelector({
42
42
  ...props
43
43
  }: DropdownSelectorProps) {
44
44
  const triggerRef = useRef<HTMLButtonElement>(null)
45
+ const penHandledRef = useRef(false)
45
46
  const [isOpen, setIsOpen] = useState(false)
46
47
  const preview = findPreviewRecursive(props.children, props.value)
47
48
 
@@ -65,6 +66,38 @@ export default function DropdownSelector({
65
66
  [onChange],
66
67
  )
67
68
 
69
+ // Popover が document listener の登録に使うため、識別子を安定させる
70
+ const handleClose = useCallback(() => {
71
+ setIsOpen(false)
72
+ }, [])
73
+
74
+ const handleSelect = useCallback(
75
+ (v: string) => {
76
+ onChange(v)
77
+ setIsOpen(false)
78
+ },
79
+ [onChange],
80
+ )
81
+
82
+ const handleTriggerPointerUp = useCallback(
83
+ (e: React.PointerEvent<HTMLButtonElement>) => {
84
+ if (e.pointerType !== 'pen') return
85
+ if (props.disabled === true) return
86
+ penHandledRef.current = true
87
+ setIsOpen(true)
88
+ },
89
+ [props.disabled],
90
+ )
91
+
92
+ const handleTriggerClick = useCallback(() => {
93
+ if (penHandledRef.current) {
94
+ penHandledRef.current = false
95
+ return
96
+ }
97
+ if (props.disabled === true) return
98
+ setIsOpen(true)
99
+ }, [props.disabled])
100
+
68
101
  const labelId = useId()
69
102
  const describedbyId = useId()
70
103
 
@@ -116,10 +149,8 @@ export default function DropdownSelector({
116
149
  props.assistiveText !== undefined ? describedbyId : undefined
117
150
  }
118
151
  disabled={props.disabled}
119
- onClick={() => {
120
- if (props.disabled === true) return
121
- setIsOpen(true)
122
- }}
152
+ onPointerUp={handleTriggerPointerUp}
153
+ onClick={handleTriggerClick}
123
154
  ref={triggerRef}
124
155
  type="button"
125
156
  data-active={isOpen}
@@ -135,18 +166,12 @@ export default function DropdownSelector({
135
166
  {isOpen && (
136
167
  <DropdownPopover
137
168
  isOpen={isOpen}
138
- onClose={() => setIsOpen(false)}
169
+ onClose={handleClose}
139
170
  triggerRef={triggerRef}
140
171
  value={props.value}
141
172
  inertWorkaround={props.inertWorkaround}
142
173
  >
143
- <MenuList
144
- value={props.value}
145
- onChange={(v) => {
146
- onChange(v)
147
- setIsOpen(false)
148
- }}
149
- >
174
+ <MenuList value={props.value} onChange={handleSelect}>
150
175
  {props.children}
151
176
  </MenuList>
152
177
  </DropdownPopover>
@@ -3,8 +3,7 @@ import { useClassNames } from '../../_lib/useClassNames'
3
3
 
4
4
  import './index.css'
5
5
 
6
- export interface FieldLabelProps
7
- extends React.LabelHTMLAttributes<HTMLLabelElement> {
6
+ export interface FieldLabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {
8
7
  readonly className?: string
9
8
  readonly label: string
10
9
  readonly subLabel?: React.ReactNode
@@ -24,7 +24,8 @@ export interface OwnProps {
24
24
  }
25
25
 
26
26
  export interface IconProps
27
- extends OwnProps,
27
+ extends
28
+ OwnProps,
28
29
  React.PropsWithoutRef<
29
30
  Omit<Props, 'class' | 'unsafe-non-guideline-scale' | 'fixed-size' | 'css'>
30
31
  > {}
@@ -64,3 +64,4 @@
64
64
  font-weight: inherit;
65
65
  font-size: inherit;
66
66
  }
67
+
@@ -1,4 +1,4 @@
1
- import { Meta, StoryObj } from '@storybook/react-webpack5'
1
+ import { Meta, StoryObj } from '@storybook/react-vite'
2
2
  import TextEllipsis from '.'
3
3
 
4
4
  export default {
package/src/css.d.ts ADDED
@@ -0,0 +1 @@
1
+ declare module '*.css'