react-native-ruler-date-picker 0.1.0 → 0.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 (220) hide show
  1. package/README.md +186 -60
  2. package/lib/commonjs/LensTick.js +83 -0
  3. package/lib/commonjs/LensTick.js.map +1 -0
  4. package/lib/commonjs/Ruler.js +38 -0
  5. package/lib/commonjs/Ruler.js.map +1 -0
  6. package/lib/commonjs/RulerContext.js +17 -0
  7. package/lib/commonjs/RulerContext.js.map +1 -0
  8. package/lib/commonjs/RulerDatePicker.js +38 -351
  9. package/lib/commonjs/RulerDatePicker.js.map +1 -1
  10. package/lib/commonjs/RulerDateRangePicker.js +56 -0
  11. package/lib/commonjs/RulerDateRangePicker.js.map +1 -0
  12. package/lib/commonjs/RulerHeader.js +106 -0
  13. package/lib/commonjs/RulerHeader.js.map +1 -0
  14. package/lib/commonjs/RulerIndicator.js +67 -0
  15. package/lib/commonjs/RulerIndicator.js.map +1 -0
  16. package/lib/commonjs/RulerLensTicks.js +55 -0
  17. package/lib/commonjs/RulerLensTicks.js.map +1 -0
  18. package/lib/commonjs/RulerLensTrack.js +52 -0
  19. package/lib/commonjs/RulerLensTrack.js.map +1 -0
  20. package/lib/commonjs/RulerRange.js +39 -0
  21. package/lib/commonjs/RulerRange.js.map +1 -0
  22. package/lib/commonjs/RulerRangeContext.js +17 -0
  23. package/lib/commonjs/RulerRangeContext.js.map +1 -0
  24. package/lib/commonjs/RulerRangeHeader.js +154 -0
  25. package/lib/commonjs/RulerRangeHeader.js.map +1 -0
  26. package/lib/commonjs/RulerRangeHighlight.js +50 -0
  27. package/lib/commonjs/RulerRangeHighlight.js.map +1 -0
  28. package/lib/commonjs/RulerRangeIndicator.js +71 -0
  29. package/lib/commonjs/RulerRangeIndicator.js.map +1 -0
  30. package/lib/commonjs/RulerRangeRoot.js +80 -0
  31. package/lib/commonjs/RulerRangeRoot.js.map +1 -0
  32. package/lib/commonjs/RulerRangeTicks.js +57 -0
  33. package/lib/commonjs/RulerRangeTicks.js.map +1 -0
  34. package/lib/commonjs/RulerRangeTrack.js +46 -0
  35. package/lib/commonjs/RulerRangeTrack.js.map +1 -0
  36. package/lib/commonjs/RulerResetButton.js +46 -0
  37. package/lib/commonjs/RulerResetButton.js.map +1 -0
  38. package/lib/commonjs/RulerRoot.js +87 -0
  39. package/lib/commonjs/RulerRoot.js.map +1 -0
  40. package/lib/commonjs/RulerTicks.js +51 -0
  41. package/lib/commonjs/RulerTicks.js.map +1 -0
  42. package/lib/commonjs/RulerTrack.js +46 -0
  43. package/lib/commonjs/RulerTrack.js.map +1 -0
  44. package/lib/commonjs/Tick.js +41 -36
  45. package/lib/commonjs/Tick.js.map +1 -1
  46. package/lib/commonjs/defaults.js +20 -19
  47. package/lib/commonjs/defaults.js.map +1 -1
  48. package/lib/commonjs/index.js +287 -1
  49. package/lib/commonjs/index.js.map +1 -1
  50. package/lib/commonjs/presets.js +108 -0
  51. package/lib/commonjs/presets.js.map +1 -0
  52. package/lib/commonjs/tickResolver.js +101 -0
  53. package/lib/commonjs/tickResolver.js.map +1 -0
  54. package/lib/commonjs/useHaptics.js +1 -1
  55. package/lib/commonjs/useHaptics.web.js +43 -0
  56. package/lib/commonjs/useHaptics.web.js.map +1 -0
  57. package/lib/commonjs/useRulerDatePicker.js +264 -0
  58. package/lib/commonjs/useRulerDatePicker.js.map +1 -0
  59. package/lib/commonjs/useRulerDateRangePicker.js +313 -0
  60. package/lib/commonjs/useRulerDateRangePicker.js.map +1 -0
  61. package/lib/commonjs/utils.js +61 -47
  62. package/lib/commonjs/utils.js.map +1 -1
  63. package/lib/module/LensTick.js +77 -0
  64. package/lib/module/LensTick.js.map +1 -0
  65. package/lib/module/Ruler.js +35 -0
  66. package/lib/module/Ruler.js.map +1 -0
  67. package/lib/module/RulerContext.js +12 -0
  68. package/lib/module/RulerContext.js.map +1 -0
  69. package/lib/module/RulerDatePicker.js +38 -350
  70. package/lib/module/RulerDatePicker.js.map +1 -1
  71. package/lib/module/RulerDateRangePicker.js +52 -0
  72. package/lib/module/RulerDateRangePicker.js.map +1 -0
  73. package/lib/module/RulerHeader.js +101 -0
  74. package/lib/module/RulerHeader.js.map +1 -0
  75. package/lib/module/RulerIndicator.js +62 -0
  76. package/lib/module/RulerIndicator.js.map +1 -0
  77. package/lib/module/RulerLensTicks.js +50 -0
  78. package/lib/module/RulerLensTicks.js.map +1 -0
  79. package/lib/module/RulerLensTrack.js +47 -0
  80. package/lib/module/RulerLensTrack.js.map +1 -0
  81. package/lib/module/RulerRange.js +36 -0
  82. package/lib/module/RulerRange.js.map +1 -0
  83. package/lib/module/RulerRangeContext.js +12 -0
  84. package/lib/module/RulerRangeContext.js.map +1 -0
  85. package/lib/module/RulerRangeHeader.js +149 -0
  86. package/lib/module/RulerRangeHeader.js.map +1 -0
  87. package/lib/module/RulerRangeHighlight.js +45 -0
  88. package/lib/module/RulerRangeHighlight.js.map +1 -0
  89. package/lib/module/RulerRangeIndicator.js +66 -0
  90. package/lib/module/RulerRangeIndicator.js.map +1 -0
  91. package/lib/module/RulerRangeRoot.js +75 -0
  92. package/lib/module/RulerRangeRoot.js.map +1 -0
  93. package/lib/module/RulerRangeTicks.js +51 -0
  94. package/lib/module/RulerRangeTicks.js.map +1 -0
  95. package/lib/module/RulerRangeTrack.js +41 -0
  96. package/lib/module/RulerRangeTrack.js.map +1 -0
  97. package/lib/module/RulerResetButton.js +41 -0
  98. package/lib/module/RulerResetButton.js.map +1 -0
  99. package/lib/module/RulerRoot.js +82 -0
  100. package/lib/module/RulerRoot.js.map +1 -0
  101. package/lib/module/RulerTicks.js +45 -0
  102. package/lib/module/RulerTicks.js.map +1 -0
  103. package/lib/module/RulerTrack.js +41 -0
  104. package/lib/module/RulerTrack.js.map +1 -0
  105. package/lib/module/Tick.js +41 -36
  106. package/lib/module/Tick.js.map +1 -1
  107. package/lib/module/defaults.js +19 -18
  108. package/lib/module/defaults.js.map +1 -1
  109. package/lib/module/index.js +46 -1
  110. package/lib/module/index.js.map +1 -1
  111. package/lib/module/presets.js +103 -0
  112. package/lib/module/presets.js.map +1 -0
  113. package/lib/module/tickResolver.js +97 -0
  114. package/lib/module/tickResolver.js.map +1 -0
  115. package/lib/module/useHaptics.js +1 -1
  116. package/lib/module/useHaptics.js.map +1 -1
  117. package/lib/module/useHaptics.web.js +39 -0
  118. package/lib/module/useHaptics.web.js.map +1 -0
  119. package/lib/module/useRulerDatePicker.js +260 -0
  120. package/lib/module/useRulerDatePicker.js.map +1 -0
  121. package/lib/module/useRulerDateRangePicker.js +310 -0
  122. package/lib/module/useRulerDateRangePicker.js.map +1 -0
  123. package/lib/module/utils.js +59 -45
  124. package/lib/module/utils.js.map +1 -1
  125. package/lib/typescript/LensTick.d.ts +20 -0
  126. package/lib/typescript/LensTick.d.ts.map +1 -0
  127. package/lib/typescript/Ruler.d.ts +31 -0
  128. package/lib/typescript/Ruler.d.ts.map +1 -0
  129. package/lib/typescript/RulerContext.d.ts +11 -0
  130. package/lib/typescript/RulerContext.d.ts.map +1 -0
  131. package/lib/typescript/RulerDatePicker.d.ts +10 -7
  132. package/lib/typescript/RulerDatePicker.d.ts.map +1 -1
  133. package/lib/typescript/RulerDateRangePicker.d.ts +26 -0
  134. package/lib/typescript/RulerDateRangePicker.d.ts.map +1 -0
  135. package/lib/typescript/RulerHeader.d.ts +14 -0
  136. package/lib/typescript/RulerHeader.d.ts.map +1 -0
  137. package/lib/typescript/RulerIndicator.d.ts +17 -0
  138. package/lib/typescript/RulerIndicator.d.ts.map +1 -0
  139. package/lib/typescript/RulerLensTicks.d.ts +12 -0
  140. package/lib/typescript/RulerLensTicks.d.ts.map +1 -0
  141. package/lib/typescript/RulerLensTrack.d.ts +13 -0
  142. package/lib/typescript/RulerLensTrack.d.ts.map +1 -0
  143. package/lib/typescript/RulerRange.d.ts +32 -0
  144. package/lib/typescript/RulerRange.d.ts.map +1 -0
  145. package/lib/typescript/RulerRangeContext.d.ts +11 -0
  146. package/lib/typescript/RulerRangeContext.d.ts.map +1 -0
  147. package/lib/typescript/RulerRangeHeader.d.ts +12 -0
  148. package/lib/typescript/RulerRangeHeader.d.ts.map +1 -0
  149. package/lib/typescript/RulerRangeHighlight.d.ts +8 -0
  150. package/lib/typescript/RulerRangeHighlight.d.ts.map +1 -0
  151. package/lib/typescript/RulerRangeIndicator.d.ts +17 -0
  152. package/lib/typescript/RulerRangeIndicator.d.ts.map +1 -0
  153. package/lib/typescript/RulerRangeRoot.d.ts +7 -0
  154. package/lib/typescript/RulerRangeRoot.d.ts.map +1 -0
  155. package/lib/typescript/RulerRangeTicks.d.ts +14 -0
  156. package/lib/typescript/RulerRangeTicks.d.ts.map +1 -0
  157. package/lib/typescript/RulerRangeTrack.d.ts +8 -0
  158. package/lib/typescript/RulerRangeTrack.d.ts.map +1 -0
  159. package/lib/typescript/RulerResetButton.d.ts +10 -0
  160. package/lib/typescript/RulerResetButton.d.ts.map +1 -0
  161. package/lib/typescript/RulerRoot.d.ts +7 -0
  162. package/lib/typescript/RulerRoot.d.ts.map +1 -0
  163. package/lib/typescript/RulerTicks.d.ts +9 -0
  164. package/lib/typescript/RulerTicks.d.ts.map +1 -0
  165. package/lib/typescript/RulerTrack.d.ts +8 -0
  166. package/lib/typescript/RulerTrack.d.ts.map +1 -0
  167. package/lib/typescript/Tick.d.ts +3 -16
  168. package/lib/typescript/Tick.d.ts.map +1 -1
  169. package/lib/typescript/defaults.d.ts +6 -9
  170. package/lib/typescript/defaults.d.ts.map +1 -1
  171. package/lib/typescript/index.d.ts +37 -1
  172. package/lib/typescript/index.d.ts.map +1 -1
  173. package/lib/typescript/presets.d.ts +27 -0
  174. package/lib/typescript/presets.d.ts.map +1 -0
  175. package/lib/typescript/tickResolver.d.ts +10 -0
  176. package/lib/typescript/tickResolver.d.ts.map +1 -0
  177. package/lib/typescript/types.d.ts +302 -85
  178. package/lib/typescript/types.d.ts.map +1 -1
  179. package/lib/typescript/useHaptics.web.d.ts +17 -0
  180. package/lib/typescript/useHaptics.web.d.ts.map +1 -0
  181. package/lib/typescript/useRulerDatePicker.d.ts +26 -0
  182. package/lib/typescript/useRulerDatePicker.d.ts.map +1 -0
  183. package/lib/typescript/useRulerDateRangePicker.d.ts +40 -0
  184. package/lib/typescript/useRulerDateRangePicker.d.ts.map +1 -0
  185. package/lib/typescript/utils.d.ts +14 -12
  186. package/lib/typescript/utils.d.ts.map +1 -1
  187. package/package.json +25 -7
  188. package/src/LensTick.tsx +90 -0
  189. package/src/Ruler.ts +32 -0
  190. package/src/RulerContext.tsx +20 -0
  191. package/src/RulerDatePicker.tsx +41 -439
  192. package/src/RulerDateRangePicker.tsx +53 -0
  193. package/src/RulerHeader.tsx +125 -0
  194. package/src/RulerIndicator.tsx +84 -0
  195. package/src/RulerLensTicks.tsx +50 -0
  196. package/src/RulerLensTrack.tsx +45 -0
  197. package/src/RulerRange.ts +33 -0
  198. package/src/RulerRangeContext.tsx +20 -0
  199. package/src/RulerRangeHeader.tsx +180 -0
  200. package/src/RulerRangeHighlight.tsx +47 -0
  201. package/src/RulerRangeIndicator.tsx +85 -0
  202. package/src/RulerRangeRoot.tsx +87 -0
  203. package/src/RulerRangeTicks.tsx +68 -0
  204. package/src/RulerRangeTrack.tsx +39 -0
  205. package/src/RulerResetButton.tsx +59 -0
  206. package/src/RulerRoot.tsx +93 -0
  207. package/src/RulerTicks.tsx +57 -0
  208. package/src/RulerTrack.tsx +39 -0
  209. package/src/Tick.tsx +60 -49
  210. package/src/defaults.ts +21 -19
  211. package/src/index.ts +83 -1
  212. package/src/presets.ts +108 -0
  213. package/src/tickResolver.ts +123 -0
  214. package/src/types.ts +354 -102
  215. package/src/useHaptics.web.ts +55 -0
  216. package/src/useRulerDatePicker.ts +373 -0
  217. package/src/useRulerDateRangePicker.ts +468 -0
  218. package/src/utils.ts +67 -68
  219. package/lib/commonjs/package.json +0 -1
  220. package/lib/module/package.json +0 -1
