@pickle-ui/react-native 1.0.0-beta.1 → 1.0.0-beta.2

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 (240) hide show
  1. package/README.md +36 -10
  2. package/dist/components/Button.d.ts.map +1 -1
  3. package/dist/components/Button.js +24 -21
  4. package/dist/components/Button.js.map +1 -1
  5. package/dist/components/Flex.d.ts +25 -0
  6. package/dist/components/Flex.d.ts.map +1 -0
  7. package/dist/components/Flex.js +24 -0
  8. package/dist/components/Flex.js.map +1 -0
  9. package/dist/components/Grid.d.ts +36 -0
  10. package/dist/components/Grid.d.ts.map +1 -0
  11. package/dist/components/Grid.js +68 -0
  12. package/dist/components/Grid.js.map +1 -0
  13. package/dist/components/Separator.d.ts +11 -0
  14. package/dist/components/Separator.d.ts.map +1 -0
  15. package/dist/components/Separator.js +12 -0
  16. package/dist/components/Separator.js.map +1 -0
  17. package/dist/components/Spinner.d.ts +14 -0
  18. package/dist/components/Spinner.d.ts.map +1 -0
  19. package/dist/components/Spinner.js +41 -0
  20. package/dist/components/Spinner.js.map +1 -0
  21. package/dist/components/XStack.d.ts +4 -0
  22. package/dist/components/XStack.d.ts.map +1 -0
  23. package/dist/components/XStack.js +6 -0
  24. package/dist/components/XStack.js.map +1 -0
  25. package/dist/components/YStack.d.ts +4 -0
  26. package/dist/components/YStack.d.ts.map +1 -0
  27. package/dist/components/YStack.js +6 -0
  28. package/dist/components/YStack.js.map +1 -0
  29. package/dist/components/_internal/InputFrame.d.ts +13 -0
  30. package/dist/components/_internal/InputFrame.d.ts.map +1 -0
  31. package/dist/components/_internal/InputFrame.js +14 -0
  32. package/dist/components/_internal/InputFrame.js.map +1 -0
  33. package/dist/components/_internal/StoryItem.d.ts +6 -0
  34. package/dist/components/_internal/StoryItem.d.ts.map +1 -0
  35. package/dist/components/_internal/StoryItem.js +9 -0
  36. package/dist/components/_internal/StoryItem.js.map +1 -0
  37. package/dist/components/_internal/layout.d.ts +79 -0
  38. package/dist/components/_internal/layout.d.ts.map +1 -0
  39. package/dist/components/_internal/layout.js +73 -0
  40. package/dist/components/_internal/layout.js.map +1 -0
  41. package/dist/components/_internal/useControllableState.d.ts +7 -0
  42. package/dist/components/_internal/useControllableState.d.ts.map +1 -0
  43. package/dist/components/_internal/useControllableState.js +17 -0
  44. package/dist/components/_internal/useControllableState.js.map +1 -0
  45. package/dist/components/form/Checkbox.d.ts +26 -0
  46. package/dist/components/form/Checkbox.d.ts.map +1 -0
  47. package/dist/components/form/Checkbox.js +41 -0
  48. package/dist/components/form/Checkbox.js.map +1 -0
  49. package/dist/components/form/Form.context.d.ts +34 -0
  50. package/dist/components/form/Form.context.d.ts.map +1 -0
  51. package/dist/components/form/Form.context.js +53 -0
  52. package/dist/components/form/Form.context.js.map +1 -0
  53. package/dist/components/form/Form.d.ts +33 -0
  54. package/dist/components/form/Form.d.ts.map +1 -0
  55. package/dist/components/form/Form.js +36 -0
  56. package/dist/components/form/Form.js.map +1 -0
  57. package/dist/components/form/FormCheckbox.d.ts +7 -0
  58. package/dist/components/form/FormCheckbox.d.ts.map +1 -0
  59. package/dist/components/form/FormCheckbox.js +24 -0
  60. package/dist/components/form/FormCheckbox.js.map +1 -0
  61. package/dist/components/form/FormDescription.d.ts +4 -0
  62. package/dist/components/form/FormDescription.d.ts.map +1 -0
  63. package/dist/components/form/FormDescription.js +7 -0
  64. package/dist/components/form/FormDescription.js.map +1 -0
  65. package/dist/components/form/FormError.d.ts +5 -0
  66. package/dist/components/form/FormError.d.ts.map +1 -0
  67. package/dist/components/form/FormError.js +8 -0
  68. package/dist/components/form/FormError.js.map +1 -0
  69. package/dist/components/form/FormField.d.ts +17 -0
  70. package/dist/components/form/FormField.d.ts.map +1 -0
  71. package/dist/components/form/FormField.js +36 -0
  72. package/dist/components/form/FormField.js.map +1 -0
  73. package/dist/components/form/FormInput.d.ts +10 -0
  74. package/dist/components/form/FormInput.d.ts.map +1 -0
  75. package/dist/components/form/FormInput.js +36 -0
  76. package/dist/components/form/FormInput.js.map +1 -0
  77. package/dist/components/form/FormInputGroup.d.ts +8 -0
  78. package/dist/components/form/FormInputGroup.d.ts.map +1 -0
  79. package/dist/components/form/FormInputGroup.js +18 -0
  80. package/dist/components/form/FormInputGroup.js.map +1 -0
  81. package/dist/components/form/FormLabel.d.ts +4 -0
  82. package/dist/components/form/FormLabel.d.ts.map +1 -0
  83. package/dist/components/form/FormLabel.js +7 -0
  84. package/dist/components/form/FormLabel.js.map +1 -0
  85. package/dist/components/form/FormRadioGroup.d.ts +11 -0
  86. package/dist/components/form/FormRadioGroup.d.ts.map +1 -0
  87. package/dist/components/form/FormRadioGroup.js +24 -0
  88. package/dist/components/form/FormRadioGroup.js.map +1 -0
  89. package/dist/components/form/FormRoot.d.ts +13 -0
  90. package/dist/components/form/FormRoot.d.ts.map +1 -0
  91. package/dist/components/form/FormRoot.js +19 -0
  92. package/dist/components/form/FormRoot.js.map +1 -0
  93. package/dist/components/form/FormTextarea.d.ts +7 -0
  94. package/dist/components/form/FormTextarea.d.ts.map +1 -0
  95. package/dist/components/form/FormTextarea.js +27 -0
  96. package/dist/components/form/FormTextarea.js.map +1 -0
  97. package/dist/components/form/Input.d.ts +17 -0
  98. package/dist/components/form/Input.d.ts.map +1 -0
  99. package/dist/components/form/Input.js +32 -0
  100. package/dist/components/form/Input.js.map +1 -0
  101. package/dist/components/form/InputGroup.context.d.ts +10 -0
  102. package/dist/components/form/InputGroup.context.d.ts.map +1 -0
  103. package/dist/components/form/InputGroup.context.js +8 -0
  104. package/dist/components/form/InputGroup.context.js.map +1 -0
  105. package/dist/components/form/InputGroup.d.ts +31 -0
  106. package/dist/components/form/InputGroup.d.ts.map +1 -0
  107. package/dist/components/form/InputGroup.js +123 -0
  108. package/dist/components/form/InputGroup.js.map +1 -0
  109. package/dist/components/form/RadioGroup.d.ts +29 -0
  110. package/dist/components/form/RadioGroup.d.ts.map +1 -0
  111. package/dist/components/form/RadioGroup.js +42 -0
  112. package/dist/components/form/RadioGroup.js.map +1 -0
  113. package/dist/components/form/Textarea.d.ts +19 -0
  114. package/dist/components/form/Textarea.d.ts.map +1 -0
  115. package/dist/components/form/Textarea.js +26 -0
  116. package/dist/components/form/Textarea.js.map +1 -0
  117. package/dist/entries/checkbox.d.ts +3 -0
  118. package/dist/entries/checkbox.d.ts.map +1 -0
  119. package/dist/entries/checkbox.js +2 -0
  120. package/dist/entries/checkbox.js.map +1 -0
  121. package/dist/entries/flex.d.ts +3 -0
  122. package/dist/entries/flex.d.ts.map +1 -0
  123. package/dist/entries/flex.js +2 -0
  124. package/dist/entries/flex.js.map +1 -0
  125. package/dist/entries/form.d.ts +3 -0
  126. package/dist/entries/form.d.ts.map +1 -0
  127. package/dist/entries/form.js +2 -0
  128. package/dist/entries/form.js.map +1 -0
  129. package/dist/entries/grid.d.ts +3 -0
  130. package/dist/entries/grid.d.ts.map +1 -0
  131. package/dist/entries/grid.js +2 -0
  132. package/dist/entries/grid.js.map +1 -0
  133. package/dist/entries/input-group.d.ts +3 -0
  134. package/dist/entries/input-group.d.ts.map +1 -0
  135. package/dist/entries/input-group.js +2 -0
  136. package/dist/entries/input-group.js.map +1 -0
  137. package/dist/entries/input.d.ts +3 -0
  138. package/dist/entries/input.d.ts.map +1 -0
  139. package/dist/entries/input.js +2 -0
  140. package/dist/entries/input.js.map +1 -0
  141. package/dist/entries/radio-group.d.ts +3 -0
  142. package/dist/entries/radio-group.d.ts.map +1 -0
  143. package/dist/entries/radio-group.js +2 -0
  144. package/dist/entries/radio-group.js.map +1 -0
  145. package/dist/entries/separator.d.ts +3 -0
  146. package/dist/entries/separator.d.ts.map +1 -0
  147. package/dist/entries/separator.js +2 -0
  148. package/dist/entries/separator.js.map +1 -0
  149. package/dist/entries/spinner.d.ts +3 -0
  150. package/dist/entries/spinner.d.ts.map +1 -0
  151. package/dist/entries/spinner.js +2 -0
  152. package/dist/entries/spinner.js.map +1 -0
  153. package/dist/entries/textarea.d.ts +3 -0
  154. package/dist/entries/textarea.d.ts.map +1 -0
  155. package/dist/entries/textarea.js +2 -0
  156. package/dist/entries/textarea.js.map +1 -0
  157. package/dist/entries/x-stack.d.ts +3 -0
  158. package/dist/entries/x-stack.d.ts.map +1 -0
  159. package/dist/entries/x-stack.js +2 -0
  160. package/dist/entries/x-stack.js.map +1 -0
  161. package/dist/entries/y-stack.d.ts +3 -0
  162. package/dist/entries/y-stack.d.ts.map +1 -0
  163. package/dist/entries/y-stack.js +2 -0
  164. package/dist/entries/y-stack.js.map +1 -0
  165. package/dist/index.d.ts +12 -0
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.js +12 -0
  168. package/dist/index.js.map +1 -1
  169. package/package.json +6 -2
  170. package/src/components/Button.tsx +24 -21
  171. package/src/components/Flex.stories.tsx +58 -0
  172. package/src/components/Flex.test.tsx +57 -0
  173. package/src/components/Flex.tsx +52 -0
  174. package/src/components/Grid.stories.tsx +55 -0
  175. package/src/components/Grid.test.tsx +140 -0
  176. package/src/components/Grid.tsx +166 -0
  177. package/src/components/Separator.stories.tsx +39 -0
  178. package/src/components/Separator.test.tsx +25 -0
  179. package/src/components/Separator.tsx +30 -0
  180. package/src/components/Spinner.stories.tsx +35 -0
  181. package/src/components/Spinner.test.tsx +30 -0
  182. package/src/components/Spinner.tsx +75 -0
  183. package/src/components/XStack.stories.tsx +46 -0
  184. package/src/components/XStack.test.tsx +13 -0
  185. package/src/components/XStack.tsx +7 -0
  186. package/src/components/YStack.stories.tsx +46 -0
  187. package/src/components/YStack.test.tsx +13 -0
  188. package/src/components/YStack.tsx +7 -0
  189. package/src/components/_internal/InputFrame.tsx +50 -0
  190. package/src/components/_internal/StoryItem.tsx +24 -0
  191. package/src/components/_internal/layout.ts +103 -0
  192. package/src/components/_internal/useControllableState.ts +25 -0
  193. package/src/components/form/Checkbox.stories.tsx +67 -0
  194. package/src/components/form/Checkbox.test.tsx +88 -0
  195. package/src/components/form/Checkbox.tsx +141 -0
  196. package/src/components/form/Form.context.ts +91 -0
  197. package/src/components/form/Form.stories.tsx +152 -0
  198. package/src/components/form/Form.test.tsx +195 -0
  199. package/src/components/form/Form.tsx +51 -0
  200. package/src/components/form/FormCheckbox.tsx +42 -0
  201. package/src/components/form/FormDescription.tsx +14 -0
  202. package/src/components/form/FormError.tsx +17 -0
  203. package/src/components/form/FormField.tsx +82 -0
  204. package/src/components/form/FormInput.tsx +70 -0
  205. package/src/components/form/FormInputGroup.tsx +30 -0
  206. package/src/components/form/FormLabel.tsx +17 -0
  207. package/src/components/form/FormRadioGroup.tsx +48 -0
  208. package/src/components/form/FormRoot.tsx +41 -0
  209. package/src/components/form/FormTextarea.tsx +56 -0
  210. package/src/components/form/Input.stories.tsx +105 -0
  211. package/src/components/form/Input.test.tsx +76 -0
  212. package/src/components/form/Input.tsx +81 -0
  213. package/src/components/form/InputGroup.context.ts +11 -0
  214. package/src/components/form/InputGroup.stories.tsx +129 -0
  215. package/src/components/form/InputGroup.test.tsx +95 -0
  216. package/src/components/form/InputGroup.tsx +266 -0
  217. package/src/components/form/RadioGroup.stories.tsx +62 -0
  218. package/src/components/form/RadioGroup.test.tsx +98 -0
  219. package/src/components/form/RadioGroup.tsx +151 -0
  220. package/src/components/form/Textarea.stories.tsx +61 -0
  221. package/src/components/form/Textarea.test.tsx +35 -0
  222. package/src/components/form/Textarea.tsx +74 -0
  223. package/src/entries/checkbox.ts +2 -0
  224. package/src/entries/flex.ts +2 -0
  225. package/src/entries/form.ts +13 -0
  226. package/src/entries/grid.ts +2 -0
  227. package/src/entries/input-group.ts +8 -0
  228. package/src/entries/input.ts +2 -0
  229. package/src/entries/radio-group.ts +5 -0
  230. package/src/entries/separator.ts +2 -0
  231. package/src/entries/spinner.ts +2 -0
  232. package/src/entries/textarea.ts +2 -0
  233. package/src/entries/x-stack.ts +2 -0
  234. package/src/entries/y-stack.ts +2 -0
  235. package/src/index.ts +12 -0
  236. package/dist/components/_internal/Spinner.d.ts +0 -9
  237. package/dist/components/_internal/Spinner.d.ts.map +0 -1
  238. package/dist/components/_internal/Spinner.js +0 -31
  239. package/dist/components/_internal/Spinner.js.map +0 -1
  240. package/src/components/_internal/Spinner.tsx +0 -49
