@prototyp/skeletor 1.0.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 (216) hide show
  1. package/.eslintrc.json +19 -0
  2. package/.github/CODEOWNERS +2 -0
  3. package/.gitignore +5 -0
  4. package/README.md +418 -0
  5. package/lib/module/components/Block/Block.js +71 -0
  6. package/lib/module/components/Block/Block.js.map +1 -0
  7. package/lib/module/components/Block/index.js +2 -0
  8. package/lib/module/components/Block/index.js.map +1 -0
  9. package/lib/module/components/InputFocusScrollView/InputFocusScrollView.js +93 -0
  10. package/lib/module/components/InputFocusScrollView/InputFocusScrollView.js.map +1 -0
  11. package/lib/module/components/InputFocusScrollView/index.js +2 -0
  12. package/lib/module/components/InputFocusScrollView/index.js.map +1 -0
  13. package/lib/module/components/Screen/Screen.js +55 -0
  14. package/lib/module/components/Screen/Screen.js.map +1 -0
  15. package/lib/module/components/Screen/index.js +2 -0
  16. package/lib/module/components/Screen/index.js.map +1 -0
  17. package/lib/module/components/SkeletorProvider/SkeletorContext.js +9 -0
  18. package/lib/module/components/SkeletorProvider/SkeletorContext.js.map +1 -0
  19. package/lib/module/components/SkeletorProvider/SkeletorProvider.js +17 -0
  20. package/lib/module/components/SkeletorProvider/SkeletorProvider.js.map +1 -0
  21. package/lib/module/components/SkeletorProvider/index.js +3 -0
  22. package/lib/module/components/SkeletorProvider/index.js.map +1 -0
  23. package/lib/module/components/Text/Text.js +64 -0
  24. package/lib/module/components/Text/Text.js.map +1 -0
  25. package/lib/module/components/Text/index.js +2 -0
  26. package/lib/module/components/Text/index.js.map +1 -0
  27. package/lib/module/components/index.js +6 -0
  28. package/lib/module/components/index.js.map +1 -0
  29. package/lib/module/hooks/index.js +7 -0
  30. package/lib/module/hooks/index.js.map +1 -0
  31. package/lib/module/hooks/useAndroidBackHandler.js +24 -0
  32. package/lib/module/hooks/useAndroidBackHandler.js.map +1 -0
  33. package/lib/module/hooks/useAnimation.js +33 -0
  34. package/lib/module/hooks/useAnimation.js.map +1 -0
  35. package/lib/module/hooks/useAnimationTimeline.js +97 -0
  36. package/lib/module/hooks/useAnimationTimeline.js.map +1 -0
  37. package/lib/module/hooks/useAppState.js +21 -0
  38. package/lib/module/hooks/useAppState.js.map +1 -0
  39. package/lib/module/hooks/useForm.js +159 -0
  40. package/lib/module/hooks/useForm.js.map +1 -0
  41. package/lib/module/hooks/useSkeletor.js +6 -0
  42. package/lib/module/hooks/useSkeletor.js.map +1 -0
  43. package/lib/module/index.js +5 -0
  44. package/lib/module/index.js.map +1 -0
  45. package/lib/module/models/Alignment.js +2 -0
  46. package/lib/module/models/Alignment.js.map +1 -0
  47. package/lib/module/models/Border.js +2 -0
  48. package/lib/module/models/Border.js.map +1 -0
  49. package/lib/module/models/Size.js +2 -0
  50. package/lib/module/models/Size.js.map +1 -0
  51. package/lib/module/models/SkeletorConfig.js +2 -0
  52. package/lib/module/models/SkeletorConfig.js.map +1 -0
  53. package/lib/module/models/Spacing.js +2 -0
  54. package/lib/module/models/Spacing.js.map +1 -0
  55. package/lib/module/models/index.js +6 -0
  56. package/lib/module/models/index.js.map +1 -0
  57. package/lib/module/types/Font.d.js +2 -0
  58. package/lib/module/types/Font.d.js.map +1 -0
  59. package/lib/module/utils/extractAlignmentProperties.js +10 -0
  60. package/lib/module/utils/extractAlignmentProperties.js.map +1 -0
  61. package/lib/module/utils/extractSizeProperties.js +12 -0
  62. package/lib/module/utils/extractSizeProperties.js.map +1 -0
  63. package/lib/module/utils/index.js +3 -0
  64. package/lib/module/utils/index.js.map +1 -0
  65. package/lib/typescript/lib/module/components/Block/Block.d.ts +4 -0
  66. package/lib/typescript/lib/module/components/Block/Block.d.ts.map +1 -0
  67. package/lib/typescript/lib/module/components/Block/index.d.ts +2 -0
  68. package/lib/typescript/lib/module/components/Block/index.d.ts.map +1 -0
  69. package/lib/typescript/lib/module/components/InputFocusScrollView/InputFocusScrollView.d.ts +4 -0
  70. package/lib/typescript/lib/module/components/InputFocusScrollView/InputFocusScrollView.d.ts.map +1 -0
  71. package/lib/typescript/lib/module/components/InputFocusScrollView/index.d.ts +2 -0
  72. package/lib/typescript/lib/module/components/InputFocusScrollView/index.d.ts.map +1 -0
  73. package/lib/typescript/lib/module/components/Screen/Screen.d.ts +5 -0
  74. package/lib/typescript/lib/module/components/Screen/Screen.d.ts.map +1 -0
  75. package/lib/typescript/lib/module/components/Screen/index.d.ts +2 -0
  76. package/lib/typescript/lib/module/components/Screen/index.d.ts.map +1 -0
  77. package/lib/typescript/lib/module/components/SkeletorProvider/SkeletorContext.d.ts +14 -0
  78. package/lib/typescript/lib/module/components/SkeletorProvider/SkeletorContext.d.ts.map +1 -0
  79. package/lib/typescript/lib/module/components/SkeletorProvider/SkeletorProvider.d.ts +8 -0
  80. package/lib/typescript/lib/module/components/SkeletorProvider/SkeletorProvider.d.ts.map +1 -0
  81. package/lib/typescript/lib/module/components/SkeletorProvider/index.d.ts +3 -0
  82. package/lib/typescript/lib/module/components/SkeletorProvider/index.d.ts.map +1 -0
  83. package/lib/typescript/lib/module/components/Text/Text.d.ts +4 -0
  84. package/lib/typescript/lib/module/components/Text/Text.d.ts.map +1 -0
  85. package/lib/typescript/lib/module/components/Text/index.d.ts +2 -0
  86. package/lib/typescript/lib/module/components/Text/index.d.ts.map +1 -0
  87. package/lib/typescript/lib/module/components/index.d.ts +6 -0
  88. package/lib/typescript/lib/module/components/index.d.ts.map +1 -0
  89. package/lib/typescript/lib/module/hooks/index.d.ts +7 -0
  90. package/lib/typescript/lib/module/hooks/index.d.ts.map +1 -0
  91. package/lib/typescript/lib/module/hooks/useAndroidBackHandler.d.ts +2 -0
  92. package/lib/typescript/lib/module/hooks/useAndroidBackHandler.d.ts.map +1 -0
  93. package/lib/typescript/lib/module/hooks/useAnimation.d.ts +9 -0
  94. package/lib/typescript/lib/module/hooks/useAnimation.d.ts.map +1 -0
  95. package/lib/typescript/lib/module/hooks/useAnimationTimeline.d.ts +10 -0
  96. package/lib/typescript/lib/module/hooks/useAnimationTimeline.d.ts.map +1 -0
  97. package/lib/typescript/lib/module/hooks/useAppState.d.ts +2 -0
  98. package/lib/typescript/lib/module/hooks/useAppState.d.ts.map +1 -0
  99. package/lib/typescript/lib/module/hooks/useForm.d.ts +33 -0
  100. package/lib/typescript/lib/module/hooks/useForm.d.ts.map +1 -0
  101. package/lib/typescript/lib/module/hooks/useSkeletor.d.ts +7 -0
  102. package/lib/typescript/lib/module/hooks/useSkeletor.d.ts.map +1 -0
  103. package/lib/typescript/lib/module/index.d.ts +5 -0
  104. package/lib/typescript/lib/module/index.d.ts.map +1 -0
  105. package/lib/typescript/lib/module/models/Alignment.d.ts +2 -0
  106. package/lib/typescript/lib/module/models/Alignment.d.ts.map +1 -0
  107. package/lib/typescript/lib/module/models/Border.d.ts +1 -0
  108. package/lib/typescript/lib/module/models/Border.d.ts.map +1 -0
  109. package/lib/typescript/lib/module/models/Size.d.ts +1 -0
  110. package/lib/typescript/lib/module/models/Size.d.ts.map +1 -0
  111. package/lib/typescript/lib/module/models/SkeletorConfig.d.ts +1 -0
  112. package/lib/typescript/lib/module/models/SkeletorConfig.d.ts.map +1 -0
  113. package/lib/typescript/lib/module/models/Spacing.d.ts +1 -0
  114. package/lib/typescript/lib/module/models/Spacing.d.ts.map +1 -0
  115. package/lib/typescript/lib/module/models/index.d.ts +2 -0
  116. package/lib/typescript/lib/module/models/index.d.ts.map +1 -0
  117. package/lib/typescript/lib/module/types/Font.d.d.ts +1 -0
  118. package/lib/typescript/lib/module/types/Font.d.d.ts.map +1 -0
  119. package/lib/typescript/lib/module/utils/extractAlignmentProperties.d.ts +8 -0
  120. package/lib/typescript/lib/module/utils/extractAlignmentProperties.d.ts.map +1 -0
  121. package/lib/typescript/lib/module/utils/extractSizeProperties.d.ts +10 -0
  122. package/lib/typescript/lib/module/utils/extractSizeProperties.d.ts.map +1 -0
  123. package/lib/typescript/lib/module/utils/index.d.ts +3 -0
  124. package/lib/typescript/lib/module/utils/index.d.ts.map +1 -0
  125. package/lib/typescript/src/components/Block/Block.d.ts +23 -0
  126. package/lib/typescript/src/components/Block/Block.d.ts.map +1 -0
  127. package/lib/typescript/src/components/Block/index.d.ts +2 -0
  128. package/lib/typescript/src/components/Block/index.d.ts.map +1 -0
  129. package/lib/typescript/src/components/InputFocusScrollView/InputFocusScrollView.d.ts +18 -0
  130. package/lib/typescript/src/components/InputFocusScrollView/InputFocusScrollView.d.ts.map +1 -0
  131. package/lib/typescript/src/components/InputFocusScrollView/index.d.ts +2 -0
  132. package/lib/typescript/src/components/InputFocusScrollView/index.d.ts.map +1 -0
  133. package/lib/typescript/src/components/Screen/Screen.d.ts +16 -0
  134. package/lib/typescript/src/components/Screen/Screen.d.ts.map +1 -0
  135. package/lib/typescript/src/components/Screen/index.d.ts +2 -0
  136. package/lib/typescript/src/components/Screen/index.d.ts.map +1 -0
  137. package/lib/typescript/src/components/SkeletorProvider/SkeletorContext.d.ts +5 -0
  138. package/lib/typescript/src/components/SkeletorProvider/SkeletorContext.d.ts.map +1 -0
  139. package/lib/typescript/src/components/SkeletorProvider/SkeletorProvider.d.ts +8 -0
  140. package/lib/typescript/src/components/SkeletorProvider/SkeletorProvider.d.ts.map +1 -0
  141. package/lib/typescript/src/components/SkeletorProvider/index.d.ts +3 -0
  142. package/lib/typescript/src/components/SkeletorProvider/index.d.ts.map +1 -0
  143. package/lib/typescript/src/components/Text/Text.d.ts +21 -0
  144. package/lib/typescript/src/components/Text/Text.d.ts.map +1 -0
  145. package/lib/typescript/src/components/Text/index.d.ts +2 -0
  146. package/lib/typescript/src/components/Text/index.d.ts.map +1 -0
  147. package/lib/typescript/src/components/index.d.ts +6 -0
  148. package/lib/typescript/src/components/index.d.ts.map +1 -0
  149. package/lib/typescript/src/hooks/index.d.ts +7 -0
  150. package/lib/typescript/src/hooks/index.d.ts.map +1 -0
  151. package/lib/typescript/src/hooks/useAndroidBackHandler.d.ts +16 -0
  152. package/lib/typescript/src/hooks/useAndroidBackHandler.d.ts.map +1 -0
  153. package/lib/typescript/src/hooks/useAnimation.d.ts +20 -0
  154. package/lib/typescript/src/hooks/useAnimation.d.ts.map +1 -0
  155. package/lib/typescript/src/hooks/useAnimationTimeline.d.ts +30 -0
  156. package/lib/typescript/src/hooks/useAnimationTimeline.d.ts.map +1 -0
  157. package/lib/typescript/src/hooks/useAppState.d.ts +7 -0
  158. package/lib/typescript/src/hooks/useAppState.d.ts.map +1 -0
  159. package/lib/typescript/src/hooks/useForm.d.ts +52 -0
  160. package/lib/typescript/src/hooks/useForm.d.ts.map +1 -0
  161. package/lib/typescript/src/hooks/useSkeletor.d.ts +3 -0
  162. package/lib/typescript/src/hooks/useSkeletor.d.ts.map +1 -0
  163. package/lib/typescript/src/index.d.ts +5 -0
  164. package/lib/typescript/src/index.d.ts.map +1 -0
  165. package/lib/typescript/src/models/Alignment.d.ts +9 -0
  166. package/lib/typescript/src/models/Alignment.d.ts.map +1 -0
  167. package/lib/typescript/src/models/Border.d.ts +16 -0
  168. package/lib/typescript/src/models/Border.d.ts.map +1 -0
  169. package/lib/typescript/src/models/Size.d.ts +10 -0
  170. package/lib/typescript/src/models/Size.d.ts.map +1 -0
  171. package/lib/typescript/src/models/SkeletorConfig.d.ts +7 -0
  172. package/lib/typescript/src/models/SkeletorConfig.d.ts.map +1 -0
  173. package/lib/typescript/src/models/Spacing.d.ts +21 -0
  174. package/lib/typescript/src/models/Spacing.d.ts.map +1 -0
  175. package/lib/typescript/src/models/index.d.ts +6 -0
  176. package/lib/typescript/src/models/index.d.ts.map +1 -0
  177. package/lib/typescript/src/utils/extractAlignmentProperties.d.ts +3 -0
  178. package/lib/typescript/src/utils/extractAlignmentProperties.d.ts.map +1 -0
  179. package/lib/typescript/src/utils/extractSizeProperties.d.ts +3 -0
  180. package/lib/typescript/src/utils/extractSizeProperties.d.ts.map +1 -0
  181. package/lib/typescript/src/utils/index.d.ts +3 -0
  182. package/lib/typescript/src/utils/index.d.ts.map +1 -0
  183. package/package.json +63 -0
  184. package/prototyp-skeletor-v1.0.0.tgz +0 -0
  185. package/src/components/Block/Block.tsx +106 -0
  186. package/src/components/Block/index.ts +1 -0
  187. package/src/components/InputFocusScrollView/InputFocusScrollView.tsx +120 -0
  188. package/src/components/InputFocusScrollView/index.ts +1 -0
  189. package/src/components/Screen/Screen.tsx +91 -0
  190. package/src/components/Screen/index.ts +1 -0
  191. package/src/components/SkeletorProvider/SkeletorContext.ts +12 -0
  192. package/src/components/SkeletorProvider/SkeletorProvider.tsx +18 -0
  193. package/src/components/SkeletorProvider/index.ts +2 -0
  194. package/src/components/Text/Text.tsx +99 -0
  195. package/src/components/Text/index.ts +1 -0
  196. package/src/components/index.ts +5 -0
  197. package/src/hooks/index.ts +6 -0
  198. package/src/hooks/useAndroidBackHandler.ts +45 -0
  199. package/src/hooks/useAnimation.ts +62 -0
  200. package/src/hooks/useAnimationTimeline.ts +139 -0
  201. package/src/hooks/useAppState.ts +26 -0
  202. package/src/hooks/useForm.ts +190 -0
  203. package/src/hooks/useSkeletor.ts +7 -0
  204. package/src/index.ts +4 -0
  205. package/src/models/Alignment.ts +9 -0
  206. package/src/models/Border.ts +15 -0
  207. package/src/models/Size.ts +9 -0
  208. package/src/models/SkeletorConfig.ts +6 -0
  209. package/src/models/Spacing.ts +20 -0
  210. package/src/models/index.ts +5 -0
  211. package/src/types/Font.d.ts +1 -0
  212. package/src/utils/extractAlignmentProperties.ts +13 -0
  213. package/src/utils/extractSizeProperties.ts +13 -0
  214. package/src/utils/index.ts +2 -0
  215. package/tsconfig.json +16 -0
  216. package/yarn.lock +6080 -0
