@amabeth/repeating-wheel-picker 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +57 -57
  3. package/example/index.ts +8 -0
  4. package/example/node_modules/@expo/cli/static/template/+html.tsx +28 -0
  5. package/example/node_modules/@expo/cli/static/template/+native-intent.ts +9 -0
  6. package/example/node_modules/@expo/cli/static/template/[...rsc]+api.ts +16 -0
  7. package/example/node_modules/ansi-styles/index.d.ts +345 -0
  8. package/example/node_modules/chalk/index.d.ts +415 -0
  9. package/example/node_modules/commander/typings/index.d.ts +627 -0
  10. package/example/node_modules/expo/Expo.podspec +108 -0
  11. package/example/node_modules/expo/build/Expo.d.ts +8 -0
  12. package/example/node_modules/expo/build/Expo.fx.d.ts +4 -0
  13. package/example/node_modules/expo/build/Expo.fx.web.d.ts +3 -0
  14. package/example/node_modules/expo/build/devtools/DevToolsPluginClient.d.ts +72 -0
  15. package/example/node_modules/expo/build/devtools/DevToolsPluginClientFactory.d.ts +16 -0
  16. package/example/node_modules/expo/build/devtools/DevToolsPluginClientImplApp.d.ts +15 -0
  17. package/example/node_modules/expo/build/devtools/DevToolsPluginClientImplBrowser.d.ts +14 -0
  18. package/example/node_modules/expo/build/devtools/MessageFramePacker.d.ts +50 -0
  19. package/example/node_modules/expo/build/devtools/ProtocolVersion.d.ts +7 -0
  20. package/example/node_modules/expo/build/devtools/WebSocketBackingStore.d.ts +10 -0
  21. package/example/node_modules/expo/build/devtools/WebSocketWithReconnect.d.ts +81 -0
  22. package/example/node_modules/expo/build/devtools/devtools.types.d.ts +42 -0
  23. package/example/node_modules/expo/build/devtools/getConnectionInfo.d.ts +6 -0
  24. package/example/node_modules/expo/build/devtools/getConnectionInfo.native.d.ts +6 -0
  25. package/example/node_modules/expo/build/devtools/index.d.ts +12 -0
  26. package/example/node_modules/expo/build/devtools/logger.d.ts +6 -0
  27. package/example/node_modules/expo/build/dom/base.d.ts +5 -0
  28. package/example/node_modules/expo/build/dom/dom-entry.d.ts +3 -0
  29. package/example/node_modules/expo/build/dom/dom-hooks.d.ts +8 -0
  30. package/example/node_modules/expo/build/dom/dom.d.ts +5 -0
  31. package/example/node_modules/expo/build/dom/dom.types.d.ts +34 -0
  32. package/example/node_modules/expo/build/dom/dom.web.d.ts +3 -0
  33. package/example/node_modules/expo/build/dom/global-events.d.ts +4 -0
  34. package/example/node_modules/expo/build/dom/injection.d.ts +9 -0
  35. package/example/node_modules/expo/build/dom/internal.d.ts +3 -0
  36. package/example/node_modules/expo/build/dom/internal.web.d.ts +2 -0
  37. package/example/node_modules/expo/build/dom/marshal.d.ts +4 -0
  38. package/example/node_modules/expo/build/dom/webview/ExpoDOMWebView.d.ts +6 -0
  39. package/example/node_modules/expo/build/dom/webview/RNWebView.d.ts +7 -0
  40. package/example/node_modules/expo/build/dom/webview/useDebugZeroHeight.d.ts +12 -0
  41. package/example/node_modules/expo/build/dom/webview-wrapper.d.ts +16 -0
  42. package/example/node_modules/expo/build/environment/DevLoadingView.d.ts +3 -0
  43. package/example/node_modules/expo/build/environment/DevLoadingView.web.d.ts +3 -0
  44. package/example/node_modules/expo/build/environment/DevLoadingViewNativeModule.d.ts +9 -0
  45. package/example/node_modules/expo/build/environment/DevLoadingViewNativeModule.native.d.ts +3 -0
  46. package/example/node_modules/expo/build/environment/ExpoGo.d.ts +31 -0
  47. package/example/node_modules/expo/build/environment/ExpoGo.web.d.ts +3 -0
  48. package/example/node_modules/expo/build/environment/getInitialSafeArea.d.ts +7 -0
  49. package/example/node_modules/expo/build/environment/getInitialSafeArea.native.d.ts +11 -0
  50. package/example/node_modules/expo/build/errors/AppEntryNotFound.d.ts +2 -0
  51. package/example/node_modules/expo/build/errors/ExpoErrorManager.d.ts +8 -0
  52. package/example/node_modules/expo/build/errors/ExpoErrorManager.native.d.ts +4 -0
  53. package/example/node_modules/expo/build/hooks/useEvent.d.ts +59 -0
  54. package/example/node_modules/expo/build/launch/registerRootComponent.d.ts +30 -0
  55. package/example/node_modules/expo/build/launch/withDevTools.d.ts +3 -0
  56. package/example/node_modules/expo/build/launch/withDevTools.ios.d.ts +7 -0
  57. package/example/node_modules/expo/build/launch/withDevTools.web.d.ts +3 -0
  58. package/example/node_modules/expo/build/timer/polyfillNextTick.d.ts +6 -0
  59. package/example/node_modules/expo/build/utils/blobUtils.d.ts +9 -0
  60. package/example/node_modules/expo/build/utils/getBundleUrl.d.ts +2 -0
  61. package/example/node_modules/expo/build/utils/getBundleUrl.native.d.ts +2 -0
  62. package/example/node_modules/expo/build/utils/getBundleUrl.web.d.ts +2 -0
  63. package/example/node_modules/expo/build/winter/FormData.d.ts +49 -0
  64. package/example/node_modules/expo/build/winter/ImportMetaRegistry.d.ts +9 -0
  65. package/example/node_modules/expo/build/winter/TextDecoder.d.ts +20 -0
  66. package/example/node_modules/expo/build/winter/fetch/ExpoFetchModule.d.ts +2 -0
  67. package/example/node_modules/expo/build/winter/fetch/ExpoFetchModule.web.d.ts +10 -0
  68. package/example/node_modules/expo/build/winter/fetch/FetchErrors.d.ts +8 -0
  69. package/example/node_modules/expo/build/winter/fetch/FetchResponse.d.ts +31 -0
  70. package/example/node_modules/expo/build/winter/fetch/NativeRequest.d.ts +30 -0
  71. package/example/node_modules/expo/build/winter/fetch/RequestUtils.d.ts +21 -0
  72. package/example/node_modules/expo/build/winter/fetch/convertFormData.d.ts +19 -0
  73. package/example/node_modules/expo/build/winter/fetch/fetch.d.ts +4 -0
  74. package/example/node_modules/expo/build/winter/fetch/fetch.types.d.ts +16 -0
  75. package/example/node_modules/expo/build/winter/fetch/fetch.web.d.ts +2 -0
  76. package/example/node_modules/expo/build/winter/fetch/index.d.ts +3 -0
  77. package/example/node_modules/expo/build/winter/index.d.ts +2 -0
  78. package/example/node_modules/expo/build/winter/runtime.d.ts +2 -0
  79. package/example/node_modules/expo/build/winter/runtime.native.d.ts +2 -0
  80. package/example/node_modules/expo/build/winter/url.d.ts +23 -0
  81. package/example/node_modules/expo/config-plugins.d.ts +1 -0
  82. package/example/node_modules/expo/config.d.ts +1 -0
  83. package/example/node_modules/expo/devtools.d.ts +1 -0
  84. package/example/node_modules/expo/dom/global.d.ts +1 -0
  85. package/example/node_modules/expo/dom/index.d.ts +1 -0
  86. package/example/node_modules/expo/dom/internal.d.ts +1 -0
  87. package/example/node_modules/expo/fetch.d.ts +1 -0
  88. package/example/node_modules/expo/fingerprint.d.ts +1 -0
  89. package/example/node_modules/expo/metro-config.d.ts +1 -0
  90. package/example/node_modules/expo/react-native.config.js +50 -0
  91. package/example/node_modules/expo/src/Expo.fx.tsx +53 -0
  92. package/example/node_modules/expo/src/Expo.fx.web.tsx +21 -0
  93. package/example/node_modules/expo/src/Expo.ts +30 -0
  94. package/example/node_modules/expo/src/devtools/DevToolsPluginClient.ts +240 -0
  95. package/example/node_modules/expo/src/devtools/DevToolsPluginClientFactory.ts +73 -0
  96. package/example/node_modules/expo/src/devtools/DevToolsPluginClientImplApp.ts +56 -0
  97. package/example/node_modules/expo/src/devtools/DevToolsPluginClientImplBrowser.ts +38 -0
  98. package/example/node_modules/expo/src/devtools/MessageFramePacker.ts +235 -0
  99. package/example/node_modules/expo/src/devtools/ProtocolVersion.ts +6 -0
  100. package/example/node_modules/expo/src/devtools/WebSocketBackingStore.ts +10 -0
  101. package/example/node_modules/expo/src/devtools/WebSocketWithReconnect.ts +318 -0
  102. package/example/node_modules/expo/src/devtools/devtools.types.ts +50 -0
  103. package/example/node_modules/expo/src/devtools/getConnectionInfo.native.ts +18 -0
  104. package/example/node_modules/expo/src/devtools/getConnectionInfo.ts +16 -0
  105. package/example/node_modules/expo/src/devtools/index.ts +53 -0
  106. package/example/node_modules/expo/src/devtools/logger.ts +29 -0
  107. package/example/node_modules/expo/src/dom/base.ts +62 -0
  108. package/example/node_modules/expo/src/dom/dom-entry.tsx +128 -0
  109. package/example/node_modules/expo/src/dom/dom-hooks.ts +46 -0
  110. package/example/node_modules/expo/src/dom/dom.ts +8 -0
  111. package/example/node_modules/expo/src/dom/dom.types.ts +39 -0
  112. package/example/node_modules/expo/src/dom/dom.web.ts +6 -0
  113. package/example/node_modules/expo/src/dom/global-events.ts +16 -0
  114. package/example/node_modules/expo/src/dom/injection.ts +42 -0
  115. package/example/node_modules/expo/src/dom/internal.ts +5 -0
  116. package/example/node_modules/expo/src/dom/internal.web.ts +1 -0
  117. package/example/node_modules/expo/src/dom/marshal.tsx +116 -0
  118. package/example/node_modules/expo/src/dom/webview/ExpoDOMWebView.ts +10 -0
  119. package/example/node_modules/expo/src/dom/webview/RNWebView.ts +12 -0
  120. package/example/node_modules/expo/src/dom/webview/useDebugZeroHeight.ts +62 -0
  121. package/example/node_modules/expo/src/dom/webview-wrapper.tsx +253 -0
  122. package/example/node_modules/expo/src/environment/DevLoadingView.tsx +123 -0
  123. package/example/node_modules/expo/src/environment/DevLoadingView.web.tsx +135 -0
  124. package/example/node_modules/expo/src/environment/DevLoadingViewNativeModule.native.ts +3 -0
  125. package/example/node_modules/expo/src/environment/DevLoadingViewNativeModule.ts +7 -0
  126. package/example/node_modules/expo/src/environment/ExpoGo.ts +53 -0
  127. package/example/node_modules/expo/src/environment/ExpoGo.web.ts +7 -0
  128. package/example/node_modules/expo/src/environment/getInitialSafeArea.native.ts +16 -0
  129. package/example/node_modules/expo/src/environment/getInitialSafeArea.ts +8 -0
  130. package/example/node_modules/expo/src/errors/AppEntryNotFound.tsx +35 -0
  131. package/example/node_modules/expo/src/errors/ExpoErrorManager.native.ts +51 -0
  132. package/example/node_modules/expo/src/errors/ExpoErrorManager.ts +11 -0
  133. package/example/node_modules/expo/src/hooks/useEvent.ts +112 -0
  134. package/example/node_modules/expo/src/launch/registerRootComponent.tsx +64 -0
  135. package/example/node_modules/expo/src/launch/withDevTools.ios.tsx +47 -0
  136. package/example/node_modules/expo/src/launch/withDevTools.tsx +30 -0
  137. package/example/node_modules/expo/src/launch/withDevTools.web.tsx +23 -0
  138. package/example/node_modules/expo/src/timer/polyfillNextTick.ts +10 -0
  139. package/example/node_modules/expo/src/ts-declarations/console.d.ts +47 -0
  140. package/example/node_modules/expo/src/ts-declarations/global.d.ts +12 -0
  141. package/example/node_modules/expo/src/ts-declarations/react-native.d.ts +34 -0
  142. package/example/node_modules/expo/src/ts-declarations/whatwg-url-without-unicode.d.ts +186 -0
  143. package/example/node_modules/expo/src/utils/blobUtils.ts +23 -0
  144. package/example/node_modules/expo/src/utils/getBundleUrl.native.ts +17 -0
  145. package/example/node_modules/expo/src/utils/getBundleUrl.ts +5 -0
  146. package/example/node_modules/expo/src/utils/getBundleUrl.web.ts +21 -0
  147. package/example/node_modules/expo/src/winter/FormData.ts +222 -0
  148. package/example/node_modules/expo/src/winter/ImportMetaRegistry.ts +14 -0
  149. package/example/node_modules/expo/src/winter/TextDecoder.ts +429 -0
  150. package/example/node_modules/expo/src/winter/fetch/ExpoFetchModule.ts +3 -0
  151. package/example/node_modules/expo/src/winter/fetch/ExpoFetchModule.web.ts +7 -0
  152. package/example/node_modules/expo/src/winter/fetch/FetchErrors.ts +11 -0
  153. package/example/node_modules/expo/src/winter/fetch/FetchResponse.ts +146 -0
  154. package/example/node_modules/expo/src/winter/fetch/NativeRequest.ts +38 -0
  155. package/example/node_modules/expo/src/winter/fetch/RequestUtils.ts +124 -0
  156. package/example/node_modules/expo/src/winter/fetch/convertFormData.ts +92 -0
  157. package/example/node_modules/expo/src/winter/fetch/fetch.ts +59 -0
  158. package/example/node_modules/expo/src/winter/fetch/fetch.types.ts +17 -0
  159. package/example/node_modules/expo/src/winter/fetch/fetch.web.ts +1 -0
  160. package/example/node_modules/expo/src/winter/fetch/index.ts +2 -0
  161. package/example/node_modules/expo/src/winter/index.ts +1 -0
  162. package/example/node_modules/expo/src/winter/runtime.native.ts +41 -0
  163. package/example/node_modules/expo/src/winter/runtime.ts +5 -0
  164. package/example/node_modules/expo/src/winter/url.ts +116 -0
  165. package/example/node_modules/expo/types/global.d.ts +38 -0
  166. package/example/node_modules/expo/types/index.d.ts +3 -0
  167. package/example/node_modules/expo/types/metro-require.d.ts +52 -0
  168. package/example/node_modules/expo/types/react-native-web.d.ts +291 -0
  169. package/example/node_modules/expo-modules-autolinking/build/ExpoModuleConfig.d.ts +85 -0
  170. package/example/node_modules/expo-modules-autolinking/build/autolinking/findModules.d.ts +5 -0
  171. package/example/node_modules/expo-modules-autolinking/build/autolinking/generatePackageList.d.ts +11 -0
  172. package/example/node_modules/expo-modules-autolinking/build/autolinking/getConfiguration.d.ts +2 -0
  173. package/example/node_modules/expo-modules-autolinking/build/autolinking/index.d.ts +17 -0
  174. package/example/node_modules/expo-modules-autolinking/build/autolinking/mergeLinkingOptions.d.ts +21 -0
  175. package/example/node_modules/expo-modules-autolinking/build/autolinking/resolveModules.d.ts +9 -0
  176. package/example/node_modules/expo-modules-autolinking/build/autolinking/utils.d.ts +6 -0
  177. package/example/node_modules/expo-modules-autolinking/build/autolinking/verifySearchResults.d.ts +5 -0
  178. package/example/node_modules/expo-modules-autolinking/build/fileUtils.d.ts +18 -0
  179. package/example/node_modules/expo-modules-autolinking/build/index.d.ts +1 -0
  180. package/example/node_modules/expo-modules-autolinking/build/platforms/android.d.ts +38 -0
  181. package/example/node_modules/expo-modules-autolinking/build/platforms/apple.d.ts +15 -0
  182. package/example/node_modules/expo-modules-autolinking/build/platforms/devtools.d.ts +3 -0
  183. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/androidResolver.d.ts +20 -0
  184. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/config.d.ts +5 -0
  185. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/index.d.ts +2 -0
  186. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/iosResolver.d.ts +2 -0
  187. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/reactNativeConfig.d.ts +13 -0
  188. package/example/node_modules/expo-modules-autolinking/build/reactNativeConfig/reactNativeConfig.types.d.ts +95 -0
  189. package/example/node_modules/expo-modules-autolinking/build/types.d.ts +319 -0
  190. package/example/node_modules/expo-modules-autolinking/e2e/TestUtils.ts +53 -0
  191. package/example/node_modules/expo-modules-autolinking/exports.d.ts +1 -0
  192. package/example/node_modules/expo-modules-autolinking/src/ExpoModuleConfig.ts +181 -0
  193. package/example/node_modules/expo-modules-autolinking/src/autolinking/findModules.ts +259 -0
  194. package/example/node_modules/expo-modules-autolinking/src/autolinking/generatePackageList.ts +46 -0
  195. package/example/node_modules/expo-modules-autolinking/src/autolinking/getConfiguration.ts +7 -0
  196. package/example/node_modules/expo-modules-autolinking/src/autolinking/index.ts +45 -0
  197. package/example/node_modules/expo-modules-autolinking/src/autolinking/mergeLinkingOptions.ts +127 -0
  198. package/example/node_modules/expo-modules-autolinking/src/autolinking/resolveModules.ts +46 -0
  199. package/example/node_modules/expo-modules-autolinking/src/autolinking/utils.ts +37 -0
  200. package/example/node_modules/expo-modules-autolinking/src/autolinking/verifySearchResults.ts +33 -0
  201. package/example/node_modules/expo-modules-autolinking/src/fileUtils.ts +64 -0
  202. package/example/node_modules/expo-modules-autolinking/src/index.ts +262 -0
  203. package/example/node_modules/expo-modules-autolinking/src/platforms/android.ts +303 -0
  204. package/example/node_modules/expo-modules-autolinking/src/platforms/apple.ts +292 -0
  205. package/example/node_modules/expo-modules-autolinking/src/platforms/devtools.ts +25 -0
  206. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/androidResolver.ts +264 -0
  207. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/config.ts +67 -0
  208. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/index.ts +2 -0
  209. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/iosResolver.ts +37 -0
  210. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/reactNativeConfig.ts +245 -0
  211. package/example/node_modules/expo-modules-autolinking/src/reactNativeConfig/reactNativeConfig.types.ts +107 -0
  212. package/example/node_modules/expo-modules-autolinking/src/types.ts +384 -0
  213. package/example/node_modules/find-up/index.d.ts +138 -0
  214. package/example/node_modules/glob/dist/commonjs/glob.d.ts +388 -0
  215. package/example/node_modules/glob/dist/commonjs/has-magic.d.ts +14 -0
  216. package/example/node_modules/glob/dist/commonjs/ignore.d.ts +24 -0
  217. package/example/node_modules/glob/dist/commonjs/index.d.ts +97 -0
  218. package/example/node_modules/glob/dist/commonjs/pattern.d.ts +76 -0
  219. package/example/node_modules/glob/dist/commonjs/processor.d.ts +59 -0
  220. package/example/node_modules/glob/dist/commonjs/walker.d.ts +97 -0
  221. package/example/node_modules/glob/dist/esm/glob.d.ts +388 -0
  222. package/example/node_modules/glob/dist/esm/has-magic.d.ts +14 -0
  223. package/example/node_modules/glob/dist/esm/ignore.d.ts +24 -0
  224. package/example/node_modules/glob/dist/esm/index.d.ts +97 -0
  225. package/example/node_modules/glob/dist/esm/pattern.d.ts +76 -0
  226. package/example/node_modules/glob/dist/esm/processor.d.ts +59 -0
  227. package/example/node_modules/glob/dist/esm/walker.d.ts +97 -0
  228. package/example/node_modules/locate-path/index.d.ts +83 -0
  229. package/example/node_modules/log-symbols/node_modules/chalk/types/index.d.ts +97 -0
  230. package/example/node_modules/minimatch/dist/commonjs/assert-valid-pattern.d.ts +2 -0
  231. package/example/node_modules/minimatch/dist/commonjs/ast.d.ts +20 -0
  232. package/example/node_modules/minimatch/dist/commonjs/brace-expressions.d.ts +8 -0
  233. package/example/node_modules/minimatch/dist/commonjs/escape.d.ts +12 -0
  234. package/example/node_modules/minimatch/dist/commonjs/index.d.ts +94 -0
  235. package/example/node_modules/minimatch/dist/commonjs/unescape.d.ts +17 -0
  236. package/example/node_modules/minimatch/dist/esm/assert-valid-pattern.d.ts +2 -0
  237. package/example/node_modules/minimatch/dist/esm/ast.d.ts +20 -0
  238. package/example/node_modules/minimatch/dist/esm/brace-expressions.d.ts +8 -0
  239. package/example/node_modules/minimatch/dist/esm/escape.d.ts +12 -0
  240. package/example/node_modules/minimatch/dist/esm/index.d.ts +94 -0
  241. package/example/node_modules/minimatch/dist/esm/unescape.d.ts +17 -0
  242. package/example/node_modules/ora/index.d.ts +257 -0
  243. package/example/node_modules/ora/node_modules/chalk/types/index.d.ts +97 -0
  244. package/example/node_modules/ora/node_modules/strip-ansi/index.d.ts +15 -0
  245. package/example/node_modules/p-locate/index.d.ts +53 -0
  246. package/example/node_modules/path-exists/index.d.ts +28 -0
  247. package/example/package.json +29 -0
  248. package/example/src/constants/styles.ts +43 -0
  249. package/example/src/hooks/useComponentHeight.ts +13 -0
  250. package/example/src/scenes/app.tsx +33 -0
  251. package/example/src/scenes/booleanPicker.tsx +60 -0
  252. package/example/src/scenes/customTypePicker.tsx +83 -0
  253. package/example/src/scenes/numberPicker.tsx +75 -0
  254. package/example/src/scenes/stringPicker.tsx +64 -0
  255. package/lib/module/index.js +6 -6
  256. package/lib/module/index.js.map +1 -1
  257. package/package.json +168 -183
  258. package/src/index.tsx +0 -507