@@ -0,0 +1,19 @@
1
+ import { TextInput } from 'react-native';
2
+ export type TextareaProps = Omit<React.ComponentProps<typeof TextInput>, 'multiline'> & {
3
+ /** Class overrides for the inner `TextInput`; `className` styles the control around it. */
4
+ classNames?: {
5
+ textarea?: string;
6
+ };
7
+ /** Dims the field and stops editing, like the web's `disabled`. */
8
+ disabled?: boolean;
9
+ /** Marks the value as invalid, like the web's `aria-invalid`. */
10
+ invalid?: boolean;
11
+ size?: 'lg' | 'md' | 'sm';
12
+ };
13
+ /**
14
+ * A multi-line text field that grows with its content from three lines, like
15
+ * `Textarea` in @pickle-ui/react. Set a `min-h-*` class on
16
+ * `classNames.textarea` to change the minimum.
17
+ */
18
+ export declare function Textarea({ className, classNames, disabled, editable, invalid, onBlur, onFocus, size, ...props }: TextareaProps): import("react").JSX.Element;
19
+ //# sourceMappingURL=Textarea.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../../../src/components/form/Textarea.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAWzC,MAAM,MAAM,aAAa,GAAG,IAAI,CAC9B,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,EACtC,WAAW,CACZ,GAAG;IACF,2FAA2F;IAC3F,UAAU,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,EACvB,SAAS,EACT,UAAU,EACV,QAAgB,EAChB,QAAe,EACf,OAAe,EACf,MAAM,EACN,OAAO,EACP,IAAW,EACX,GAAG,KAAK,EACT,EAAE,aAAa,+BAiCf"}
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { TextInput } from 'react-native';
4
+ import { cn } from '../../lib/cn';
5
+ import { InputFrame } from '../_internal/InputFrame';
6
+ const sizeClasses = {
7
+ lg: 'min-h-18 px-[11px]',
8
+ md: 'min-h-17.5 px-[11px]',
9
+ sm: 'min-h-16 px-[9px]',
10
+ };
11
+ /**
12
+ * A multi-line text field that grows with its content from three lines, like
13
+ * `Textarea` in @pickle-ui/react. Set a `min-h-*` class on
14
+ * `classNames.textarea` to change the minimum.
15
+ */
16
+ export function Textarea({ className, classNames, disabled = false, editable = true, invalid = false, onBlur, onFocus, size = 'md', ...props }) {
17
+ const [focused, setFocused] = useState(false);
18
+ return (_jsx(InputFrame, { className: className, disabled: disabled, focused: focused, invalid: invalid, children: _jsx(TextInput, { accessibilityState: { disabled }, className: cn('text-foreground web:field-sizing-content web:resize-none flex-1 py-2 text-sm outline-none', sizeClasses[size], classNames?.textarea), editable: editable && !disabled, multiline: true, onBlur: (event) => {
19
+ setFocused(false);
20
+ onBlur?.(event);
21
+ }, onFocus: (event) => {
22
+ setFocused(true);
23
+ onFocus?.(event);
24
+ }, placeholderTextColorClassName: "accent-muted-foreground/72", textAlignVertical: "top", ...props }) }));
25
+ }
26
+ //# sourceMappingURL=Textarea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Textarea.js","sourceRoot":"","sources":["../../../src/components/form/Textarea.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,oBAAoB;IACxB,EAAE,EAAE,sBAAsB;IAC1B,EAAE,EAAE,mBAAmB;CACf,CAAC;AAeX;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,EACvB,SAAS,EACT,UAAU,EACV,QAAQ,GAAG,KAAK,EAChB,QAAQ,GAAG,IAAI,EACf,OAAO,GAAG,KAAK,EACf,MAAM,EACN,OAAO,EACP,IAAI,GAAG,IAAI,EACX,GAAG,KAAK,EACM;IACd,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9C,OAAO,CACL,KAAC,UAAU,IACT,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,YAEhB,KAAC,SAAS,IACR,kBAAkB,EAAE,EAAE,QAAQ,EAAE,EAChC,SAAS,EAAE,EAAE,CACX,2FAA2F,EAC3F,WAAW,CAAC,IAAI,CAAC,EACjB,UAAU,EAAE,QAAQ,CACrB,EACD,QAAQ,EAAE,QAAQ,IAAI,CAAC,QAAQ,EAC/B,SAAS,QACT,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;gBAChB,UAAU,CAAC,KAAK,CAAC,CAAC;gBAClB,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC,EACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjB,UAAU,CAAC,IAAI,CAAC,CAAC;gBACjB,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC,EACD,6BAA6B,EAAC,4BAA4B,EAC1D,iBAAiB,EAAC,KAAK,KACnB,KAAK,GACT,GACS,CACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Checkbox } from '../components/form/Checkbox';
2
+ export type { CheckboxProps } from '../components/form/Checkbox';
3
+ //# sourceMappingURL=checkbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../../src/entries/checkbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Checkbox } from '../components/form/Checkbox';
2
+ //# sourceMappingURL=checkbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkbox.js","sourceRoot":"","sources":["../../src/entries/checkbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Flex } from '../components/Flex';
2
+ export type { FlexProps } from '../components/Flex';
3
+ //# sourceMappingURL=flex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flex.d.ts","sourceRoot":"","sources":["../../src/entries/flex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Flex } from '../components/Flex';
2
+ //# sourceMappingURL=flex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flex.js","sourceRoot":"","sources":["../../src/entries/flex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Form } from '../components/form/Form';
2
+ export type { FormCheckboxProps, FormDescriptionProps, FormErrorProps, FormFieldProps, FormInputGroupProps, FormInputProps, FormLabelProps, FormProps, FormRadioGroupProps, FormTextareaProps, } from '../components/form/Form';
3
+ //# sourceMappingURL=form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/entries/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAC/C,YAAY,EACV,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,SAAS,EACT,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Form } from '../components/form/Form';
2
+ //# sourceMappingURL=form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/entries/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Grid } from '../components/Grid';
2
+ export type { GridProps } from '../components/Grid';
3
+ //# sourceMappingURL=grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../src/entries/grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Grid } from '../components/Grid';
2
+ //# sourceMappingURL=grid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.js","sourceRoot":"","sources":["../../src/entries/grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { InputGroup } from '../components/form/InputGroup';
2
+ export type { InputGroupAddonProps, InputGroupButtonProps, InputGroupInputProps, InputGroupProps, InputGroupTextProps, } from '../components/form/InputGroup';
3
+ //# sourceMappingURL=input-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-group.d.ts","sourceRoot":"","sources":["../../src/entries/input-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,eAAe,EACf,mBAAmB,GACpB,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { InputGroup } from '../components/form/InputGroup';
2
+ //# sourceMappingURL=input-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-group.js","sourceRoot":"","sources":["../../src/entries/input-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Input } from '../components/form/Input';
2
+ export type { InputProps } from '../components/form/Input';
3
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/entries/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Input } from '../components/form/Input';
2
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/entries/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { RadioGroup } from '../components/form/RadioGroup';
2
+ export type { RadioGroupItemProps, RadioGroupProps, } from '../components/form/RadioGroup';
3
+ //# sourceMappingURL=radio-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-group.d.ts","sourceRoot":"","sources":["../../src/entries/radio-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,YAAY,EACV,mBAAmB,EACnB,eAAe,GAChB,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { RadioGroup } from '../components/form/RadioGroup';
2
+ //# sourceMappingURL=radio-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-group.js","sourceRoot":"","sources":["../../src/entries/radio-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Separator } from '../components/Separator';
2
+ export type { SeparatorProps } from '../components/Separator';
3
+ //# sourceMappingURL=separator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separator.d.ts","sourceRoot":"","sources":["../../src/entries/separator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Separator } from '../components/Separator';
2
+ //# sourceMappingURL=separator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separator.js","sourceRoot":"","sources":["../../src/entries/separator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Spinner } from '../components/Spinner';
2
+ export type { SpinnerProps } from '../components/Spinner';
3
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/entries/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Spinner } from '../components/Spinner';
2
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/entries/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { Textarea } from '../components/form/Textarea';
2
+ export type { TextareaProps } from '../components/form/Textarea';
3
+ //# sourceMappingURL=textarea.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../src/entries/textarea.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Textarea } from '../components/form/Textarea';
2
+ //# sourceMappingURL=textarea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textarea.js","sourceRoot":"","sources":["../../src/entries/textarea.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { XStack } from '../components/XStack';
2
+ export type { XStackProps } from '../components/XStack';
3
+ //# sourceMappingURL=x-stack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x-stack.d.ts","sourceRoot":"","sources":["../../src/entries/x-stack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { XStack } from '../components/XStack';
2
+ //# sourceMappingURL=x-stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x-stack.js","sourceRoot":"","sources":["../../src/entries/x-stack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { YStack } from '../components/YStack';
2
+ export type { YStackProps } from '../components/YStack';
3
+ //# sourceMappingURL=y-stack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"y-stack.d.ts","sourceRoot":"","sources":["../../src/entries/y-stack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { YStack } from '../components/YStack';
2
+ //# sourceMappingURL=y-stack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"y-stack.js","sourceRoot":"","sources":["../../src/entries/y-stack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,20 @@
1
1
  export * from './entries/badge';
