@charcoal-ui/react 6.0.0-rc.8 → 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 (272) 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 +907 -901
  249. package/dist/layered.css +907 -901
  250. package/dist/layered.css.map +1 -1
  251. package/package.json +10 -10
  252. package/src/__tests__/css-shorthand-safety.test.ts +150 -0
  253. package/src/_lib/compat.ts +1 -7
  254. package/src/components/Button/__snapshots__/index.css.snap +8 -3
  255. package/src/components/Button/index.css +8 -3
  256. package/src/components/Carousel/index.browser.test.tsx +1 -1
  257. package/src/components/Carousel/intersectionObserver.test.ts +12 -12
  258. package/src/components/Carousel/resizeObserver.test.ts +1 -1
  259. package/src/components/DropdownSelector/MenuItem/index.tsx +40 -2
  260. package/src/components/DropdownSelector/Popover/index.tsx +20 -1
  261. package/src/components/DropdownSelector/index.browser.test.tsx +94 -0
  262. package/src/components/DropdownSelector/index.test.tsx +57 -2
  263. package/src/components/DropdownSelector/index.tsx +37 -12
  264. package/src/components/FieldLabel/index.tsx +1 -2
  265. package/src/components/Icon/index.tsx +2 -1
  266. package/src/components/LoadingSpinner/__snapshots__/index.css.snap +1 -2
  267. package/src/components/LoadingSpinner/index.css +1 -2
  268. package/src/components/Modal/__snapshots__/index.css.snap +1 -0
  269. package/src/components/Pagination/__snapshots__/index.css.snap +3 -1
  270. package/src/components/Pagination/index.css +3 -1
  271. package/src/components/TextEllipsis/TextEllipsis.story.tsx +1 -1
  272. package/src/css.d.ts +1 -0
