@charcoal-ui/react 4.0.0-beta.0 → 4.0.0-beta.11

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/README.md +1 -1
  2. package/dist/_lib/compat.d.ts +0 -12
  3. package/dist/_lib/compat.d.ts.map +1 -1
  4. package/dist/_lib/createDivComponent.d.ts +4 -0
  5. package/dist/_lib/createDivComponent.d.ts.map +1 -0
  6. package/dist/_lib/useClassNames.d.ts +2 -2
  7. package/dist/_lib/useClassNames.d.ts.map +1 -1
  8. package/dist/components/Button/index.d.ts +5 -1
  9. package/dist/components/Button/index.d.ts.map +1 -1
  10. package/dist/components/Checkbox/CheckboxInput/index.d.ts +11 -0
  11. package/dist/components/Checkbox/CheckboxInput/index.d.ts.map +1 -0
  12. package/dist/components/Checkbox/CheckboxWithLabel.d.ts +9 -0
  13. package/dist/components/Checkbox/CheckboxWithLabel.d.ts.map +1 -0
  14. package/dist/components/Checkbox/index.d.ts +12 -21
  15. package/dist/components/Checkbox/index.d.ts.map +1 -1
  16. package/dist/components/Clickable/index.d.ts +9 -15
  17. package/dist/components/Clickable/index.d.ts.map +1 -1
  18. package/dist/components/DropdownSelector/Divider/index.d.ts +3 -0
  19. package/dist/components/DropdownSelector/Divider/index.d.ts.map +1 -0
  20. package/dist/components/DropdownSelector/DropdownMenuItem/index.d.ts +8 -0
  21. package/dist/components/DropdownSelector/DropdownMenuItem/index.d.ts.map +1 -0
  22. package/dist/components/DropdownSelector/DropdownPopover.d.ts.map +1 -1
  23. package/dist/components/DropdownSelector/ListItem/index.d.ts +5 -13
  24. package/dist/components/DropdownSelector/ListItem/index.d.ts.map +1 -1
  25. package/dist/components/DropdownSelector/MenuItem/index.d.ts +10 -3
  26. package/dist/components/DropdownSelector/MenuItem/index.d.ts.map +1 -1
  27. package/dist/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.d.ts +1 -1
  28. package/dist/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.d.ts.map +1 -1
  29. package/dist/components/DropdownSelector/MenuItemGroup/index.d.ts +1 -3
  30. package/dist/components/DropdownSelector/MenuItemGroup/index.d.ts.map +1 -1
  31. package/dist/components/DropdownSelector/MenuList/index.d.ts +1 -4
  32. package/dist/components/DropdownSelector/MenuList/index.d.ts.map +1 -1
  33. package/dist/components/DropdownSelector/Popover/index.d.ts +2 -2
  34. package/dist/components/DropdownSelector/Popover/index.d.ts.map +1 -1
  35. package/dist/components/DropdownSelector/index.d.ts +3 -1
  36. package/dist/components/DropdownSelector/index.d.ts.map +1 -1
  37. package/dist/components/FieldLabel/index.d.ts +1 -0
  38. package/dist/components/FieldLabel/index.d.ts.map +1 -1
  39. package/dist/components/IconButton/index.d.ts +7 -5
  40. package/dist/components/IconButton/index.d.ts.map +1 -1
  41. package/dist/components/LoadingSpinner/index.d.ts +1 -0
  42. package/dist/components/LoadingSpinner/index.d.ts.map +1 -1
  43. package/dist/components/Modal/Dialog/index.d.ts +6 -24
  44. package/dist/components/Modal/Dialog/index.d.ts.map +1 -1
  45. package/dist/components/Modal/ModalPlumbing.d.ts +10 -3
  46. package/dist/components/Modal/ModalPlumbing.d.ts.map +1 -1
  47. package/dist/components/Modal/index.d.ts +6 -2
  48. package/dist/components/Modal/index.d.ts.map +1 -1
  49. package/dist/components/Modal/useCustomModalOverlay.d.ts +1 -0
  50. package/dist/components/Modal/useCustomModalOverlay.d.ts.map +1 -1
  51. package/dist/components/Radio/RadioGroup/index.d.ts +20 -0
  52. package/dist/components/Radio/RadioGroup/index.d.ts.map +1 -0
  53. package/dist/components/Radio/RadioGroupContext.d.ts +11 -0
  54. package/dist/components/Radio/RadioGroupContext.d.ts.map +1 -0
  55. package/dist/components/Radio/RadioInput/index.d.ts +10 -0
  56. package/dist/components/Radio/RadioInput/index.d.ts.map +1 -0
  57. package/dist/components/Radio/index.d.ts +1 -14
  58. package/dist/components/Radio/index.d.ts.map +1 -1
  59. package/dist/components/SegmentedControl/index.d.ts +1 -0
  60. package/dist/components/SegmentedControl/index.d.ts.map +1 -1
  61. package/dist/components/Switch/SwitchInput/index.d.ts +9 -0
  62. package/dist/components/Switch/SwitchInput/index.d.ts.map +1 -0
  63. package/dist/components/Switch/SwitchWithLabel.d.ts +9 -0
  64. package/dist/components/Switch/SwitchWithLabel.d.ts.map +1 -0
  65. package/dist/components/Switch/index.d.ts +4 -15
  66. package/dist/components/Switch/index.d.ts.map +1 -1
  67. package/dist/components/TagItem/index.d.ts +10 -15
  68. package/dist/components/TagItem/index.d.ts.map +1 -1
  69. package/dist/components/TextArea/index.d.ts +29 -18
  70. package/dist/components/TextArea/index.d.ts.map +1 -1
  71. package/dist/components/TextField/AssistiveText/index.d.ts +5 -0
  72. package/dist/components/TextField/AssistiveText/index.d.ts.map +1 -0
  73. package/dist/components/TextField/index.d.ts +33 -22
  74. package/dist/components/TextField/index.d.ts.map +1 -1
  75. package/dist/core/CharcoalProvider.d.ts +4 -11
  76. package/dist/core/CharcoalProvider.d.ts.map +1 -1
  77. package/dist/core/SSRProvider.d.ts +3 -1
  78. package/dist/core/SSRProvider.d.ts.map +1 -1
  79. package/dist/index.cjs.js +576 -1255
  80. package/dist/index.cjs.js.map +1 -1
  81. package/dist/index.css +1097 -3
  82. package/dist/index.css.map +1 -1
  83. package/dist/index.d.ts +4 -5
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.esm.js +555 -1231
  86. package/dist/index.esm.js.map +1 -1
  87. package/package.json +25 -23
  88. package/src/README.mdx +68 -0
  89. package/src/SSR.mdx +67 -0
  90. package/src/_lib/compat.ts +0 -11
  91. package/src/_lib/createDivComponent.tsx +11 -0
  92. package/src/_lib/useClassNames.ts +3 -9
  93. package/src/components/Button/__snapshots__/index.story.storyshot +18 -56
  94. package/src/components/Button/index.css +2 -3
  95. package/src/components/Button/index.story.tsx +14 -67
  96. package/src/components/Button/index.tsx +7 -3
  97. package/src/components/Checkbox/CheckboxInput/__snapshots__/index.story.storyshot +77 -0
  98. package/src/components/Checkbox/CheckboxInput/index.css +110 -0
  99. package/src/components/Checkbox/CheckboxInput/index.story.tsx +51 -0
  100. package/src/components/Checkbox/CheckboxInput/index.tsx +47 -0
  101. package/src/components/Checkbox/CheckboxWithLabel.tsx +24 -0
  102. package/src/components/Checkbox/__snapshots__/index.story.storyshot +103 -538
  103. package/src/components/Checkbox/index.css +21 -0
  104. package/src/components/Checkbox/index.story.tsx +49 -79
  105. package/src/components/Checkbox/index.tsx +32 -162
  106. package/src/components/Clickable/__snapshots__/index.story.storyshot +4 -80
  107. package/src/components/Clickable/index.css +41 -0
  108. package/src/components/Clickable/index.story.tsx +2 -2
  109. package/src/components/Clickable/index.tsx +19 -84
  110. package/src/components/DropdownSelector/Divider/index.css +11 -0
  111. package/src/components/DropdownSelector/Divider/index.tsx +5 -0
  112. package/src/components/DropdownSelector/DropdownMenuItem/index.css +20 -0
  113. package/src/components/DropdownSelector/DropdownMenuItem/index.tsx +34 -0
  114. package/src/components/DropdownSelector/DropdownPopover.tsx +16 -9
  115. package/src/components/DropdownSelector/ListItem/__snapshots__/index.story.storyshot +41 -224
  116. package/src/components/DropdownSelector/ListItem/index.css +24 -0
  117. package/src/components/DropdownSelector/ListItem/index.story.tsx +12 -6
  118. package/src/components/DropdownSelector/ListItem/index.tsx +14 -53
  119. package/src/components/DropdownSelector/MenuItem/index.tsx +17 -12
  120. package/src/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.tsx +2 -2
  121. package/src/components/DropdownSelector/MenuItemGroup/index.css +19 -0
  122. package/src/components/DropdownSelector/MenuItemGroup/index.tsx +6 -28
  123. package/src/components/DropdownSelector/MenuList/__snapshots__/index.story.storyshot +162 -416
  124. package/src/components/DropdownSelector/MenuList/index.css +4 -0
  125. package/src/components/DropdownSelector/MenuList/index.story.tsx +1 -1
  126. package/src/components/DropdownSelector/MenuList/index.tsx +4 -12
  127. package/src/components/DropdownSelector/Popover/__snapshots__/index.story.storyshot +5 -5
  128. package/src/components/DropdownSelector/Popover/index.css +11 -0
  129. package/src/components/DropdownSelector/Popover/index.story.tsx +1 -1
  130. package/src/components/DropdownSelector/Popover/index.tsx +7 -17
  131. package/src/components/DropdownSelector/__snapshots__/index.story.storyshot +468 -2494
  132. package/src/components/DropdownSelector/index.css +84 -0
  133. package/src/components/DropdownSelector/index.story.tsx +2 -6
  134. package/src/components/DropdownSelector/index.tsx +61 -137
  135. package/src/components/FieldLabel/index.css +35 -0
  136. package/src/components/FieldLabel/index.tsx +15 -105
  137. package/src/components/Icon/__snapshots__/index.story.storyshot +1 -1
  138. package/src/components/Icon/index.story.tsx +1 -1
  139. package/src/components/IconButton/__snapshots__/index.story.storyshot +19 -297
  140. package/src/components/IconButton/index.css +118 -0
  141. package/src/components/IconButton/index.story.tsx +17 -40
  142. package/src/components/IconButton/index.tsx +41 -118
  143. package/src/components/LoadingSpinner/__snapshots__/LoadingSpinnerIcon.story.storyshot +2 -17
  144. package/src/components/LoadingSpinner/__snapshots__/index.story.storyshot +80 -30
  145. package/src/components/LoadingSpinner/index.css +42 -0
  146. package/src/components/LoadingSpinner/index.story.tsx +19 -8
  147. package/src/components/LoadingSpinner/index.tsx +26 -52
  148. package/src/components/Modal/Dialog/index.css +44 -0
  149. package/src/components/Modal/Dialog/index.tsx +14 -57
  150. package/src/components/Modal/ModalPlumbing.css +40 -0
  151. package/src/components/Modal/ModalPlumbing.tsx +13 -61
  152. package/src/components/Modal/__snapshots__/index.story.storyshot +281 -2221
  153. package/src/components/Modal/index.css +36 -0
  154. package/src/components/Modal/index.story.tsx +26 -13
  155. package/src/components/Modal/index.tsx +42 -78
  156. package/src/components/Modal/useCustomModalOverlay.tsx +19 -4
  157. package/src/components/Radio/RadioGroup/index.css +5 -0
  158. package/src/components/Radio/RadioGroup/index.tsx +80 -0
  159. package/src/components/Radio/RadioGroupContext.ts +23 -0
  160. package/src/components/Radio/RadioInput/index.css +82 -0
  161. package/src/components/Radio/RadioInput/index.tsx +41 -0
  162. package/src/components/Radio/__snapshots__/index.story.storyshot +111 -855
  163. package/src/components/Radio/index.css +18 -0
  164. package/src/components/Radio/index.story.tsx +47 -40
  165. package/src/components/Radio/index.test.tsx +18 -26
  166. package/src/components/Radio/index.tsx +16 -208
  167. package/src/components/SegmentedControl/__snapshots__/index.story.storyshot +32 -262
  168. package/src/components/SegmentedControl/index.css +50 -0
  169. package/src/components/SegmentedControl/index.story.tsx +1 -1
  170. package/src/components/SegmentedControl/index.tsx +20 -89
  171. package/src/components/Switch/SwitchInput/index.css +82 -0
  172. package/src/components/Switch/SwitchInput/index.tsx +40 -0
  173. package/src/components/Switch/SwitchWithLabel.tsx +24 -0
  174. package/src/components/Switch/__snapshots__/index.story.storyshot +35 -539
  175. package/src/components/Switch/index.css +23 -0
  176. package/src/components/Switch/index.story.tsx +16 -19
  177. package/src/components/Switch/index.tsx +43 -140
  178. package/src/components/TagItem/__snapshots__/index.story.storyshot +212 -1063
  179. package/src/components/TagItem/index.css +140 -0
  180. package/src/components/TagItem/index.story.tsx +45 -162
  181. package/src/components/TagItem/index.tsx +72 -220
  182. package/src/components/TextArea/TextArea.story.tsx +63 -25
  183. package/src/components/TextArea/__snapshots__/TextArea.story.storyshot +615 -1055
  184. package/src/components/TextArea/index.css +78 -0
  185. package/src/components/TextArea/index.tsx +83 -174
  186. package/src/components/TextField/AssistiveText/index.css +10 -0
  187. package/src/components/TextField/AssistiveText/index.tsx +6 -0
  188. package/src/components/TextField/TextField.story.tsx +85 -76
  189. package/src/components/TextField/__snapshots__/TextField.story.storyshot +632 -1710
  190. package/src/components/TextField/index.css +87 -0
  191. package/src/components/TextField/index.tsx +92 -211
  192. package/src/core/CharcoalProvider.tsx +5 -29
  193. package/src/core/SSRProvider.tsx +12 -1
  194. package/src/index.ts +7 -19
  195. package/src/type.d.ts +3 -8
  196. package/dist/components/Button/index.story.d.ts +0 -24
  197. package/dist/components/Button/index.story.d.ts.map +0 -1
  198. package/dist/components/Checkbox/index.story.d.ts +0 -8
  199. package/dist/components/Checkbox/index.story.d.ts.map +0 -1
  200. package/dist/components/Clickable/index.story.d.ts +0 -6
  201. package/dist/components/Clickable/index.story.d.ts.map +0 -1
  202. package/dist/components/DropdownSelector/Divider.d.ts +0 -7
  203. package/dist/components/DropdownSelector/Divider.d.ts.map +0 -1
  204. package/dist/components/DropdownSelector/DropdownMenuItem.d.ts +0 -7
  205. package/dist/components/DropdownSelector/DropdownMenuItem.d.ts.map +0 -1
  206. package/dist/components/DropdownSelector/ListItem/index.story.d.ts +0 -9
  207. package/dist/components/DropdownSelector/ListItem/index.story.d.ts.map +0 -1
  208. package/dist/components/DropdownSelector/MenuList/index.story.d.ts +0 -8
  209. package/dist/components/DropdownSelector/MenuList/index.story.d.ts.map +0 -1
  210. package/dist/components/DropdownSelector/Popover/index.story.d.ts +0 -5
  211. package/dist/components/DropdownSelector/Popover/index.story.d.ts.map +0 -1
  212. package/dist/components/DropdownSelector/index.story.d.ts +0 -19
  213. package/dist/components/DropdownSelector/index.story.d.ts.map +0 -1
  214. package/dist/components/Icon/index.story.d.ts +0 -6
  215. package/dist/components/Icon/index.story.d.ts.map +0 -1
  216. package/dist/components/IconButton/index.story.d.ts +0 -9
  217. package/dist/components/IconButton/index.story.d.ts.map +0 -1
  218. package/dist/components/LoadingSpinner/LoadingSpinnerIcon.story.d.ts +0 -8
  219. package/dist/components/LoadingSpinner/LoadingSpinnerIcon.story.d.ts.map +0 -1
  220. package/dist/components/LoadingSpinner/index.story.d.ts +0 -6
  221. package/dist/components/LoadingSpinner/index.story.d.ts.map +0 -1
  222. package/dist/components/Modal/__stories__/InternalScrollStory.d.ts +0 -4
  223. package/dist/components/Modal/__stories__/InternalScrollStory.d.ts.map +0 -1
  224. package/dist/components/Modal/index.story.d.ts +0 -21
  225. package/dist/components/Modal/index.story.d.ts.map +0 -1
  226. package/dist/components/MultiSelect/context.d.ts +0 -14
  227. package/dist/components/MultiSelect/context.d.ts.map +0 -1
  228. package/dist/components/MultiSelect/index.d.ts +0 -36
  229. package/dist/components/MultiSelect/index.d.ts.map +0 -1
  230. package/dist/components/MultiSelect/index.story.d.ts +0 -82
  231. package/dist/components/MultiSelect/index.story.d.ts.map +0 -1
  232. package/dist/components/MultiSelect/index.test.d.ts +0 -2
  233. package/dist/components/MultiSelect/index.test.d.ts.map +0 -1
  234. package/dist/components/Radio/index.story.d.ts +0 -26
  235. package/dist/components/Radio/index.story.d.ts.map +0 -1
  236. package/dist/components/Radio/index.test.d.ts +0 -2
  237. package/dist/components/Radio/index.test.d.ts.map +0 -1
  238. package/dist/components/SegmentedControl/index.story.d.ts +0 -7
  239. package/dist/components/SegmentedControl/index.story.d.ts.map +0 -1
  240. package/dist/components/Switch/index.story.d.ts +0 -9
  241. package/dist/components/Switch/index.story.d.ts.map +0 -1
  242. package/dist/components/TagItem/index.story.d.ts +0 -16
  243. package/dist/components/TagItem/index.story.d.ts.map +0 -1
  244. package/dist/components/TextArea/TextArea.story.d.ts +0 -9
  245. package/dist/components/TextArea/TextArea.story.d.ts.map +0 -1
  246. package/dist/components/TextField/TextField.story.d.ts +0 -22
  247. package/dist/components/TextField/TextField.story.d.ts.map +0 -1
  248. package/dist/components/a11y.test.d.ts +0 -2
  249. package/dist/components/a11y.test.d.ts.map +0 -1
  250. package/dist/core/ComponentAbstraction.d.ts +0 -24
  251. package/dist/core/ComponentAbstraction.d.ts.map +0 -1
  252. package/dist/styled.d.ts +0 -95
  253. package/dist/styled.d.ts.map +0 -1
  254. package/src/components/DropdownSelector/Divider.tsx +0 -16
  255. package/src/components/DropdownSelector/DropdownMenuItem.tsx +0 -43
  256. package/src/components/LoadingSpinner/LoadingSpinnerIcon.story.tsx +0 -13
  257. package/src/components/Modal/__stories__/InternalScrollStory.tsx +0 -75
  258. package/src/components/MultiSelect/__snapshots__/index.story.storyshot +0 -1066
  259. package/src/components/MultiSelect/context.ts +0 -23
  260. package/src/components/MultiSelect/index.story.tsx +0 -216
  261. package/src/components/MultiSelect/index.test.tsx +0 -263
  262. package/src/components/MultiSelect/index.tsx +0 -281
  263. package/src/components/a11y.test.tsx +0 -99
  264. package/src/core/ComponentAbstraction.tsx +0 -48
  265. package/src/styled.ts +0 -3