package/README.md CHANGED
@@ -1,17 +1,26 @@
1
- # react-native-ruler-date-picker
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/md-rehman/react-native-ruler-date-picker/dev/apps/docs/public/logo.svg" width="96" height="96" alt="react-native-ruler-date-picker logo" />
3
+ </p>
2
4
 
3
- A performant, customizable ruler-style date picker for React Native.
5
+ <h1 align="center">react-native-ruler-date-picker</h1>
4
6
 
5
- <!-- TODO: Add hero GIF/video here -->
7
+ <p align="center">
8
+ A performant, customizable horizontal ruler date picker & scroll wheel for React Native and Expo. Powered by 60 FPS Reanimated 3 physics and dual-speed haptic feedback.
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://github.com/md-rehman/react-native-ruler-date-picker"><strong>Documentation & Interactive Demos »</strong></a>
13
+ </p>
6
14
 
7
15
  ## ✨ Features
8
16
 
9
17
  - **60 FPS Physics** — Reanimated 3 decay animations with snap-to-tick alignment
10
18
  - **Dual-Speed Haptics** — Discrete ticks at slow scroll, continuous buzz at fast swipe
11
19
  - **Windowed Rendering** — Only renders visible ticks + buffer for memory efficiency
12
- - **Fully Customizable** — Every dimension, color, and behavior is configurable via props
13
- - **Graceful Haptics** — Works with `expo-haptics`, custom handlers, or silently without either
14
- - **Dark Mode Support** — Auto-detects system color scheme with manual override
20
+ - **Multi-Tier Rule-Based Graduations** — Declarative tick rules (`ticks="calendar"` | `"metric"` | `"minimal"` or custom rules array)
21
+ - **Compound Anatomy API** — Full layout flexibility with `Ruler.*` and `RulerRange.*`
22
+ - **Date Range Selection [Experimental]** — Dual-handle date range picker with `RulerDateRangePicker`
23
+ - **Dark Mode Support** — Auto-detects system color scheme with custom theme palette override
15
24
 