@@ -1,6 +1,6 @@
1
1
  .charcoal-button {
2
2
  appearance: none;
3
- background: transparent;
3
+ background-image: none;
4
4
  box-sizing: border-box;
5
5
  padding: 0 24px;
6
6
  border-style: none;
@@ -9,7 +9,9 @@
9
9
  letter-spacing: inherit;
10
10
  word-spacing: inherit;
11
11
  text-decoration: none;
12
- font: inherit;
12
+ font-family: inherit;
13
+ font-style: inherit;
14
+ font-variant: inherit;
13
15
  margin: 0;
14
16
  overflow: visible;
15
17
  text-transform: none;
@@ -25,7 +27,10 @@
25
27
  line-height: 22px;
26
28
  font-weight: bold;
27
29
  color: var(--charcoal-color-text-default);
28
- background-color: var(--charcoal-color-container-secondary-default-a);
30
+ background-color: var(
31
+ --charcoal-color-container-secondary-default-a,
32
+ transparent
33
+ );
29
34
  transition:
30
35
  0.2s color,
31
36
  0.2s background-color,
@@ -8,7 +8,7 @@
8
8
  * document.elementFromPoint のヒットテストで検証する。
9
9
  * (pointer-events / 擬似要素のヒットテストは jsdom では再現できない)
10
10
  */
11
- import { userEvent } from '@vitest/browser/context'
11
+ import { userEvent } from 'vitest/browser'
12
12
  import { render } from '@testing-library/react'
13
13
  import Carousel from '.'
14
14
 
@@ -23,18 +23,18 @@ describe('observeCenter', () => {
23
23
 
24
24
  it('同一 root の el は observer を共有し、中央交差で対象の onEnter だけ呼ぶ', () => {
25
25
  const instances: MockIO[] = []
26
- globalThis.IntersectionObserver = vi.fn(
27
- (cb: IntersectionObserverCallback) => {
28
- const inst: MockIO = {
29
- cb,
30
- observe: vi.fn(),
31
- unobserve: vi.fn(),
32
- disconnect: vi.fn(),
33
- }
34
- instances.push(inst)
35
- return inst
36
- },
37
- ) as unknown as typeof globalThis.IntersectionObserver
26
+ globalThis.IntersectionObserver = vi.fn(function (
27
+ cb: IntersectionObserverCallback,
28
+ ) {
29
+ const inst: MockIO = {
30
+ cb,
31
+ observe: vi.fn(),
32
+ unobserve: vi.fn(),
33
+ disconnect: vi.fn(),
34
+ }
35
+ instances.push(inst)
36
+ return inst
37
+ }) as unknown as typeof globalThis.IntersectionObserver
38
38
 
39
39
  const root = document.createElement('div')
40
40
  const a = document.createElement('div')
@@ -23,7 +23,7 @@ describe('observeResize', () => {
23
23
 
24
24
  it('単一の observer を共有し、対象のサイズ変化で cb を呼ぶ', () => {
25
25
  const instances: MockRO[] = []
26
- globalThis.ResizeObserver = vi.fn((cb: ResizeObserverCallback) => {
26
+ globalThis.ResizeObserver = vi.fn(function (cb: ResizeObserverCallback) {
27
27
  const inst: MockRO = {
28
28
  cb,
29
29
  observe: vi.fn(),
@@ -1,4 +1,4 @@
1
- import { ForwardedRef, forwardRef } from 'react'
1
+ import { ForwardedRef, forwardRef, useCallback, useRef } from 'react'
2
2
  import ListItem, { ListItemProps } from '../ListItem'
3
3
  import { useMenuItemHandleKeyDown } from './internals/useMenuItemHandleKeyDown'
4
4
 
@@ -18,6 +18,42 @@ const MenuItem = forwardRef(function MenuItem<
18
18
  ref: ForwardedRef<HTMLLIElement>,
19
19
  ) {
20
20
  const [handleKeyDown, setContextValue] = useMenuItemHandleKeyDown(value)
21
+ const penHandledRef = useRef(false)
22
+ const pointerStartRef = useRef<{ x: number; y: number } | null>(null)
23
+
24
+ const handlePointerDown = useCallback(
25
+ (e: React.PointerEvent<HTMLLIElement>) => {
26
+ if (e.pointerType === 'pen') {
27
+ pointerStartRef.current = { x: e.clientX, y: e.clientY }
28
+ }
29
+ },
30
+ [],
31
+ )
32
+
33
+ const handlePointerUp = useCallback(
34
+ (e: React.PointerEvent<HTMLLIElement>) => {
35
+ if (e.pointerType !== 'pen' || disabled === true) return
36
+ const start = pointerStartRef.current
37
+ if (!start) return
38
+ const dx = Math.abs(e.clientX - start.x)
39
+ const dy = Math.abs(e.clientY - start.y)
40
+ // タップとドラッグを区別するための許容量
41
+ if (dx > 8 || dy > 8) return
42
+ penHandledRef.current = true
43
+ setContextValue()
44
+ },
45
+ [disabled, setContextValue],
46
+ )
47
+
48
+ const handleClick = useCallback(() => {
49
+ if (penHandledRef.current) {
50
+ penHandledRef.current = false
51
+ return
52
+ }
53
+ if (disabled === true) return
54
+ setContextValue()
55
+ }, [disabled, setContextValue])
56
+
21
57
  return (
22
58
  // @ts-expect-error TODO: fix mismatch between MenuItemProps and ListItemProps
23
59
  <ListItem
@@ -25,7 +61,9 @@ const MenuItem = forwardRef(function MenuItem<
25
61
  ref={ref}
26
62
  data-key={value}
27
63
  onKeyDown={handleKeyDown}
28
- onClick={disabled === true ? undefined : setContextValue}
64
+ onPointerDown={handlePointerDown}
65
+ onPointerUp={handlePointerUp}
66
+ onClick={handleClick}
29
67
  tabIndex={-1}
30
68
  aria-disabled={disabled}
31
69
  role="option"
@@ -1,6 +1,6 @@
1
1
  import './index.css'
2
2
 
3
- import { RefObject, useContext, useRef, ReactNode } from 'react'
3
+ import { RefObject, useContext, useEffect, useRef, ReactNode } from 'react'
4
4
  import { ModalBackgroundContext } from '../../Modal/ModalBackgroundContext'
5
5
  import { usePreventScroll } from './usePreventScroll'
6
6
  import { DismissButton, Overlay } from 'react-aria/Overlay'
@@ -54,6 +54,25 @@ export default function Popover(props: PopoverProps) {
54
54
  const modalBackground = useContext(ModalBackgroundContext)
55
55
  usePreventScroll(modalBackground, props.isOpen)
56
56
 
57
+ // iOS Safari は非インタラクティブな要素へのペン入力で click を合成しないため、
58
+ // click に依存する react-aria の外側判定ではペンで閉じられない。
59
+ // underlay 側では拾えない: react-aria が modal 時に外側を inert にするので
60
+ // underlay 自身がイベントを受け取らなくなる。
61
+ const { isOpen, onClose } = props
62
+ useEffect(() => {
63
+ if (!isOpen) return
64
+ const handlePointerUp = (e: PointerEvent) => {
65
+ if (e.pointerType !== 'pen') return
66
+ const popover = finalPopoverRef.current
67
+ if (popover !== null && e.composedPath().includes(popover)) return
68
+ onClose()
69
+ }
70
+ document.addEventListener('pointerup', handlePointerUp, true)
71
+ return () => {
72
+ document.removeEventListener('pointerup', handlePointerUp, true)
73
+ }
74
+ }, [isOpen, onClose, finalPopoverRef])
75
+
57
76
  if (!props.isOpen) return null
58
77
 
59
78
  return (
@@ -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
  > {}
@@ -33,8 +33,7 @@ to {
33
33
  height: 1em;
34
34
  border-radius: 1em;
35
35
  background-color: currentColor;
36
- animation: charcoal-loading-spinner-icon-scale-out 1s both ease-out;
37
- animation-iteration-count: infinite;
36
+ animation: charcoal-loading-spinner-icon-scale-out 1s infinite both ease-out;
38
37
  }
39
38
 
40
39
  .charcoal-loading-spinner-icon[data-reset-animation] {
@@ -31,8 +31,7 @@
31
31
  height: 1em;
32
32
  border-radius: 1em;
33
33
  background-color: currentColor;
34
- animation: charcoal-loading-spinner-icon-scale-out 1s both ease-out;
35
- animation-iteration-count: infinite;
34
+ animation: charcoal-loading-spinner-icon-scale-out 1s infinite both ease-out;
36
35
 
37
36
  &[data-reset-animation] {
38
37
  animation: none;
@@ -64,3 +64,4 @@
64
64
  font-weight: inherit;
65
65
  font-size: inherit;
66
66
  }
67
+
@@ -23,7 +23,9 @@
23
23
  border-style: none;
24
24
  outline: none;
25
25
  text-decoration: none;
26
- font: inherit;
26
+ font-family: inherit;
27
+ font-style: inherit;
28
+ font-variant: inherit;
27
29
  margin: 0;
28
30
  user-select: none;
29
31
  display: flex;
@@ -22,7 +22,9 @@
22
22
  border-style: none;
23
23
  outline: none;
24
24
  text-decoration: none;
25
- font: inherit;
25
+ font-family: inherit;
26
+ font-style: inherit;
27
+ font-variant: inherit;
26
28
  margin: 0;
27
29
  user-select: none;
28
30
 
@@ -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'