@@ -0,0 +1,78 @@
1
+ .charcoal-text-area-root {
2
+ display: grid;
3
+ grid-template-columns: 1fr;
4
+ grid-gap: 4px;
5
+ }
6
+
7
+ .charcoal-text-area-root[aria-disabled='true'] {
8
+ opacity: 0.32;
9
+ }
10
+
11
+ .charcoal-text-area-container {
12
+ position: relative;
13
+ overflow: hidden;
14
+
15
+ color: var(--charcoal-text2);
16
+ background-color: var(--charcoal-surface3);
17
+ border-radius: 4px;
18
+ transition: 0.2s background-color, 0.2s box-shadow;
19
+ height: calc(22px * var(--charcoal-text-area-rows) + 18px);
20
+ }
21
+
22
+ .charcoal-text-area-container[aria-invalid='true'] {
23
+ box-shadow: 0 0 0 4px rgba(255, 43, 0, 0.32);
24
+ }
25
+
26
+ .charcoal-text-area-container:focus-within {
27
+ outline: none;
28
+ box-shadow: 0 0 0 4px rgba(0, 150, 250, 0.32);
29
+ }
30
+
31
+ .charcoal-text-area-container:not(aria-disabled='true'):hover {
32
+ background-color: var(--charcoal-surface3-hover);
33
+ }
34
+
35
+ .charcoal-text-area-container[aria-invalid='true']:focus-within {
36
+ box-shadow: 0 0 0 4px rgba(255, 43, 0, 0.32);
37
+ }
38
+
39
+ .charcoal-text-area-textarea {
40
+ border: none;
41
+ outline: none;
42
+ resize: none;
43
+ font-family: inherit;
44
+ color: inherit;
45
+ box-sizing: border-box;
46
+
47
+ /* Prevent zooming for iOS Safari */
48
+ transform-origin: top left;
49
+ transform: scale(0.875);
50
+ width: calc(100% / 0.875);
51
+ font-size: calc(14px / 0.875);
52
+ line-height: calc(22px / 0.875);
53
+ padding: calc(9px / 0.875) calc(8px / 0.875);
54
+ height: calc(22px / 0.875 * var(--charcoal-text-area-rows) + 20px);
55
+
56
+ /* Display box-shadow for iOS Safari */
57
+ appearance: none;
58
+
59
+ background: none;
60
+ }
61
+ .charcoal-text-area-textarea[data-no-bottom-padding='true'] {
62
+ padding: calc(9px / 0.875) calc(8px / 0.875) 0;
63
+ height: calc(22px / 0.875 * (var(--charcoal-text-area-rows) - 1) + 9px);
64
+ }
65
+
66
+ .charcoal-text-area-textarea::placeholder {
67
+ color: var(--charcoal-text3);
68
+ }
69
+
70
+ .charcoal-text-area-counter {
71
+ position: absolute;
72
+ bottom: 9px;
73
+ right: 8px;
74
+
75
+ line-height: 22px;
76
+ font-size: 14px;
77
+ color: var(--charcoal-text3);
78
+ }
@@ -1,70 +1,58 @@
1
- import { useTextField } from '@react-aria/textfield'
1
+ import './index.css'
2
+
2
3
  import { useVisuallyHidden } from '@react-aria/visually-hidden'