16
25
  ## 📦 Installation
17
26
 
@@ -37,88 +46,205 @@ Optional (for haptic feedback):
37
46
  npx expo install expo-haptics
38
47
  ```
39
48
 
49
+ ### Configure Peer Dependencies
50
+
51
+ #### 1. Babel Configuration
52
+ For bare React Native CLI apps, add the Reanimated Babel plugin to your `babel.config.js` as the **very last** plugin:
53
+
54
+ ```javascript
55
+ module.exports = {
56
+ presets: ['module:@react-native/babel-preset'],
57
+ plugins: [
58
+ 'react-native-reanimated/plugin', // MUST be last plugin
59
+ ],
60
+ };
61
+ ```
62
+
63
+ > **Note for Expo (SDK 50+)**: In managed Expo workflows using `babel-preset-expo`, the Reanimated Babel plugin is included automatically.
64
+
65
+ #### 2. GestureHandlerRootView
66
+ Wrap your application root component with `GestureHandlerRootView` so gestures and pan physics function properly:
67
+
68
+ ```tsx
69
+ import React from 'react';
70
+ import { GestureHandlerRootView } from 'react-native-gesture-handler';
71
+ import MainScreen from './MainScreen';
72
+
73
+ export default function App() {
74
+ return (
75
+ <GestureHandlerRootView style={{ flex: 1 }}>
76
+ <MainScreen />
77
+ </GestureHandlerRootView>
78
+ );
79
+ }
80
+ ```
81
+
82
+ > If using **Expo Router**, wrap your root layout in `app/_layout.tsx`.
83
+
40
84
  ## 🚀 Quick Start
41
85
 
42
86
  ```tsx