2
2
  export * from './entries/button';
3
3
  export * from './entries/card';
4
+ export * from './entries/checkbox';
4
5
  export * from './entries/cn';
6
+ export * from './entries/flex';
7
+ export * from './entries/form';
8
+ export * from './entries/grid';
9
+ export * from './entries/input';
10
+ export * from './entries/input-group';
11
+ export * from './entries/radio-group';
12
+ export * from './entries/separator';
13
+ export * from './entries/spinner';
5
14
  export * from './entries/text';
15
+ export * from './entries/textarea';
6
16
  export * from './entries/theme';
7
17
  export * from './entries/use-color-token';
18
+ export * from './entries/x-stack';
19
+ export * from './entries/y-stack';
8
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -3,8 +3,20 @@
3
3
  export * from './entries/badge';
4
4
  export * from './entries/button';
5
5
  export * from './entries/card';
6
+ export * from './entries/checkbox';
6
7
  export * from './entries/cn';
8
+ export * from './entries/flex';
9
+ export * from './entries/form';
10
+ export * from './entries/grid';
11
+ export * from './entries/input';
12
+ export * from './entries/input-group';
13
+ export * from './entries/radio-group';
14
+ export * from './entries/separator';
15
+ export * from './entries/spinner';
7
16
  export * from './entries/text';