3
4
  import { forwardRef, useCallback, useEffect, useRef, useState } from 'react'
4
- import styled, { css } from 'styled-components'
5
- import { FieldLabelProps } from '../FieldLabel'
5
+ import FieldLabel from '../FieldLabel'
6
6
  import { countCodePointsInString, mergeRefs } from '../../_lib'
7
- import { ReactAreaUseTextFieldCompat } from '../../_lib/compat'
8
- import { AssistiveText, TextFieldLabel } from '../TextField'
9
7
  import { useFocusWithClick } from '../TextField/useFocusWithClick'
10
- import { mergeProps } from '@react-aria/utils'
11
-
12
- type DOMProps = Omit<
13
- React.TextareaHTMLAttributes<HTMLTextAreaElement>,
14
- // react-ariaのhookは、onChangeが`(v: string) => void`想定
15
- | 'onChange'
16
- // ReactAreaUseTextFieldCompatに書いてあるような事情で、ここにあるイベントハンドラの型をゆるめる
17
- | keyof ReactAreaUseTextFieldCompat
18
- >
19
-
20
- export interface TextAreaProps
21
- extends Pick<FieldLabelProps, 'label' | 'requiredText' | 'subLabel'>,
22
- DOMProps,
23
- ReactAreaUseTextFieldCompat {
24
- readonly autoHeight?: boolean
25
- readonly rows?: number
26
-
27
- // <input> 要素は number とか string[] もありうるが、今はこれしか想定してない
28
- readonly defaultValue?: string
29
- readonly value?: string
30
- readonly onChange?: (value: string) => void
31
-
32
- // react-ariaの型定義のせいでHTMLTextAreaElementにできない
33
- readonly onKeyDown?: (event: React.KeyboardEvent<Element>) => void
34
- readonly onFocus?: (event: React.FocusEvent<Element>) => void
35
- readonly onBlur?: (event: React.FocusEvent<Element>) => void
36
-
37
- readonly showCount?: boolean
38
- readonly showLabel?: boolean
39
- readonly assistiveText?: string
40
- readonly invalid?: boolean
41
- }
8
+ import { useId } from '@react-aria/utils'
9
+ import { AssistiveText } from '../TextField/AssistiveText'
10
+ import { useClassNames } from '../../_lib/useClassNames'
11
+
12
+ export type TextAreaProps = {
13
+ value?: string
14
+ onChange?: (value: string) => void
15
+
16
+ showCount?: boolean
17
+ showLabel?: boolean
18
+ assistiveText?: string
19
+ invalid?: boolean
20
+
21
+ label?: string
22
+ requiredText?: string
23
+ disabled?: boolean
24
+ subLabel?: React.ReactNode
25
+ autoHeight?: boolean
26
+
27
+ getCount?: (value: string) => number
28
+ } & Omit<React.ComponentPropsWithoutRef<'textarea'>, 'onChange'>
42
29
 