@@ -0,0 +1,7 @@
1
+ export * from "./useForm";
2
+ export * from "./useAnimation";
3
+ export * from "./useAnimationTimeline";
4
+ export * from "./useAppState";
5
+ export * from "./useSkeletor";
6
+ export * from "./useAndroidBackHandler";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,16 @@
1
+ interface DefaultProps {
2
+ /** Whether the custom handler is enabled or disabled. */
3
+ enabled: boolean;
4
+ }
5
+ interface WithCallback extends DefaultProps {
6
+ /** Callback function to execute on back button press. Will disable default behavior. */
7
+ handlePress: () => void;
8
+ }
9
+ interface WithDisable extends DefaultProps {
10
+ /** Whether or not the default android back button behavior will be blocked */
11
+ disableDefault: boolean;
12
+ }
13
+ export declare type AndroidBackHandlerConfig = WithCallback | WithDisable;
14
+ export declare function useAndroidBackHandler(props: AndroidBackHandlerConfig): void;
15
+ export {};
16
+ //# sourceMappingURL=useAndroidBackHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAndroidBackHandler.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useAndroidBackHandler.ts"],"names":[],"mappings":"AAGA,UAAU,YAAY;IACpB,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAC;CAClB;AACD,UAAU,YAAa,SAAQ,YAAY;IACzC,wFAAwF;IACxF,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,UAAU,WAAY,SAAQ,YAAY;IACxC,8EAA8E;IAC9E,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,oBAAY,wBAAwB,GAAG,YAAY,GAAG,WAAW,CAAC;AAQlE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,wBAAwB,QAmBpE"}
@@ -0,0 +1,20 @@
1
+ import { Animated, ViewStyle } from "react-native";
2
+ /** Any is a hotfix, requires more investigation */
3
+ declare type Animation<Keys extends keyof Partial<ViewStyle>> = Record<Keys, Animated.AnimatedInterpolation<string | number> | any>;
4
+ declare type Definition<Keys extends keyof Partial<ViewStyle>> = Record<Keys, number[] | string[]>;
5
+ interface Configuration {
6
+ /** In miliseconds */
7
+ duration: number;
8
+ /** Loop will disable native driver because it breaks the loop animation (at least it did last time I tested in 2020.) */
9
+ loop?: boolean;
10
+ useNativeDriver?: boolean;
11
+ }
12
+ export interface AnimationSet<Keys extends keyof Partial<ViewStyle>> {
13
+ values: Animated.Value[];
14
+ definitions: Definition<Keys>;
15
+ animations: Animation<Keys>;
16
+ configuration: Configuration;
17
+ }
18
+ export declare function useAnimation<Keys extends keyof Partial<ViewStyle>>(styles: Definition<Keys>, configuration?: Configuration): AnimationSet<Keys>;
19
+ export {};
20
+ //# sourceMappingURL=useAnimation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAnimation.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useAnimation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEnD,mDAAmD;AACnD,aAAK,SAAS,CAAC,IAAI,SAAS,MAAM,OAAO,CAAC,SAAS,CAAC,IAAI,MAAM,CAC5D,IAAI,EACJ,QAAQ,CAAC,qBAAqB,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,GAAG,CACtD,CAAC;AACF,aAAK,UAAU,CAAC,IAAI,SAAS,MAAM,OAAO,CAAC,SAAS,CAAC,IAAI,MAAM,CAC7D,IAAI,EACJ,MAAM,EAAE,GAAG,MAAM,EAAE,CACpB,CAAC;AAEF,UAAU,aAAa;IACrB,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,yHAAyH;IACzH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY,CAAC,IAAI,SAAS,MAAM,OAAO,CAAC,SAAS,CAAC;IACjE,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;IACzB,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,UAAU,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;IAC5B,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED,wBAAgB,YAAY,CAAC,IAAI,SAAS,MAAM,OAAO,CAAC,SAAS,CAAC,EAChE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,EACxB,aAAa,CAAC,EAAE,aAAa,GAC5B,YAAY,CAAC,IAAI,CAAC,CA8BpB"}
@@ -0,0 +1,30 @@
1
+ import { AnimationSet } from "./useAnimation";
2
+ interface BaseTimelineType {
3
+ elements: AnimationSet<any>[];
4
+ start: boolean;
5
+ onFinished?: () => void;
6
+ onStarted?: () => void;
7
+ }
8
+ declare type DelayTimeline = BaseTimelineType & {
9
+ delay: number;
10
+ };
11
+ declare type StaggerTimeline = BaseTimelineType & {
12
+ stagger: number;
13
+ };
14
+ interface TimelineConfiguration {
15
+ delay?: DelayTimeline;
16
+ parallel?: BaseTimelineType;
17
+ sequence?: BaseTimelineType;
18
+ stagger?: StaggerTimeline;
19
+ }
20
+ /** Used to layout animated values on a timeline and handle starting/reversing the animations.
21
+ * Supports all Animated types (delay, stagger, parallel, sequence).
22
+ * @example
23
+ * useAnimationTimeline({
24
+ stagger: { elements: [ring1, ring2, ring3], stagger: 900, start: show },
25
+ sequence: { elements: [button], start: Boolean(show && !disabled) },
26
+ });
27
+ */
28
+ export declare function useAnimationTimeline(config: TimelineConfiguration): void;
29
+ export {};
30
+ //# sourceMappingURL=useAnimationTimeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAnimationTimeline.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useAnimationTimeline.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,UAAU,gBAAgB;IACxB,QAAQ,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,aAAK,aAAa,GAAG,gBAAgB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AACF,aAAK,eAAe,GAAG,gBAAgB,GAAG;IACxC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,UAAU,qBAAqB;IAC7B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAED;;;;;;;EAOE;AACF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAyGxE"}
@@ -0,0 +1,7 @@
1
+ interface Config {
2
+ onForeground?: () => void;
3
+ onBackground?: () => void;
4
+ }
5
+ export declare function useAppState({ onForeground, onBackground }: Config): void;
6
+ export {};
7
+ //# sourceMappingURL=useAppState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAppState.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useAppState.ts"],"names":[],"mappings":"AAGA,UAAU,MAAM;IACd,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,wBAAgB,WAAW,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,MAAM,QAiBjE"}
@@ -0,0 +1,52 @@
1
+ declare type Validation<T> = {
2
+ [K in keyof Partial<T>]?: boolean;
3
+ };
4
+ declare type Rules<T> = {
5
+ [K in keyof T]?: (value: T[K], state: T) => boolean | undefined;
6
+ };
7
+ declare type Values<T> = {
8
+ [K in keyof T]: T[K];
9
+ };
10
+ export declare type FormConfig<R> = {
11
+ /** List of optional properties. Optional properties will be marked as valid if left empty. */
12
+ optional?: Array<keyof R>;
13
+ /** Validation rules by specified property name. If you define a validation rule function here, the field will be validated against it. If no rule is set, a crude value check will be used instead (Boolean(value)) */
14
+ rules?: Rules<R>;
15
+ /** Will compare key/value pairs instead of just top level JSON.stringify on complex objects/arrays */
16
+ deepCompare?: boolean;
17
+ logging?: boolean;
18
+ };
19
+ /** One-fits-all solution to manage state changes, field validation and optional entries within a form.
20
+ * @example <caption>Simple use case:</caption>
21
+ * const { state, validation, update } = useForm({ email: '', password: '', });
22
+ *
23
+ *
24
+ * @example <caption>For more complex form states (ie one field can be of multiple types), you should pass the form's type:</caption>
25
+ * const { state, validation, update } = useForm<{ numericOrUndefined: number | undefined }>({ numericOrUndefined: undefined }, { rules: { numericOrUndefined: (value: number | undefined): boolean | undefined => ... }});
26
+ *
27
+ */
28
+ export declare function useForm<T>(values: Values<T>, config?: FormConfig<T>): {
29
+ state: Values<T>;
30
+ validation: Validation<T>;
31
+ update: <K extends keyof T>(key: K, value: Values<T>[K], shouldValidate?: boolean) => void;
32
+ validate: <K_1 extends keyof T>(key: K_1) => void;
33
+ validateForm: () => boolean;
34
+ isFormValid: () => boolean;
35
+ clearForm: () => void;
36
+ resetState: () => void;
37
+ resetValidation: () => void;
38
+ resetInitialValues: () => void;
39
+ };
40
+ /** Helper hook to validate form state outside of the scope of useForm. */
41
+ export declare function useFormUtils<T>(config?: FormConfig<T>): {
42
+ doesValueExist: (value: T[keyof T] | undefined) => value is T[keyof T];
43
+ validateByRule: <K extends keyof T>(key: K, value: T[K], state: Values<T>) => boolean | undefined;
44
+ isOptional: (key: keyof T) => boolean | undefined;
45
+ fieldValidation: (key: keyof T, value: T[keyof T] | undefined, state: Values<T>) => boolean | undefined;
46
+ stateValidation: (state: Values<T>) => {
47
+ valid: boolean;
48
+ validation: Validation<T>;
49
+ };
50
+ };
51
+ export {};
52
+ //# sourceMappingURL=useForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useForm.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useForm.ts"],"names":[],"mappings":"AAEA,aAAK,UAAU,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO;CAAE,CAAC;AAC3D,aAAK,KAAK,CAAC,CAAC,IAAI;KACb,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,SAAS;CAChE,CAAC;AAEF,aAAK,MAAM,CAAC,CAAC,IAAI;KACd,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACrB,CAAC;AAEF,oBAAY,UAAU,CAAC,CAAC,IAAI;IAC1B,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1B,uNAAuN;IACvN,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACjB,sGAAsG;IACtG,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;;;8EA2B/C,OAAO;;wBAmBD,OAAO;;;;;;EAgDjC;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;4BACrB,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS;oEAU5C,OAAO,CAAC,CAAC;sBAUO,MAAM,CAAC;2BAKzB,MAAM,CAAC,SACL,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,SACtB,OAAO,CAAC,CAAC;6BAWc,OAAO,CAAC,CAAC;;;;EAuB1C"}
@@ -0,0 +1,3 @@
1
+ import { SkeletorConfig } from "../models";
2
+ export declare function useSkeletor(): SkeletorConfig;
3
+ //# sourceMappingURL=useSkeletor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSkeletor.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useSkeletor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3C,wBAAgB,WAAW,IAAI,cAAc,CAE5C"}
@@ -0,0 +1,5 @@
1
+ export * from "./components";
2
+ export * from "./hooks";
3
+ export * from "./models";
4
+ export * from "./utils";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { ViewStyle } from "react-native";
2
+ export interface Alignment {
3
+ align?: ViewStyle["alignItems"];
4
+ alignSelf?: ViewStyle["alignSelf"];
5
+ justify?: ViewStyle["justifyContent"];
6
+ flexDirection?: ViewStyle["flexDirection"];
7
+ flexWrap?: ViewStyle["flexWrap"];
8
+ }
9
+ //# sourceMappingURL=Alignment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Alignment.d.ts","sourceRoot":"","sources":["../../../../src/models/Alignment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;IAChC,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,SAAS,CAAC,gBAAgB,CAAC,CAAC;IACtC,aAAa,CAAC,EAAE,SAAS,CAAC,eAAe,CAAC,CAAC;IAC3C,QAAQ,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;CAClC"}
@@ -0,0 +1,16 @@
1
+ export interface Border {
2
+ border?: {
3
+ borderWidth?: number;
4
+ borderTopWidth?: number;
5
+ borderBottomWidth?: number;
6
+ borderLeftWidth?: number;
7
+ borderRightWidth?: number;
8
+ borderColor?: string;
9
+ borderRadius?: number;
10
+ borderTopLeftRadius?: number;
11
+ borderTopRightRadius?: number;
12
+ borderBottomLeftRadius?: number;
13
+ borderBottomRightRadius?: number;
14
+ };
15
+ }
16
+ //# sourceMappingURL=Border.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Border.d.ts","sourceRoot":"","sources":["../../../../src/models/Border.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,MAAM,CAAC,EAAE;QACP,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;QAChC,uBAAuB,CAAC,EAAE,MAAM,CAAC;KAClC,CAAC;CACH"}
@@ -0,0 +1,10 @@
1
+ export interface Size {
2
+ width?: number | string;
3
+ height?: number | string;
4
+ minHeight?: number | string;
5
+ minWidth?: number | string;
6
+ maxHeight?: number | string;
7
+ maxWidth?: number | string;
8
+ flex?: number;
9
+ }
10
+ //# sourceMappingURL=Size.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Size.d.ts","sourceRoot":"","sources":["../../../../src/models/Size.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,IAAI;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
@@ -0,0 +1,7 @@
1
+ export interface SkeletorConfig {
2
+ defaultFont: Font | undefined;
3
+ defaultFontSize: [number, number] | number;
4
+ defaultStatusBarType: "dark-content" | "light-content" | "default";
5
+ defaultTextColor: string;
6
+ }
7
+ //# sourceMappingURL=SkeletorConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkeletorConfig.d.ts","sourceRoot":"","sources":["../../../../src/models/SkeletorConfig.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,IAAI,GAAG,SAAS,CAAC;IAC9B,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC;IAC3C,oBAAoB,EAAE,cAAc,GAAG,eAAe,GAAG,SAAS,CAAC;IACnE,gBAAgB,EAAE,MAAM,CAAC;CAC1B"}
@@ -0,0 +1,21 @@
1
+ export interface Spacing {
2
+ margins?: {
3
+ marginTop?: number | string;
4
+ marginBottom?: number | string;
5
+ marginLeft?: number | string;
6
+ marginRight?: number | string;
7
+ marginHorizontal?: number | string;
8
+ marginVertical?: number | string;
9
+ margin?: number | string;
10
+ };
11
+ paddings?: {
12
+ paddingTop?: number | string;
13
+ paddingBottom?: number | string;
14
+ paddingLeft?: number | string;
15
+ paddingRight?: number | string;
16
+ paddingHorizontal?: number | string;
17
+ paddingVertical?: number | string;
18
+ padding?: number | string;
19
+ };
20
+ }
21
+ //# sourceMappingURL=Spacing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Spacing.d.ts","sourceRoot":"","sources":["../../../../src/models/Spacing.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC/B,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC9B,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACnC,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACjC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KAC1B,CAAC;IACF,QAAQ,CAAC,EAAE;QACT,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC7B,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAChC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC9B,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC/B,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACpC,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAClC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KAC3B,CAAC;CACH"}
@@ -0,0 +1,6 @@
1
+ export * from "./Alignment";
2
+ export * from "./Border";
3
+ export * from "./Size";
4
+ export * from "./SkeletorConfig";
5
+ export * from "./Spacing";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/models/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Alignment } from "../models";
2
+ export declare function extractAlignmentProperties<Props extends Alignment>(props: Props): Alignment;
3
+ //# sourceMappingURL=extractAlignmentProperties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractAlignmentProperties.d.ts","sourceRoot":"","sources":["../../../../src/utils/extractAlignmentProperties.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,wBAAgB,0BAA0B,CAAC,KAAK,SAAS,SAAS,EAChE,KAAK,EAAE,KAAK,GACX,SAAS,CAQX"}
@@ -0,0 +1,3 @@
1
+ import { Size } from "../models";
2
+ export declare function extractSizeProperties<Props extends Size>(props: Props): Size;
3
+ //# sourceMappingURL=extractSizeProperties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractSizeProperties.d.ts","sourceRoot":"","sources":["../../../../src/utils/extractSizeProperties.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,wBAAgB,qBAAqB,CAAC,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAU5E"}
@@ -0,0 +1,3 @@
1
+ export * from "./extractAlignmentProperties";
2
+ export * from "./extractSizeProperties";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@prototyp/skeletor",
3
+ "description": "React-Native UI and functional toolkit",
4
+ "author": "Luka Buljan <luka@prototyp.digital>",
5
+ "version": "1.0.2",
6
+ "types": "lib/typescript/src/index.d.ts",
7
+ "main": "lib/module/index.js",
8
+ "react-native": "src/index.ts",
9
+ "module": "lib/module/index.js",
10
+ "repository": {
11
+ "type": "git",
12
+ "directory": "git+https://github.com/prototypdigital/skeletor.git"
13
+ },
14
+ "scripts": {
15
+ "prepack": "bob build"
16
+ },
17
+ "devDependencies": {
18
+ "@tsconfig/react-native": "2.0.3",
19
+ "@types/jest": "29.4.0",
20
+ "@types/react-native": "0.70.6",
21
+ "jest": "29.4.2",
22
+ "react": "18.1.0",
23
+ "react-native": "0.70.5",
24
+ "react-native-builder-bob": "0.20.3",
25
+ "typescript": "4.8.3"
26
+ },
27
+ "peerDependencies": {
28
+ "react": ">=16",
29
+ "react-native": ">=0.70.5"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "keywords": [
35
+ "react-native",
36
+ "ui",
37
+ "kit",
38
+ "validation",
39
+ "animation",
40
+ "helpers",
41
+ "utilities",
42
+ "utils"
43
+ ],
44
+ "files": [
45
+ "src",
46
+ "lib",
47
+ "!**/__tests__",
48
+ "!**/__fixtures__",
49
+ "!**/__mocks__"
50
+ ],
51
+ "react-native-builder-bob": {
52
+ "source": "src",
53
+ "output": "lib",
54
+ "targets": [
55
+ "module",
56
+ "typescript"
57
+ ]
58
+ },
59
+ "eslintIgnore": [
60
+ "node_modules/",
61
+ "lib/"
62
+ ]
63
+ }
Binary file
@@ -0,0 +1,106 @@
1
+ import React, { PropsWithChildren, useMemo } from "react";
2
+ import {
3
+ ScrollView,
4
+ StyleProp,
5
+ StyleSheet,
6
+ View,
7
+ ViewProps,
8
+ ViewStyle,
9
+ } from "react-native";
10
+ import { Alignment, Border, Size, Spacing } from "../../models";
11
+ import { extractAlignmentProperties, extractSizeProperties } from "../../utils";
12
+
13
+ interface SharedProps extends ViewProps {
14
+ background?: string;
15
+ overflow?: ViewStyle["overflow"];
16
+ }
17
+
18
+ interface BlockScrollViewProps extends SharedProps {
19
+ scrollable: true;
20
+ horizontal?: boolean;
21
+ showsVerticalScrollIndicator?: boolean;
22
+ showsHorizontalScrollIndicator?: boolean;
23
+ bounces?: boolean;
24
+ style?: StyleProp<ViewStyle>;
25
+ }
26
+
27
+ export interface BlockViewProps extends SharedProps {
28
+ scrollable?: false | undefined;
29
+ }
30
+
31
+ type BlockElementProps = SharedProps & Alignment & Spacing & Size & Border;
32
+
33
+ const BlockElement: React.FC<PropsWithChildren<BlockElementProps>> = ({
34
+ children,
35
+ ...props
36
+ }) => {
37
+ const { border, paddings, margins, background, style, overflow, ...view } =
38
+ props;
39
+
40
+ const size = extractSizeProperties(props);
41
+ const {
42
+ align: alignItems,
43
+ justify: justifyContent,
44
+ ...alignment
45
+ } = extractAlignmentProperties(props);
46
+
47
+ const styles = useMemo(
48
+ () =>
49
+ StyleSheet.flatten([
50
+ {
51
+ ...margins,
52
+ ...paddings,
53
+ ...alignment,
54
+ ...size,
55
+ ...border,
56
+ alignItems,
57
+ justifyContent,
58
+ backgroundColor: background,
59
+ overflow,
60
+ },
61
+ style,
62
+ ]),
63
+ [alignment, size, background, style, overflow, margins, paddings]
64
+ );
65
+
66
+ return (
67
+ <View {...view} style={styles}>
68
+ {children}
69
+ </View>
70
+ );
71
+ };
72
+
73
+ type BaseProps = Alignment & Spacing & Size & Border;
74
+ export type BlockProps = (BlockViewProps | BlockScrollViewProps) & BaseProps;
75
+
76
+ export const Block: React.FC<PropsWithChildren<BlockProps>> = ({
77
+ children,
78
+ ...props
79
+ }) => {
80
+ const { scrollable, ...rest } = props;
81
+ const element = () => <BlockElement {...rest}>{children}</BlockElement>;
82
+
83
+ if (!scrollable) {
84
+ return element();
85
+ }
86
+
87
+ const {
88
+ horizontal,
89
+ showsHorizontalScrollIndicator,
90
+ showsVerticalScrollIndicator,
91
+ bounces,
92
+ } = props;
93
+
94
+ return (
95
+ <ScrollView
96
+ horizontal={horizontal}
97
+ keyboardShouldPersistTaps="handled"
98
+ showsHorizontalScrollIndicator={showsHorizontalScrollIndicator}
99
+ showsVerticalScrollIndicator={showsVerticalScrollIndicator}
100
+ contentContainerStyle={{ flexGrow: 1, backgroundColor: rest.background }}
101
+ bounces={bounces}
102
+ >
103
+ {element()}
104
+ </ScrollView>
105
+ );
106
+ };
@@ -0,0 +1 @@
1
+ export * from "./Block";
@@ -0,0 +1,120 @@
1
+ import React, { PropsWithChildren, useRef, useState } from "react";
2
+ import {
3
+ Platform,
4
+ LayoutChangeEvent,
5
+ NativeSyntheticEvent,
6
+ ScrollView,
7
+ ScrollViewProps,
8
+ StyleSheet,
9
+ TextInputFocusEventData,
10
+ Dimensions,
11
+ } from "react-native";
12
+ import { Spacing } from "../../models";
13
+
14
+ export interface InputFocusScrollViewProps
15
+ extends Omit<ScrollViewProps, "children">,
16
+ Spacing {
17
+ /** Percentage of screen to add to element position. Values between 0 and 1. Use this if you want to position the input focus somewhere other than the top of the screen. Defaults to 0.3 */
18
+ focusPositionOffset?: number;
19
+ height?: "full" | "auto";
20
+ children: (
21
+ onInputFocus: (e: NativeSyntheticEvent<TextInputFocusEventData>) => void
22
+ ) => React.ReactNode;
23
+ }
24
+
25
+ /**
26
+ * This scroll view will automatically scroll to an active input field rendered within it, provided you attach the onInputFocus callback to the input onFocus prop.
27
+ *
28
+ * The return value is a lambda component, returning a callback which you attach to input fields rendered within it.
29
+ * @example <InputFocusScrollView>{(onInputFocus) => <TextInput onFocus={onInputFocus} ... />}</InputFocusScrollView>
30
+ * NOTE: This works on iOS only, Android does this by default with @param android:windowSoftInputMode
31
+ */
32
+ export const InputFocusScrollView: React.FC<
33
+ PropsWithChildren<InputFocusScrollViewProps>
34
+ > = ({
35
+ children,
36
+ style,
37
+ contentContainerStyle,
38
+ height = "full",
39
+ focusPositionOffset = 0.3,
40
+ margins,
41
+ paddings,
42
+ ...rest
43
+ }) => {
44
+ const screenHeight = useRef(Dimensions.get("screen").height).current;
45
+ const ref = useRef<ScrollView>(null);
46
+ const [scrollTarget, setScrollTarget] = useState<number | null>();
47
+ /** Cached scroll position to keep focus on input if layout shifts. */
48
+ const [scrollPosition, setScrollPosition] = useState<number | null>();
49
+
50
+ function onInputFocus(e: NativeSyntheticEvent<TextInputFocusEventData>) {
51
+ if (Platform.OS !== "ios" || !scrollTarget) {
52
+ return;
53
+ }
54
+ e.currentTarget.measureLayout(
55
+ scrollTarget,
56
+ (nope, top, nuuh, elementHeight) => {
57
+ let scrollY = top - elementHeight;
58
+ if (focusPositionOffset !== undefined) {
59
+ scrollY = scrollY - screenHeight * focusPositionOffset;
60
+ }
61
+
62
+ // Cache scroll position for layout shift cases
63
+ setScrollPosition(scrollY);
64
+ // Scroll to input position
65
+ ref.current?.scrollTo({ y: scrollY });
66
+ },
67
+ () => console.error("failed to measure layout")
68
+ );
69
+ }
70
+
71
+ function onScrollViewLayout(e: LayoutChangeEvent) {
72
+ if (Platform.OS !== "ios") {
73
+ return;
74
+ }
75
+ setScrollTarget(e.nativeEvent.target);
76
+ }
77
+
78
+ /** Handle layout shifts by programmatically scrolling to the same input position without animation. */
79
+ function onContentSizeChange() {
80
+ if (Platform.OS !== "ios" || !scrollPosition) {
81
+ return;
82
+ }
83
+ ref.current?.scrollTo({ y: scrollPosition, animated: false });
84
+ setScrollPosition(undefined);
85
+ }
86
+
87
+ const containerStyles = StyleSheet.flatten([styles[height], margins, style]);
88
+
89
+ const contentStyles = StyleSheet.flatten([
90
+ styles.content,
91
+ { ...paddings },
92
+ contentContainerStyle,
93
+ ]);
94
+
95
+ return (
96
+ <ScrollView
97
+ ref={ref}
98
+ scrollToOverflowEnabled
99
+ scrollEventThrottle={16}
100
+ onLayout={onScrollViewLayout}
101
+ onContentSizeChange={onContentSizeChange}
102
+ showsVerticalScrollIndicator={false}
103
+ showsHorizontalScrollIndicator={false}
104
+ style={containerStyles}
105
+ contentContainerStyle={contentStyles}
106
+ {...rest}
107
+ >
108
+ {children(onInputFocus)}
109
+ </ScrollView>
110
+ );
111
+ };
112
+
113
+ const styles = StyleSheet.create({
114
+ full: { height: "100%" },
115
+ auto: { height: "auto" },
116
+ content: {
117
+ flexGrow: 1,
118
+ paddingBottom: 30,
119
+ },
120
+ });
@@ -0,0 +1 @@
1
+ export * from "./InputFocusScrollView";