87
+ import React, { useState } from 'react';
88
+ import { View, Text, StyleSheet } from 'react-native';
43
89
  import { RulerDatePicker } from 'react-native-ruler-date-picker';
44
90
 
45
91
  export default function App() {
46
92
  const [date, setDate] = useState(new Date());
47
93
 
48
94
  return (
49
- <RulerDatePicker
50
- selectedDate={date}
51
- onSelectDate={(newDate, dateString) => {
52
- setDate(newDate);
53
- console.log('Selected:', dateString); // "2026-08-07"
54
- }}
55
- />
95
+ <View style={styles.container}>
96
+ <Text style={styles.label}>
97
+ Selected: {date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}
98
+ </Text>
99
+
100
+ <RulerDatePicker
101
+ value={date}
102
+ onChange={(newDate, dateString) => {
103
+ setDate(newDate);
104
+ console.log('Selected Date:', dateString); // "YYYY-MM-DD"
105
+ }}
106
+ ticks="calendar"
107
+ header={{ showResetToToday: true }}
108
+ />
109
+ </View>
56
110
  );
57
111
  }
112
+
113
+ const styles = StyleSheet.create({
114
+ container: {
115
+ flex: 1,
116
+ justifyContent: 'center',
117
+ alignItems: 'center',
118
+ backgroundColor: '#0F172A',
119
+ },
120
+ label: {
121
+ color: '#F8FAFC',
122
+ fontSize: 16,
123
+ fontWeight: '600',
124
+ marginBottom: 24,
125
+ },
126
+ });
58
127
  ```
59
128
 
129
+ ## 📅 Date Range Selection [Experimental]
130
+
131
+ Select a range with start and end handles using `RulerDateRangePicker`:
132
+
133
+ ```tsx
134
+ import React, { useState } from 'react';
135
+ import { View, StyleSheet } from 'react-native';
136
+ import { RulerDateRangePicker, DateRange } from 'react-native-ruler-date-picker';
137
+
138
+ export default function RangeBookingScreen() {
139
+ const [range, setRange] = useState<DateRange>({
140
+ start: new Date(),
141
+ end: new Date(Date.now() + 5 * 86400000), // +5 days
142
+ });
143
+
144
+ return (
145
+ <View style={styles.container}>
146
+ <RulerDateRangePicker
147
+ value={range}
148
+ onChange={({ startDate, endDate, dateRange }) => {
149
+ setRange(dateRange);
150
+ console.log('Selected range:', startDate, '→', endDate);
151
+ }}
152
+ minSpanDays={1}
153
+ maxSpanDays={30}
154
+ />
155
+ </View>
156
+ );
157
+ }
158
+
159
+ const styles = StyleSheet.create({
160
+ container: {
161
+ flex: 1,
162
+ justifyContent: 'center',
163
+ alignItems: 'center',
164
+ backgroundColor: '#0F172A',
165
+ },
166
+ });
167
+ ```
168
+
169
+ ## 🧩 Compound Anatomy API
170
+
171
+ For full layout flexibility, compose custom pickers with `Ruler.*`:
172
+
173
+ ```tsx
174
+ import React, { useState } from 'react';
175
+ import { View } from 'react-native';
176
+ import { Ruler } from 'react-native-ruler-date-picker';
177
+
178
+ export default function CustomAnatomy() {
179
+ const [date, setDate] = useState(new Date());
180
+
181
+ return (
182
+ <Ruler.Root value={date} onChange={setDate} tickSpacing={28}>
183
+ {/* 1. Header with custom placement */}
184
+ <Ruler.Header showResetToToday={false} />
185
+
186
+ {/* 2. Scroll arena containing needle & graduation ticks */}
187
+ <Ruler.Track>
188
+ <Ruler.Indicator />
189
+ <Ruler.Ticks />
190
+ </Ruler.Track>
191
+
192
+ {/* 3. Standalone Reset button */}
193
+ <View style={{ alignItems: 'center', marginTop: 12 }}>
194
+ <Ruler.ResetButton label="Jump to Today" />
195
+ </View>
196
+ </Ruler.Root>
197
+ );
198
+ }
199
+ ```
200
+
201
+ For range pickers, use `RulerRange.*` (`RulerRange.Root`, `RulerRange.Header`, `RulerRange.Track`, `RulerRange.Ticks`, and `RulerRange.Indicator`).
202
+
60
203
  ## 📐 API Reference
61
204
 
62
205
  ### Props
63
206
 
64
207
  | Prop | Type | Default | Description |
65
208
  |---|---|---|---|
66
- | `selectedDate` | `Date \| string` | **required** | Currently selected date |
67
- | `onSelectDate` | `(date: Date, dateString: string) => void` | **required** | Called when date changes |
68
- | `minDate` | `Date` | -365 days | Minimum scrollable date |
69
- | `maxDate` | `Date` | +365 days | Maximum scrollable date |
70
- | `labelInterval` | `'daily' \| 'weekly' \| 'monthly' \| (date: Date) => boolean` | `'weekly'` | Which ticks show labels |
71
- | `highlightDays` | `number[]` | — | Days of week to highlight (0=Sun, 6=Sat) |
72
- | `tickSpacing` | `number` | `24` | Gap between ticks (px) |
73
- | `tickHeight` | `number` | `12` | Small tick height (px) |
74
- | `tickTallHeight` | `number` | `24` | Large/labeled tick height (px) |
75
- | `tickThickness` | `number` | `4` | Tick bar width (px) |
76
- | `tickColor` | `string` | auto | Small tick color |
77
- | `tickTallColor` | `string` | auto | Large tick color (falls back to `tickColor`) |
78
- | `labelColor` | `string` | auto | Label text color |
79
- | `accentColor` | `string` | auto | Today dot & reset button color |
80
- | `indicatorColor` | `string` | auto | Center indicator line color |
81
- | `backgroundColor` | `string` | `transparent` | Component background |
82
- | `height` | `number` | `120` | Total component height (px) |
83
- | `rulerHeight` | `number` | `60` | Ruler track height (px) |
84
- | `indicatorWidth` | `number` | `2` | Center indicator width (px) |
85
- | `indicatorHeight` | `number` | `40` | Center indicator height (px) |
86
- | `todayDotSize` | `number` | `6` | Today dot diameter (px) |
87
- | `labelFontSize` | `number` | `10` | Tick label font size (px) |
88
- | `bufferTicks` | `number` | `10` | Off-screen render buffer |
89
- | `updateDebounceMs` | `number` | `100` | Debounce for `onSelectDate` (ms) |
90
- | `enableHaptics` | `boolean` | `true` | Enable/disable haptic feedback |
91
- | `onHapticTrigger` | `(mode: 'tick' \| 'continuous') => void` | — | Custom haptic handler |
92
- | `fastSwipeTickThreshold` | `number` | `1` | Ticks/frame to trigger fast mode |
93
- | `continuousHapticIntervalMs` | `number` | `20` | Continuous haptic pulse interval (ms) |
94
- | `showResetToToday` | `boolean` | `false` | Show "Today" reset button |
95
- | `renderHeader` | `(date, isToday, resetFn) => ReactNode` | — | Custom header renderer |
209
+ | `value` | `Date \| string` | `new Date() (Today)` | Currently selected date (controlled). Accepts Date or "YYYY-MM-DD". |
210
+ | `defaultValue` | `Date \| string` | `new Date() (Today)` | Initial selected date for uncontrolled mode. |
211
+ | `onChange` | `(date: Date, dateString: string) => void` | `undefined` | Called when scrolling stops and snaps to a date. |
212
+ | `minDate` | `Date \| string` | `Today - 365 days` | Minimum selectable date boundary. |
213
+ | `maxDate` | `Date \| string` | `Today + 365 days` | Maximum selectable date boundary. |
214
+ | `locale` | `string` | `'default'` | BCP 47 locale tag (e.g. "en-US", "de-DE", "ja-JP") for date formatting. |
215
+ | `ticks` | `TickRule[] \| 'calendar' \| 'metric' \| 'minimal'` | `'calendar'` | Graduation rules array or preset name. |
216
+ | `tickSpacing` | `number` | `24` | Gap in pixels between consecutive tick graduation marks. |
217
+ | `tickWidth` | `number` | `3` | Base thickness in pixels for tick graduation bars. |
218
+ | `width` | `number` | `window width` | Viewport track width in pixels. Defaults to device window width. |
219
+ | `rulerHeight` | `number` | `60` | Height in pixels of the interactive ruler tick viewport track. |
220
+ | `header` | `boolean \| HeaderConfig` | `true` | Top date header display, config options, or custom renderer. |
221
+ | `indicator` | `boolean \| IndicatorConfig` | `true` | Center needle indicator display, dimensions, or custom renderer. |
222
+ | `haptics` | `boolean \| HapticConfig` | `true` | Dual-speed tactile vibration toggle or custom trigger callback. |
223
+ | `lensEffect` | `boolean \| LensConfig` | `false` | Optical fisheye lens distortion magnifying center spacing. |
224
+ | `theme` | `RulerTheme` | `auto (system)` | Color theme tokens overriding default Light/Dark color scheme. |
225
+ | `style` | `StyleProp<ViewStyle>` | `undefined` | Container view style applied to outer root component. |
226
+ | `debounceMs` | `number` | `100` | Debounce duration in milliseconds for `onChange` during fast scroll. |
227
+ | `testID` | `string` | `undefined` | Identifier for automated testing and inspection. |
228
+ | `accessibilityLabel` | `string` | `'Date picker'` | Screen reader accessibility label for assistive technologies. |
96
229
 
97
230
  ## 🎨 Theming
98
231
 
99
- Colors auto-detect the system color scheme. Override any color individually:
232
+ Colors auto-detect system light/dark mode. Provide custom tokens using `theme`:
100
233
 
101
234
  ```tsx