43
30
  const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
44
- function TextAreaInner({ onChange, ...props }, forwardRef) {
45
- const {
31
+ function TextAreaInner(
32
+ {
33
+ onChange,
46
34
  className,
35
+ value,
47
36
  showCount = false,
48
37
  showLabel = false,
49
- label,
38
+ label = '',
50
39
  requiredText,
51
40
  subLabel,
52
41
  disabled = false,
53
42
  required,
54
- invalid = false,
55
43
  assistiveText,
56
44
  maxLength,
57
45
  autoHeight = false,
58
46
  rows: initialRows = 4,
59
- ...restProps
60
- } = props
61
-
47
+ invalid,
48
+ getCount = countCodePointsInString,
49
+ ...props
50
+ },
51
+ forwardRef
52
+ ) {
62
53
  const { visuallyHiddenProps } = useVisuallyHidden()
63
54
  const textareaRef = useRef<HTMLTextAreaElement>(null)
64
- const ariaRef = useRef<HTMLTextAreaElement>(null)
65
- const [count, setCount] = useState(
66
- countCodePointsInString(props.value ?? '')
67
- )
55
+ const [count, setCount] = useState(getCount(value ?? ''))
68
56
  const [rows, setRows] = useState(initialRows)
69
57
 
70
58
  const syncHeight = useCallback(
@@ -75,10 +63,11 @@ const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
75
63
  [initialRows]
76
64
  )
77
65
 
78
- const nonControlled = props.value === undefined
66
+ const nonControlled = value === undefined
79
67
  const handleChange = useCallback(
80
- (value: string) => {
81
- const count = countCodePointsInString(value)
68
+ (e: React.ChangeEvent<HTMLTextAreaElement>) => {
69
+ const value = e.target.value
70
+ const count = getCount(value)
82
71
  if (maxLength !== undefined && count > maxLength) {
83
72
  return
84
73
  }
@@ -90,31 +79,12 @@ const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
90
79
  }
91
80
  onChange?.(value)
92
81
  },
93
- [autoHeight, maxLength, nonControlled, onChange, syncHeight]
82
+ [autoHeight, getCount, maxLength, nonControlled, onChange, syncHeight]
94
83
  )
95
84
 
96
85
  useEffect(() => {
97
- setCount(countCodePointsInString(props.value ?? ''))
98
- }, [props.value])
99
-
100
- const {
101
- inputProps: ariaInputProps,
102
- labelProps,
103
- descriptionProps,
104
- errorMessageProps,
105
- } = useTextField(
106
- {
107
- inputElementType: 'textarea',
108
- isDisabled: disabled,
109
- isRequired: required,
110
- validationState: invalid ? 'invalid' : 'valid',
111
- description: !invalid && assistiveText,
112
- errorMessage: invalid && assistiveText,
113
- onChange: handleChange,
114
- ...props,
115
- },
116
- ariaRef
117
- )
86
+ setCount(getCount(value ?? ''))
87
+ }, [getCount, value])
118
88
 