17
+ export * from './entries/textarea';
8
18
  export * from './entries/theme';
9
19
  export * from './entries/use-color-token';
20
+ export * from './entries/x-stack';
21
+ export * from './entries/y-stack';
10
22
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,yEAAyE;AACzE,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,yEAAyE;AACzE,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pickle-ui/react-native",
3
- "version": "1.0.0-beta.1",
3
+ "version": "1.0.0-beta.2",
4
4
  "type": "module",
5
5
  "description": "React Native components for Expo, styled with Pickle UI's tokens through Uniwind.",
6
6
  "main": "dist/index.js",
@@ -52,6 +52,7 @@
52
52
  "@pickle-ui/tokens": "1.0.0-beta.7"
53
53
  },
54
54
  "devDependencies": {
55
+ "@hookform/resolvers": "^5.4.0",
55
56
  "@react-native/assets-registry": "0.88.0",
56
57
  "@react-native/jest-preset": "^0.88.1",
57
58
  "@storybook/addon-docs": "^10.6.3",
@@ -68,6 +69,7 @@
68
69
  "react": "19.3.0",
69
70
  "react-doctor": "^0.5.6",
70
71
  "react-dom": "19.3.0",
72
+ "react-hook-form": "^7.79.0",
71
73
  "react-native": "0.88.0",
72
74
  "react-native-svg": "^15.16.0",
73
75
  "react-native-web": "^0.21.4",
@@ -76,10 +78,12 @@
76
78
  "test-renderer": "^1.3.1",
77
79
  "typescript": "^6.0.3",
78
80
  "uniwind": "^1.13.0",
79
- "vite": "^8.3.5"
81
+ "vite": "^8.3.5",
82
+ "zod": "4.0.17"
80
83
  },