102
235
  <RulerDatePicker
103
- selectedDate={new Date()}
104
- onSelectDate={handleSelect}
105
- tickColor="#E5E7EB"
106
- tickTallColor="#6366F1"
107
- accentColor="#8B5CF6"
108
- indicatorColor="#8B5CF6"
109
- labelColor="#A1A1AA"
110
- backgroundColor="#18181B"
236
+ value={date}
237
+ onChange={setDate}
238
+ theme={{
239
+ background: '#0F172A',
240
+ indicatorColor: '#38BDF8',
241
+ accentColor: '#38BDF8',
242
+ labelColor: '#F8FAFC',
243
+ defaultTickColor: '#334155',
244
+ }}
111
245
  />
112
246
  ```
113
247
 
114
- ## 🤝 Contributing
115
-
116
- See the [ROADMAP](./ROADMAP.md) for planned features and development phases.
117
-
118
- 1. Clone the repo
119
- 2. Install dependencies: `pnpm install`
120
- 3. Start the example app: `pnpm dev`
121
-
122
248
  ## 📄 License
123
249
 
124
250
  MIT © [Rehman](https://md-rehman.dev)
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.LensTick = LensTick;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
10
+ var _RulerContext = require("./RulerContext.js");
11
+ var _Tick = require("./Tick.js");
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
14
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
+ /**
16
+ * Animated tick item with non-linear hyperbolic-tangent spatial distortion.
17
+ * Tick spacing smoothly magnifies near the center needle and asymptotically
18
+ * flattens out to standard spacing away from the center.
19
+ */
20
+ function LensTick({
21
+ tick,
22
+ tickSpacing,
23
+ rulerHeight,
24
+ translateX,
25
+ magnification,
26
+ radius,
27
+ scaleTicks,
28
+ containerWidth
29
+ }) {
30
+ const {
31
+ width: contextWidth
32
+ } = (0, _RulerContext.useRulerContext)();
33
+ const width = containerWidth ?? contextWidth;
34
+ const animatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => {
35
+ 'worklet';
36
+
37
+ const d = tick.offset * tickSpacing + translateX.value;
38
+ const A = (magnification - 1) * radius;
39
+ const warpedX = d + A * Math.tanh(d / radius);
40
+ if (!scaleTicks) {
41
+ return {
42
+ transform: [{
43
+ translateX: warpedX
44
+ }]
45
+ };
46
+ }
47
+ const dist = Math.abs(d);
48
+ const radiusLimit = radius * 1.5;
49
+ const factor = dist < radiusLimit ? 1 - dist / radiusLimit : 0;
50
+ const scale = 1 + (magnification - 1) * 0.25 * factor;
51
+ return {
52
+ transform: [{
53
+ translateX: warpedX
54
+ }, {
55
+ scale: scale
56
+ }]
57
+ };
58
+ }, [tick.offset, tickSpacing, translateX, magnification, radius, scaleTicks]);
59
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
60
+ style: [styles.lensTickWrapper, {
61
+ height: rulerHeight,
62
+ left: width / 2
63
+ }, animatedStyle],
64
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tick.Tick, {
65
+ tick: {
66
+ ...tick,
67
+ offset: 0
68
+ },
69
+ tickSpacing: tickSpacing,
70
+ rulerHeight: rulerHeight
71
+ })
72
+ });
73
+ }
74
+ const styles = _reactNative.StyleSheet.create({
75
+ lensTickWrapper: {
76
+ position: 'absolute',
77
+ height: '100%',
78
+ width: 0,
79
+ justifyContent: 'flex-end',
80
+ alignItems: 'center'
81
+ }
82
+ });
83
+ //# sourceMappingURL=LensTick.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_react","_interopRequireDefault","require","_reactNative","_reactNativeReanimated","_interopRequireWildcard","_RulerContext","_Tick","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","LensTick","tick","tickSpacing","rulerHeight","translateX","magnification","radius","scaleTicks","containerWidth","width","contextWidth","useRulerContext","animatedStyle","useAnimatedStyle","d","offset","value","A","warpedX","Math","tanh","transform","dist","abs","radiusLimit","factor","scale","jsx","View","style","styles","lensTickWrapper","height","left","children","Tick","StyleSheet","create","position","justifyContent","alignItems"],"sourceRoot":"../../src","sources":["LensTick.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Ruler = void 0;
7
+ var _RulerRoot = require("./RulerRoot.js");
8
+ var _RulerTrack = require("./RulerTrack.js");
9
+ var _RulerIndicator = require("./RulerIndicator.js");
10
+ var _RulerTicks = require("./RulerTicks.js");
11
+ var _Tick = require("./Tick.js");
12
+ var _RulerHeader = require("./RulerHeader.js");
13
+ var _RulerResetButton = require("./RulerResetButton.js");
14
+ var _RulerLensTrack = require("./RulerLensTrack.js");
15
+ var _RulerLensTicks = require("./RulerLensTicks.js");
16
+ /**
17
+ * Compound Anatomy API for the Ruler Date Picker.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * <Ruler.Root value={selectedDate} onChange={setSelectedDate}>
22
+ * <Ruler.Header />
23
+ * <Ruler.LensTrack />
24
+ * </Ruler.Root>
25
+ * ```
26
+ */
27
+ const Ruler = exports.Ruler = {
28
+ Root: _RulerRoot.RulerRoot,
29
+ Track: _RulerTrack.RulerTrack,
30
+ LensTrack: _RulerLensTrack.RulerLensTrack,
31
+ Ticks: _RulerTicks.RulerTicks,
32
+ LensTicks: _RulerLensTicks.RulerLensTicks,
33
+ Indicator: _RulerIndicator.RulerIndicator,
34
+ Tick: _Tick.Tick,
35
+ Header: _RulerHeader.RulerHeader,
36
+ ResetButton: _RulerResetButton.RulerResetButton
37
+ };
38
+ //# sourceMappingURL=Ruler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_RulerRoot","require","_RulerTrack","_RulerIndicator","_RulerTicks","_Tick","_RulerHeader","_RulerResetButton","_RulerLensTrack","_RulerLensTicks","Ruler","exports","Root","RulerRoot","Track","RulerTrack","LensTrack","RulerLensTrack","Ticks","RulerTicks","LensTicks","RulerLensTicks","Indicator","RulerIndicator","Tick","Header","RulerHeader","ResetButton","RulerResetButton"],"sourceRoot":"../../src","sources":["Ruler.ts"],"mappings":";;;;;;AAAA,IAAAA,UAAA,GAAAC,OAAA;AACA,IAAAC,WAAA,GAAAD,OAAA;AACA,IAAAE,eAAA,GAAAF,OAAA;AACA,IAAAG,WAAA,GAAAH,OAAA;AACA,IAAAI,KAAA,GAAAJ,OAAA;AACA,IAAAK,YAAA,GAAAL,OAAA;AACA,IAAAM,iBAAA,GAAAN,OAAA;AACA,IAAAO,eAAA,GAAAP,OAAA;AACA,IAAAQ,eAAA,GAAAR,OAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMS,KAAK,GAAAC,OAAA,CAAAD,KAAA,GAAG;EACnBE,IAAI,EAAEC,oBAAS;EACfC,KAAK,EAAEC,sBAAU;EACjBC,SAAS,EAAEC,8BAAc;EACzBC,KAAK,EAAEC,sBAAU;EACjBC,SAAS,EAAEC,8BAAc;EACzBC,SAAS,EAAEC,8BAAc;EACzBC,IAAI,EAAEA,UAAI;EACVC,MAAM,EAAEC,wBAAW;EACnBC,WAAW,EAAEC;AACf,CAAC","ignoreList":[]}
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.RulerContext = void 0;
7
+ exports.useRulerContext = useRulerContext;
8
+ var _react = require("react");
9
+ const RulerContext = exports.RulerContext = /*#__PURE__*/(0, _react.createContext)(null);
10
+ function useRulerContext() {
11
+ const context = (0, _react.useContext)(RulerContext);
12
+ if (!context) {
13
+ throw new Error('Ruler compound subcomponents must be rendered within a <Ruler.Root> provider.');
14
+ }
15
+ return context;
16
+ }
17
+ //# sourceMappingURL=RulerContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_react","require","RulerContext","exports","createContext","useRulerContext","context","useContext","Error"],"sourceRoot":"../../src","sources":["RulerContext.tsx"],"mappings":";;;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAWO,MAAMC,YAAY,GAAAC,OAAA,CAAAD,YAAA,gBAAG,IAAAE,oBAAa,EAA2B,IAAI,CAAC;AAElE,SAASC,eAAeA,CAAA,EAAsB;EACnD,MAAMC,OAAO,GAAG,IAAAC,iBAAU,EAACL,YAAY,CAAC;EACxC,IAAI,CAACI,OAAO,EAAE;IACZ,MAAM,IAAIE,KAAK,CAAC,+EAA+E,CAAC;EAClG;EACA,OAAOF,OAAO;AAChB","ignoreList":[]}