package/src/index.tsx DELETED
@@ -1,507 +0,0 @@
1
- import { type RefObject, useEffect, useMemo, useRef, useState } from "react";
2
- import {
3
- type AnimatableNumericValue,
4
- type ColorValue,
5
- type LayoutChangeEvent,
6
- Text,
7
- type TextStyle,
8
- View,
9
- type ViewStyle,
10
- VirtualizedList,
11
- } from "react-native";
12
- import { LinearGradient } from "expo-linear-gradient";
13
-
14
- /**
15
- * Provides a wheel picker with repeating data that can be infinitely scrolled.
16
- *
17
- * @param properties configuration of the wheel picker
18
- */
19
- export function RepeatingWheelPicker<T>(
20
- properties: RepeatingWheelPickerProps<T>
21
- ) {
22
- // set defaults for all unprovided optional properties
23
- const props = useMemo(() => withDefaults(properties), [properties]);
24
- // to always have enough data to scroll through, define how often the input data should be multiplied
25
- const dataMultiplier = useMemo(
26
- () => Math.max(Math.round(90 / props.data.length), 3),
27
- [props.data.length]
28
- );
29
- // difference between centered index and top most visible index
30
- const indexDiffTopToCentered = useMemo(
31
- () => Math.floor(props.itemDisplayCount / 2),
32
- [props.itemDisplayCount]
33
- );
34
- // offsets for all list elements
35
- const offsets = useMemo((): number[] =>
36
- getOffsets(
37
- props.data.length,
38
- props.itemDisplayCount,
39
- props.itemHeight,
40
- dataMultiplier),
41
- [props.data.length, props.itemDisplayCount, props.itemHeight, dataMultiplier, props.containerVerticalPadding]
42
- )
43
-
44
- // current selected item (centered one)
45
- const [current, setCurrent] = useState(() =>
46
- props.initialIndex + props.data.length * Math.floor(dataMultiplier / 2)
47
- );
48
- const listRef = useRef<VirtualizedList<T>>(null);
49
-
50
- // call "setSelected" when the current top item or the data changed
51
- useEffect(() => {
52
- const selectedElement =
53
- props.data[current % props.data.length]; // centered element
54
-
55
- if (selectedElement !== undefined) {
56
- props.setSelected(selectedElement);
57
- }
58
- }, [current, props.data]);
59
-
60
- return (
61
- <View
62
- onLayout={props.containerOnLayout}
63
- style={{
64
- ...props.containerStyle,
65
- height:
66
- props.itemHeight * props.itemDisplayCount + props.containerVerticalPadding * 2
67
- }}
68
- >
69
- <VirtualizedList<T>
70
- ref={listRef}
71
- scrollEnabled={props.enabled}
72
- getItemCount={() => props.data.length * dataMultiplier}
73
-
74
- initialScrollIndex={current - indexDiffTopToCentered}
75
- initialNumToRender={props.data.length * dataMultiplier}
76
- windowSize={props.data.length * dataMultiplier}
77
-
78
- renderItem={({ item, index }) => (
79
- <Item item={item} props={props} key={index} />
80
- )}
81
- getItem={(_, index) =>
82
- props.data[index % props.data.length]!
83
- }
84
- getItemLayout={(_, index) => ({
85
- length: props.itemHeight,
86
- offset: offsets[index]!,
87
- index: index,
88
- })}
89
- keyExtractor={(_, index) => `${index}`}
90
-
91
- // disableIntervalMomentum={true}
92
- decelerationRate="fast"
93
- snapToOffsets={offsets}
94
-
95
- onMomentumScrollEnd={(event) =>
96
- onMomentumScrollEnd(
97
- event.nativeEvent.contentOffset.y,
98
- setCurrent,
99
- props.data.length,
100
- props.itemHeight,
101
- dataMultiplier,
102
- indexDiffTopToCentered,
103
- props.containerVerticalPadding,
104
- listRef
105
- )
106
- }
107
-
108
- showsVerticalScrollIndicator={false}
109
- style={{
110
- flex: 1,
111
- width: "100%",
112
- borderRadius: props.containerStyle.borderRadius,
113
- paddingVertical: props.containerVerticalPadding,
114
- paddingHorizontal: props.containerHorizontalPadding
115
- }}
116
- />
117
-
118
- { props.enableGradient &&
119
- <View
120
- style={{
121
- backgroundColor: "transparent",
122
- position: "absolute",
123
- height: "100%",
124
- width: "100%"
125
- }}
126
- >
127
- <FrontGradient gradientFadeColor={props.gradientFadeColor} borderRadius={props.containerStyle.borderRadius} />
128
- </View>
129
- }
130
- </View>
131
- );
132
- }
133
-
134
- function Item<T>({
135
- item,
136
- props,
137
- }: {
138
- item: T;
139
- props: RepeatingWheelPickerPropsWithDefaults<T>;
140
- }) {
141
-
142
- return (
143
- <View
144
- style={{
145
- justifyContent: "center",
146
- alignContent: "center",
147
- backgroundColor: "transparent",
148
- ...props.itemContainerStyle,
149
- paddingVertical: 0,
150
- height: props.itemHeight,
151
- }}
152
- >
153
- <Text style={{ textAlign: "center", ...props.itemTextStyle }}>
154
- {props.getLabel(item)}
155
- </Text>
156
- </View>
157
- );
158
- }
159
-
160
- function FrontGradient({ gradientFadeColor, borderRadius }: { gradientFadeColor: ColorValue, borderRadius: string | AnimatableNumericValue | undefined }) {
161
-
162
- return (
163
- <LinearGradient
164
- colors={[gradientFadeColor, "transparent", gradientFadeColor]}
165
- style={{
166
- height: "100%",
167
- width: "100%",
168
- backgroundColor: "transparent",
169
- borderRadius: borderRadius
170
- }}
171
- />
172
- );
173
- }
174
-
175
- function getOffsets(
176
- dataLength: number,
177
- itemDisplayCount: number,
178
- itemHeight: number,
179
- dataMultiplier: number
180
- ) {
181
- let offsets = [];
182
-
183
- // calculate offset for all items
184
- for (let i = 0; i < dataLength * dataMultiplier; i++) {
185
- offsets[i] = itemOffset(
186
- i,
187
- itemDisplayCount,
188
- itemHeight
189
- );
190
- }
191
-
192
- return offsets;
193
- }
194
-
195
- function itemOffset(
196
- index: number,
197
- itemDisplayCount: number,
198
- itemHeight: number
199
- ) {
200
-
201
- return (index + (itemDisplayCount % 2 === 0 ? 0.5 : 0)) * itemHeight;
202
- }
203
-
204
- function onMomentumScrollEnd<T>(
205
- offset: number,
206
- setCurrent: (n: number) => void,
207
- dataLength: number,
208
- itemHeight: number,
209
- dataMultiplier: number,
210
- indexDiffTopToCentered: number,
211
- verticalPadding: number,
212
- ref: RefObject<VirtualizedList<T> | null>
213
- ) {
214
- // offset excluding padding
215
- const innerOffset = offset - verticalPadding;
216
- // get index of top most completely visible item
217
- const currentTopIndex = Math.round(innerOffset / itemHeight);
218
-
219
- // get current section within whole extended data (data * dataMultiplier)
220
- // section 0 = [0, data.length)
221
- // section 1 = [data.length, data.length * 2)
222
- // ...
223
- const currentSection = Math.floor(innerOffset / (dataLength * itemHeight));
224
- // target section is always the middle one, so user can scroll seemingly infinitely
225
- const targetSection = Math.floor(dataMultiplier / 2);
226
-
227
- // get corresponding index of current top index in target section
228
- const targetTopIndex =
229
- currentTopIndex + (targetSection - currentSection) * dataLength;
230
- // set current index to centered one, if `targetTopIndex`was at the top
231
- setCurrent(targetTopIndex + indexDiffTopToCentered);
232
-
233
- if (currentSection === targetSection) {
234
- // if target section is current section, stay in this section
235
- return;
236
- }
237
-
238
- // if target section is different from current section, scroll to target
239
- const targetOffset = offset + (targetTopIndex - currentTopIndex) * itemHeight;
240
- ref.current?.scrollToOffset({ animated: false, offset: targetOffset });
241
- }
242
-
243
- // props
244
-
245
- function withDefaults<T>(
246
- props: RepeatingWheelPickerProps<T>
247
- ): RepeatingWheelPickerPropsWithDefaults<T> {
248
- const defaultBackgroundColor = "black";
249
- const defaultTextColor = "white";
250
- const defaultTextSize = 18;
251
-
252
- validateProps(props);
253
-
254
- return {
255
- ...props,
256
-
257
- // optional
258
- containerOnLayout: props.containerOnLayout ?? (() => {}),
259
- enabled: props.enabled ?? true,
260
-
261
- getLabel: props.getLabel ?? ((t: T) => `${t}`),
262
-
263
- itemHeight: props.itemHeight ?? (props.itemTextStyle?.fontSize ?? defaultTextSize) + 15,
264
- itemDisplayCount: props.itemDisplayCount ?? 3,
265
-
266
- containerVerticalPadding: props.containerVerticalPadding ?? 0,
267
- containerHorizontalPadding: props.containerHorizontalPadding ?? 10,
268
- containerStyle: {
269
- ...props.containerStyle,
270
- backgroundColor:
271
- props.containerStyle?.backgroundColor ?? defaultBackgroundColor,
272
- padding: 0,
273
- paddingHorizontal: 0,
274
- paddingVertical: 0,
275
- paddingTop: 0,
276
- paddingBottom: 0,
277
- paddingLeft: 0,
278
- paddingRight: 0
279
- },
280
- itemContainerStyle: {
281
- ...props.itemContainerStyle,
282
- backgroundColor:
283
- props.itemContainerStyle?.backgroundColor ?? "transparent",
284
- justifyContent: props.itemContainerStyle?.justifyContent ?? "center"
285
- },
286
- itemTextStyle: {
287
- ...props.itemTextStyle,
288
- fontSize: props.itemTextStyle?.fontSize ?? defaultTextSize,
289
- color: props.itemTextStyle?.color ?? defaultTextColor,
290
- },
291
-
292
- enableGradient: props.enableGradient ?? true,
293
- gradientFadeColor: props.gradientFadeColor ?? (props.containerStyle?.backgroundColor ?? defaultBackgroundColor)
294
- };
295
- }
296
-
297
- function validateProps<T>(props: RepeatingWheelPickerProps<T>) {
298
- if (props.initialIndex < 0 || props.initialIndex >= props.data.length) {
299
- throw InvalidPropertiesError(
300
- "initialIndex",
301
- String(props.initialIndex),
302
- "has to be in range [0, data.length)"
303
- );
304
- }
305
-
306
- if (props.data.length < 2) {
307
- throw InvalidPropertiesError(
308
- "data.length",
309
- String(props.data.length),
310
- "has to be larger than 1"
311
- );
312
- }
313
-
314
- if (props.itemDisplayCount !== undefined && props.itemDisplayCount < 1) {
315
- throw InvalidPropertiesError(
316
- "itemDisplayCount",
317
- String(props.itemDisplayCount),
318
- "has to be larger than 0"
319
- );
320
- }
321
- if (props.itemDisplayCount !== undefined && !Number.isInteger(props.itemDisplayCount)) {
322
- throw InvalidPropertiesError(
323
- "itemDisplayCount",
324
- String(props.itemDisplayCount),
325
- "has to be an integer"
326
- );
327
- }
328
-
329
- if (props.itemHeight !== undefined && props.itemHeight < 1) {
330
- throw InvalidPropertiesError(
331
- "itemHeight",
332
- String(props.itemHeight),
333
- "has to be larger than 0"
334
- );
335
- }
336
- }
337
-
338
- function InvalidPropertiesError(
339
- propertyName: string,
340
- propertyValue: string,
341
- violatedConstraint: string
342
- ) {
343
- return Error(
344
- `Value "${propertyValue}" is invalid for property "${propertyName}": ${violatedConstraint}`
345
- ) as InvalidPropertiesError;
346
- }
347
-
348
- interface InvalidPropertiesError extends Error {
349
- name: "InvalidPropertiesError";
350
- }
351
-
352
- type RepeatingWheelPickerPropsWithDefaults<T> = RepeatingWheelPickerProps<T> &
353
- Required<Omit<RepeatingWheelPickerProps<T>, "containerRef">>;
354
-
355
- /**
356
- *
357
- */
358
- export type RepeatingWheelPickerProps<T> = {
359
- /**
360
- * Function to set currently selected element and use it in your application.
361
- *
362
- * @example
363
- * ```ts
364
- * const [selected, setSelected] = useState(0);
365
- *
366
- * return (
367
- * <RepeatingWheelPicker
368
- * setSelected={setSelected}
369
- * //...
370
- * />
371
- * );
372
- * ```
373
- *
374
- * @param t currently selected element
375
- */
376
- setSelected: (t: T) => void;
377
- /**
378
- * Index to initially center.
379
- */
380
- initialIndex: number;
381
- /**
382
- * Data to display.
383
- */
384
- data: T[];
385
-
386
- /**
387
- * Function to retrieve the text to display for an element as a label.
388
- *
389
- * @defaultValue
390
- * ```ts
391
- * (t: T) => `${t}`
392
- * ```
393
- *
394
- * @param t element to retrieve label for
395
- */
396
- getLabel?: (t: T) => string;
397
- /**
398
- * Function called when the layout of the container changes.
399
- *
400
- * _Example usage for monitoring the container's height:_
401
- * ```ts
402
- * const [pickerHeight, setPickerHeight] = useState<number>(0);
403
- *
404
- * const onLayout = useCallback((event: LayoutChangeEvent) => {
405
- * const { height } = event.nativeEvent.layout;
406
- * setPickerHeight(height);
407
- * }, []);
408
- *
409
- * return (
410
- * <View style={{flexDirection: "row"}}>
411
- * <View style={{height: height}}>
412
- * <Text>Picker label</Text>
413
- * </View>
414
- * <RepeatingWheelPicker
415
- * //...
416
- * containerOnLayout={onLayout}
417
- * />
418
- * </View>
419
- * );
420
- * ```
421
- *
422
- * @defaultValue () => {}
423
- *
424
- * @param event layout change event that triggered `onLayout`
425
- */
426
- containerOnLayout?: (event: LayoutChangeEvent) => void;
427
- /**
428
- * Enables / disables scrolling of the wheel picker.
429
- *
430
- * @defaultValue true
431
- */
432
- enabled?: boolean;
433
-
434
- /**
435
- * Height per displayed item.
436
- *
437
- * @defaultValue itemTextStyle.fontSize + 15
438
- */
439
- itemHeight?: number;
440
- /**
441
- * Number of items to display.
442
- *
443
- * @defaultValue 3
444
- */
445
- itemDisplayCount?: number;
446
-
447
- /**
448
- * Vertical padding for the container of the wheel picker.
449
- *
450
- * @defaultValue 0
451
- */
452
- containerVerticalPadding?: number;
453
- /**
454
- * Horizontal padding for the container of the wheel picker.
455
- *
456
- * @defaultValue 10
457
- */
458
- containerHorizontalPadding?: number;
459
- /**
460
- * Styling for the container of the wheel picker.
461
- *
462
- * @defaultValue
463
- * ```ts
464
- * {
465
- * backgroundColor: "black"
466
- * }
467
- * ```
468
- */
469
- containerStyle?: ViewStyle;
470
- /**
471
- * Styling for the container of each element.
472
- *
473
- * @defaultValue
474
- * ```ts
475
- * {
476
- * backgroundColor: "transparent",
477
- * justifyContent: "center"
478
- * }
479
- * ```
480
- */
481
- itemContainerStyle?: ViewStyle;
482
- /**
483
- * Styling for the text of the elements.
484
- *
485
- * @defaultValue
486
- * ```ts
487
- * {
488
- * fontSize: "18",
489
- * color: "white"
490
- * }
491
- * ```
492
- */
493
- itemTextStyle?: TextStyle;
494
-
495
- /**
496
- * If enabled, will show a gradient fade towards the top and bottom of the wheel picker.
497
- *
498
- * @defaultValue true
499
- */
500
- enableGradient?: boolean;
501
- /**
502
- * Color the gradient should fade to at the top and bottom.
503
- *
504
- * @defaultValue containerStyle.backgroundColor
505
- */
506
- gradientFadeColor?: ColorValue;
507
- };