119
89
  useEffect(() => {
120
90
  if (autoHeight && textareaRef.current !== null) {
@@ -124,127 +94,66 @@ const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
124
94
 
125
95
  const containerRef = useRef(null)
126
96
 
127
- useFocusWithClick(containerRef, ariaRef)
97
+ useFocusWithClick(containerRef, textareaRef)
98
+
99
+ const textAreaId = useId(props.id)
100
+ const describedbyId = useId()
101
+ const labelledbyId = useId()
102
+
103
+ const classNames = useClassNames('charcoal-text-area-root', className)
128
104
 
129
- const inputProps = mergeProps(restProps, ariaInputProps)
105
+ const showAssistiveText =
106
+ assistiveText != null && assistiveText.length !== 0
130
107
 
131
108
  return (
132
- <TextFieldRoot className={className} isDisabled={disabled}>
133
- <TextFieldLabel
109
+ <div className={classNames} aria-disabled={disabled}>
110
+ <FieldLabel
111
+ htmlFor={textAreaId}
112
+ id={labelledbyId}
134
113
  label={label}
135
- requiredText={requiredText}
136
114
  required={required}
115
+ requiredText={requiredText}
137
116
  subLabel={subLabel}
138
- {...labelProps}
139
117
  {...(!showLabel ? visuallyHiddenProps : {})}
140
118
  />
141
- <StyledTextareaContainer
142
- ref={containerRef}
143
- invalid={invalid}
144
- rows={showCount ? rows + 1 : rows}
119
+ <div
120
+ className="charcoal-text-area-container"
145
121
  aria-disabled={disabled === true ? 'true' : undefined}
122
+ aria-invalid={invalid === true}
123
+ ref={containerRef}
124
+ style={{
125
+ '--charcoal-text-area-rows': `${showCount ? rows + 1 : rows}`,
126
+ }}
146
127
  >
147
- <StyledTextarea
148
- ref={mergeRefs(textareaRef, forwardRef, ariaRef)}
128
+ <textarea
129
+ className="charcoal-text-area-textarea"
130
+ aria-describedby={showAssistiveText ? describedbyId : undefined}
131
+ aria-invalid={invalid}
132
+ aria-labelledby={labelledbyId}
133
+ id={textAreaId}
134
+ maxLength={maxLength}
135
+ data-no-bottom-padding={showCount}
136
+ onChange={handleChange}
137
+ ref={mergeRefs(forwardRef, textareaRef)}
149
138
  rows={rows}
150
- noBottomPadding={showCount}
151
- {...inputProps}
139
+ value={value}
140
+ disabled={disabled}
141
+ {...props}
152
142
  />
153
143
  {showCount && (
154
- <MultiLineCounter>
144
+ <span className="charcoal-text-area-counter">
155
145
  {maxLength !== undefined ? `${count}/${maxLength}` : count}
156
- </MultiLineCounter>
146
+ </span>
157
147
  )}
158
- </StyledTextareaContainer>
159
- {assistiveText != null && assistiveText.length !== 0 && (
160
- <AssistiveText
161
- invalid={invalid}
162
- {...(invalid ? errorMessageProps : descriptionProps)}
163
- >
148
+ </div>
149
+ {showAssistiveText && (
150
+ <AssistiveText data-invalid={invalid === true} id={describedbyId}>
164
151
  {assistiveText}
165
152
  </AssistiveText>
166
153
  )}
167
- </TextFieldRoot>
154
+ </div>
168
155
  )
169
156
  }
170
157
  )
171
158
 
172
159
  export default TextArea
173
-
174
- const TextFieldRoot = styled.div<{ isDisabled: boolean }>`
175
- display: flex;
176
- flex-direction: column;
177
-
178
- ${(p) => p.isDisabled && { opacity: p.theme.elementEffect.disabled.opacity }}
179
- `
180
-
181
- const StyledTextareaContainer = styled.div<{ rows: number; invalid: boolean }>`
182
- position: relative;
183
- overflow: hidden;
184
-
185
- color: var(--charcoal-text2);
186
- background-color: var(--charcoal-surface3);
187
- border-radius: 4px;
188
- transition: 0.2s background-color, 0.2s box-shadow;
189
-
190
- ${({ rows }) => css`
191
- height: calc(22px * ${rows} + 18px);
192
- `};
193
-
194
- :not([aria-disabled]):hover,
195
- [aria-disabled='false']:hover {
196
- background-color: var(--charcoal-surface3-hover);
197
- }
198
- :focus-within {
199
- outline: none;
200
- box-shadow: 0 0 0 4px
201
- ${(p) => (p.invalid ? `rgba(255,43,0,0.32)` : `rgba(0, 150, 250, 0.32);`)};
202
- }
203
-
204
- ${(p) =>
205
- p.invalid &&
206
- css`
207
- box-shadow: 0 0 0 4px rgba(255, 43, 0, 0.32);
208
- `}
209
- `
210
-
211
- const StyledTextarea = styled.textarea<{ noBottomPadding: boolean }>`
212
- border: none;
213
- outline: none;
214
- resize: none;
215
- font-family: inherit;
216
- color: inherit;
217
- box-sizing: border-box;
218
-
219
- /* Prevent zooming for iOS Safari */
220
- transform-origin: top left;
221
- transform: scale(0.875);
222
- width: calc(100% / 0.875);
223
- font-size: calc(14px / 0.875);
224
- line-height: calc(22px / 0.875);
225
- padding: calc(9px / 0.875) calc(8px / 0.875)
226
- ${(p) => (p.noBottomPadding ? 0 : '')};
227
-
228
- ${({ rows = 1, noBottomPadding }) => css`
229
- height: calc(22px / 0.875 * ${rows} + ${noBottomPadding ? 9 : 20}px);
230
- `};
231
-
232
- /* Display box-shadow for iOS Safari */
233
- appearance: none;
234
-
235
- background: none;
236
-
237
- &::placeholder {
238
- color: var(--charcoal-text3);
239
- }
240
- `
241
-
242
- const MultiLineCounter = styled.span`
243
- position: absolute;
244
- bottom: 9px;
245
- right: 8px;
246
-
247
- line-height: 22px;
248
- font-size: 14px;
249
- color: var(--charcoal-text3);
250
- `
@@ -0,0 +1,10 @@
1
+ .charcoal-text-field-assistive-text {
2
+ font-size: 14px;
3
+ line-height: 22px;
4
+ margin: 0;
5
+ color: var(--charcoal-text2);
6
+ }
7
+
8
+ .charcoal-text-field-assistive-text[data-invalid='true'] {
9
+ color: var(--charcoal-assertive);
10
+ }
@@ -0,0 +1,6 @@
1
+ import { createDivComponent } from '../../../_lib/createDivComponent'
2
+ import './index.css'
3
+
4
+ export const AssistiveText = createDivComponent(
5
+ 'charcoal-text-field-assistive-text'
6
+ )
@@ -1,122 +1,131 @@
1
- import styled from 'styled-components'
2
1
  import Clickable from '../Clickable'
3
2
  import TextField from '.'
4
- import { px } from '@charcoal-ui/utils'
5
- import IconButton from '../IconButton'
6
- import { useCallback, useState } from 'react'
3
+ import { useState } from 'react'
7
4
  import { Meta, StoryObj } from '@storybook/react'
8
5
 
9
6
  export default {
10
- title: 'TextField',
7
+ title: 'react/TextField',
11
8
  component: TextField,
12
- argTypes: {},
9
+ parameters: {
10
+ layout: 'centered',
11
+ },
12
+ } as Meta<typeof TextField>
13
+
14
+ export const Default: StoryObj<typeof TextField> = {
13
15
  args: {
14
16
  showLabel: false,
15
17
  assistiveText: '',
16
18
  disabled: false,
17
19
  required: false,
18
20
  invalid: false,
21
+ readOnly: false,
19
22
  label: 'Label',
20
23
  requiredText: '*必須',
21
24
  subLabel: <Clickable>Text Link</Clickable>,
22
25
  placeholder: 'TextField',
23
26
  },
24
- render: function Render(args) {
25
- return (
26
- <Container>
27
- <TextField {...args} />
28
- </Container>
29
- )
27
+ render(args) {
28
+ return <TextField {...args} />
30
29
  },
31
- } as Meta<typeof TextField>
30
+ }
31
+
32
+ export const Label: StoryObj<typeof TextField> = {
33
+ render() {
34
+ return <TextField showLabel label="Label" />
35
+ },
36
+ }
32
37
 
33
- const Container = styled.div`
34
- display: grid;
35
- gap: ${({ theme }) => px(theme.spacing[24])};
36
- `
38
+ export const Placeholder: StoryObj<typeof TextField> = {
39
+ render() {
40
+ return <TextField label="Label" placeholder="Placeholder" />
41
+ },
42
+ }
37
43
 
38
- export const Default = {}
44
+ export const RequiredText: StoryObj<typeof TextField> = {
45
+ render() {
46
+ return <TextField label="Label" showLabel required requiredText="*必須" />
47
+ },
48
+ }
39
49
 
40
- export const Number: StoryObj<typeof TextField> = {
41
- render: function Render(args) {
42
- const [count, setCount] = useState(0)
50
+ export const AssistiveText: StoryObj<typeof TextField> = {
51
+ render() {
52
+ return <TextField label="Label" assistiveText="説明が入ります" />
53
+ },
54
+ }
55
+
56
+ export const SubLabel: StoryObj<typeof TextField> = {
57
+ render() {
43
58
  return (
44
- <Container>
45
- <TextField
46
- {...args}
47
- type="number"
48
- value={count.toString()}
49
- onChange={(value) => setCount(parseInt(value))}
50
- onWheel={(e) => {
51
- e.currentTarget.blur()
52
- e.stopPropagation()
53
- }}
54
- />
55
- </Container>
59
+ <TextField label="Label" subLabel={<Clickable>Text Link</Clickable>} />
56
60
  )
57
61
  },
58
62
  }
59
63
 
60
- export const HasLabel = {
61
- args: {
62
- showLabel: true,
63
- assistiveText: 'Assistive text',
64
- required: true,
64
+ export const ShowCount = {
65
+ render() {
66
+ return <TextField label="Label" showCount maxLength={100} />
65
67
  },
66
68
  }
67
69
 
68
- export const HasCount = {
69
- args: {
70
- showCount: true,
71
- maxLength: 100,
70
+ export const Disabled: StoryObj<typeof TextField> = {
71
+ render() {
72
+ return <TextField label="Label" disabled />
72
73
  },
73
74
  }
74
75
 
75
- export const HasAffix: StoryObj<typeof TextField> = {
76
- args: {
77
- showCount: true,
78
- maxLength: 200,
79
- prefix: '/home/john/',
80
- suffix: '.png',
76
+ export const Invalid: StoryObj<typeof TextField> = {
77
+ render() {
78
+ return <TextField label="Label" invalid assistiveText="エラーメッセージ" />
81
79
  },
82
80
  }
83
81
 
84
- const PrefixIconWrap = styled.div`
85
- display: flex;
86
- align-items: center;
87
- color: ${({ theme }) => theme.color.text3};
88
- `
82
+ export const ReadOnly: StoryObj<typeof TextField> = {
83
+ render() {
84
+ return <TextField label="Label" readOnly value="読み取り専用" />
85
+ },
86
+ }
89
87
 
90
- export const PrefixIcon: StoryObj<typeof TextField> = {
91
- render: function Render(args) {
92
- const [value, setValue] = useState('')
93
- const handleChange = useCallback((value: string) => {
94
- setValue(value)
95
- }, [])
96
- const handleClear = useCallback(() => {
97
- setValue('')
98
- }, [])
88
+ export const Affix: StoryObj<typeof TextField> = {
89
+ render() {
90
+ return <TextField label="Label" prefix="/home/john/" suffix=".png" />
91
+ },
92
+ }
93
+
94
+ export const Prefix: StoryObj<typeof TextField> = {
95
+ render() {
99
96
  return (
100
97
  <TextField
101
- {...args}
102
98
  label="Label"
103
- placeholder="作品を検索"
104
- value={value}
105
- onChange={handleChange}
106
99
  prefix={
107
- <PrefixIconWrap>
100
+ <div
101
+ style={{
102
+ display: 'flex',
103
+ alignItems: 'center',
104
+ color: 'var(--charcoal-text3)',
105
+ }}
106
+ >
108
107
  <pixiv-icon name="16/Search" />
109
- </PrefixIconWrap>
110
- }
111
- suffix={
112
- <IconButton
113
- variant="Overlay"
114
- icon={'16/Remove'}
115
- size="XS"
116
- onClick={handleClear}
117
- />
108
+ </div>
118
109
  }
119
110
  />
120
111
  )
121
112
  },
122
113
  }
114
+
115
+ export const Number: StoryObj<typeof TextField> = {
116
+ render: function Render(args) {
117
+ const [count, setCount] = useState(0)
118
+ return (
119
+ <TextField
120
+ {...args}
121
+ type="number"
122
+ value={count.toString()}
123
+ onChange={(value) => setCount(parseInt(value))}
124
+ onWheel={(e) => {
125
+ e.currentTarget.blur()
126
+ e.stopPropagation()
127
+ }}
128
+ />
129
+ )
130
+ },
131
+ }