81
84
  "peerDependencies": {
82
85
  "react": "^19.0.0",
86
+ "react-hook-form": "^7.0.0",
83
87
  "react-native": "*",
84
88
  "tailwindcss": "^4.0.0",
85
89
  "uniwind": "^1.13.0"
@@ -3,10 +3,10 @@ import { Children, isValidElement } from 'react';
3
3
  import { type Insets, Pressable, Text, View } from 'react-native';
4
4
 
5
5
  import { cn } from '../lib/cn';
6
- import { Spinner } from './_internal/Spinner';
6
+ import { Spinner } from './Spinner';
7
7
 
8
8
  // Same variants, sizes and dimensions as `Button` in @pickle-ui/react on a
9
- // phone. Like the web's `pointer-coarse` hit area, `hitSlop` stretches every
9
+ // phone, with its text sizes from `sm` up. Like the web's `pointer-coarse` hit area, `hitSlop` stretches every
10
10
  // size to a 44pt touch target. Paddings leave room for the 1pt border.
11
11
  const buttonVariants = cva(
12
12
  'flex-row items-center justify-center gap-2 rounded-lg border disabled:opacity-64',
@@ -49,17 +49,19 @@ const labelVariants = cva('font-medium', {
49
49
  defaultVariants: { size: 'md', variant: 'default' },
50
50
  variants: {
51
51
  pressed: { false: '', true: '' },
52
+ // The web's sizes from `sm` up, not its larger phone sizes, which only
53
+ // stop iOS Safari zooming into focused fields.
52
54
  size: {
53
- icon: 'text-base',
54
- 'icon-lg': 'text-base',
55
- 'icon-sm': 'text-base',
56
- 'icon-xl': 'text-base',
57
- 'icon-xs': 'text-base',
58
- lg: 'text-base',
59
- md: 'text-base',
60
- sm: 'text-base',
61
- xl: 'text-lg',
62
- xs: 'text-sm',
55
+ icon: 'text-sm',
56
+ 'icon-lg': 'text-sm',
57
+ 'icon-sm': 'text-sm',
58
+ 'icon-xl': 'text-sm',
59
+ 'icon-xs': 'text-sm',
60
+ lg: 'text-sm',
61
+ md: 'text-sm',
62
+ sm: 'text-sm',
63
+ xl: 'text-base',
64
+ xs: 'text-xs',
63
65
  },
64
66
  variant: {
65
67
  default: 'text-primary-foreground',
@@ -73,16 +75,17 @@ const labelVariants = cva('font-medium', {
73
75
  },
74
76
  });
75
77
 
76
- const spinnerVariants = cva('', {
78
+ // Sized and dimmed like the web button's icons, in the label's color.
79
+ const spinnerVariants = cva('size-4 opacity-80', {
77
80
  variants: {
78
81
  variant: {
79
- default: 'border-primary-foreground',
80
- destructive: 'border-destructive-foreground',
81
- 'destructive-outline': 'border-foreground',
82
- ghost: 'border-foreground',
83
- link: 'border-foreground',
84
- outline: 'border-foreground',
85
- secondary: 'border-secondary-foreground',
82
+ default: 'text-primary-foreground',
83
+ destructive: 'text-destructive-foreground',
84
+ 'destructive-outline': 'text-foreground',
85
+ ghost: 'text-foreground',
86
+ link: 'text-foreground',
87
+ outline: 'text-foreground',
88
+ secondary: 'text-secondary-foreground',
86
89
  },
87
90
  },
88
91
  });
@@ -198,7 +201,7 @@ export function Button({
198
201
  )}
199
202
  {loading ? (
200
203
  <View className="absolute">
201
- <Spinner className={spinnerVariants({ variant })} />
204
+ <Spinner aria-hidden className={spinnerVariants({ variant })} />
202
205
  </View>
203
206
  ) : null}
204
207
  </>
@@ -0,0 +1,58 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-native-web-vite';
2
+
3
+ import { Story } from './_internal/Story';
4
+ import { StoryItem as Item } from './_internal/StoryItem';
5
+ import { Flex } from './Flex';
6
+
7
+ const meta = {
8
+ component: Flex,
9
+ parameters: { layout: 'fullscreen' },
10
+ title: 'components/Flex',
11
+ } satisfies Meta<typeof Flex>;
12
+
13
+ export default meta;
14
+ type StoryDefinition = StoryObj<typeof meta>;
15
+
16
+ export const All: StoryDefinition = {
17
+ render: () => (
18
+ <Story.Layout className="max-w-6xl" title="Flex">
19
+ <Story.Section title="Direction and spacing">
20
+ <Flex direction="column" gap={3}>
21
+ <Item className="min-h-16">First</Item>
22
+ <Item className="min-h-16">Second</Item>
23
+ <Item className="min-h-16">Third</Item>
24
+ </Flex>
25
+ </Story.Section>
26
+
27
+ <Story.Section title="Alignment and distribution">
28
+ <Flex
29
+ align="center"
30
+ className="border-border min-h-40 rounded-md border border-dashed p-4"
31
+ gap={4}
32
+ justify="between"
33
+ >
34
+ <Item className="min-h-16 min-w-20">Start</Item>
35
+ <Item className="min-h-16 min-w-20">Center</Item>
36
+ <Item className="min-h-16 min-w-20">End</Item>
37
+ </Flex>
38
+ </Story.Section>
39
+
40
+ <Story.Section title="Wrapping">
41
+ <Flex gap={3} wrap="wrap">
42
+ {['One', 'Two', 'Three', 'Four', 'Five', 'Six'].map((label) => (
43
+ <Item className="min-h-16 min-w-24" key={label}>
44
+ {label}
45
+ </Item>
46
+ ))}
47
+ </Flex>
48
+ </Story.Section>
49
+
50
+ <Story.Section title="Responsive override">
51
+ <Flex className="flex-col md:flex-row" gap={3}>
52
+ <Item className="min-h-16">Column on small screens</Item>
53
+ <Item className="min-h-16">Row from md</Item>
54
+ </Flex>
55
+ </Story.Section>
56
+ </Story.Layout>
57
+ ),
58
+ };
@@ -0,0 +1,57 @@
1
+ import { render, screen } from '@testing-library/react-native';
2
+
3
+ import { Flex } from './Flex';
4
+
5
+ function classesOf(testID: string) {
6
+ return String(screen.getByTestId(testID).props.className).split(' ');
7
+ }
8
+
9
+ describe('Flex', () => {
10
+ it('lays its children out in a row, like the web', async () => {
11
+ await render(<Flex testID="flex" />);
12
+
13
+ expect(classesOf('flex')).toContain('flex-row');
14
+ });
15
+
16
+ it('renders layout props as Tailwind classes', async () => {
17
+ await render(
18
+ <Flex
19
+ align="center"
20
+ direction="column"
21
+ gap={4}
22
+ gapX={2}
23
+ gapY={3}
24
+ justify="between"
25
+ testID="flex"
26
+ wrap="wrap"
27
+ />,
28
+ );
29
+
30
+ expect(classesOf('flex')).toEqual(
31
+ expect.arrayContaining([
32
+ 'flex-col',
33
+ 'flex-wrap',
34
+ 'items-center',
35
+ 'justify-between',
36
+ 'gap-4',
37
+ 'gap-x-2',
38
+ 'gap-y-3',
39
+ ]),
40
+ );
41
+ });
42
+
43
+ it('lets className override the props', async () => {
44
+ await render(
45
+ <Flex
46
+ className="custom-class flex-row"
47
+ direction="column"
48
+ testID="flex"
49
+ />,
50
+ );
51
+
52
+ expect(classesOf('flex')).toEqual(
53
+ expect.arrayContaining(['flex-row', 'custom-class']),
54
+ );
55
+ expect(classesOf('flex')).not.toContain('flex-col');
56
+ });
57
+ });
@@ -0,0 +1,52 @@
1
+ import { View } from 'react-native';
2
+
3
+ import { cn } from '../lib/cn';
4
+ import { getLayoutClasses, type LayoutStyleProps } from './_internal/layout';
5
+
6
+ const directionClasses = {
7
+ column: 'flex-col',
8
+ 'column-reverse': 'flex-col-reverse',
9
+ row: 'flex-row',
10
+ 'row-reverse': 'flex-row-reverse',
11
+ } as const;
12
+
13
+ const wrapClasses = {
14
+ nowrap: 'flex-nowrap',
15
+ wrap: 'flex-wrap',
16
+ 'wrap-reverse': 'flex-wrap-reverse',
17
+ } as const;
18
+
19
+ export type FlexProps = LayoutStyleProps &
20
+ Omit<React.ComponentProps<typeof View>, keyof LayoutStyleProps> & {
21
+ direction?: keyof typeof directionClasses;
22
+ wrap?: keyof typeof wrapClasses;
23
+ };
24
+
25
+ /**
26
+ * A `View` laid out with flexbox props, like `Flex` in @pickle-ui/react. It
27
+ * defaults to a row, as on the web, where React Native's `View` stacks its
28
+ * children in a column.
29
+ */
30
+ export function Flex({
31
+ align,
32
+ className,
33
+ direction = 'row',
34
+ gap,
35
+ gapX,
36
+ gapY,
37
+ justify,
38
+ wrap,
39
+ ...props
40
+ }: FlexProps) {
41
+ return (
42
+ <View
43
+ className={cn(
44
+ getLayoutClasses({ align, gap, gapX, gapY, justify }),
45
+ directionClasses[direction],
46
+ wrap === undefined ? undefined : wrapClasses[wrap],
47
+ className,
48
+ )}
49
+ {...props}
50
+ />
51
+ );
52
+ }