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.
- package/README.md +186 -60
- package/lib/commonjs/LensTick.js +83 -0
- package/lib/commonjs/LensTick.js.map +1 -0
- package/lib/commonjs/Ruler.js +38 -0
- package/lib/commonjs/Ruler.js.map +1 -0
- package/lib/commonjs/RulerContext.js +17 -0
- package/lib/commonjs/RulerContext.js.map +1 -0
- package/lib/commonjs/RulerDatePicker.js +38 -351
- package/lib/commonjs/RulerDatePicker.js.map +1 -1
- package/lib/commonjs/RulerDateRangePicker.js +56 -0
- package/lib/commonjs/RulerDateRangePicker.js.map +1 -0
- package/lib/commonjs/RulerHeader.js +106 -0
- package/lib/commonjs/RulerHeader.js.map +1 -0
- package/lib/commonjs/RulerIndicator.js +67 -0
- package/lib/commonjs/RulerIndicator.js.map +1 -0
- package/lib/commonjs/RulerLensTicks.js +55 -0
- package/lib/commonjs/RulerLensTicks.js.map +1 -0
- package/lib/commonjs/RulerLensTrack.js +52 -0
- package/lib/commonjs/RulerLensTrack.js.map +1 -0
- package/lib/commonjs/RulerRange.js +39 -0
- package/lib/commonjs/RulerRange.js.map +1 -0
- package/lib/commonjs/RulerRangeContext.js +17 -0
- package/lib/commonjs/RulerRangeContext.js.map +1 -0
- package/lib/commonjs/RulerRangeHeader.js +154 -0
- package/lib/commonjs/RulerRangeHeader.js.map +1 -0
- package/lib/commonjs/RulerRangeHighlight.js +50 -0
- package/lib/commonjs/RulerRangeHighlight.js.map +1 -0
- package/lib/commonjs/RulerRangeIndicator.js +71 -0
- package/lib/commonjs/RulerRangeIndicator.js.map +1 -0
- package/lib/commonjs/RulerRangeRoot.js +80 -0
- package/lib/commonjs/RulerRangeRoot.js.map +1 -0
- package/lib/commonjs/RulerRangeTicks.js +57 -0
- package/lib/commonjs/RulerRangeTicks.js.map +1 -0
- package/lib/commonjs/RulerRangeTrack.js +46 -0
- package/lib/commonjs/RulerRangeTrack.js.map +1 -0
- package/lib/commonjs/RulerResetButton.js +46 -0
- package/lib/commonjs/RulerResetButton.js.map +1 -0
- package/lib/commonjs/RulerRoot.js +87 -0
- package/lib/commonjs/RulerRoot.js.map +1 -0
- package/lib/commonjs/RulerTicks.js +51 -0
- package/lib/commonjs/RulerTicks.js.map +1 -0
- package/lib/commonjs/RulerTrack.js +46 -0
- package/lib/commonjs/RulerTrack.js.map +1 -0
- package/lib/commonjs/Tick.js +41 -36
- package/lib/commonjs/Tick.js.map +1 -1
- package/lib/commonjs/defaults.js +20 -19
- package/lib/commonjs/defaults.js.map +1 -1
- package/lib/commonjs/index.js +287 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/presets.js +108 -0
- package/lib/commonjs/presets.js.map +1 -0
- package/lib/commonjs/tickResolver.js +101 -0
- package/lib/commonjs/tickResolver.js.map +1 -0
- package/lib/commonjs/useHaptics.js +1 -1
- package/lib/commonjs/useHaptics.web.js +43 -0
- package/lib/commonjs/useHaptics.web.js.map +1 -0
- package/lib/commonjs/useRulerDatePicker.js +264 -0
- package/lib/commonjs/useRulerDatePicker.js.map +1 -0
- package/lib/commonjs/useRulerDateRangePicker.js +313 -0
- package/lib/commonjs/useRulerDateRangePicker.js.map +1 -0
- package/lib/commonjs/utils.js +61 -47
- package/lib/commonjs/utils.js.map +1 -1
- package/lib/module/LensTick.js +77 -0
- package/lib/module/LensTick.js.map +1 -0
- package/lib/module/Ruler.js +35 -0
- package/lib/module/Ruler.js.map +1 -0
- package/lib/module/RulerContext.js +12 -0
- package/lib/module/RulerContext.js.map +1 -0
- package/lib/module/RulerDatePicker.js +38 -350
- package/lib/module/RulerDatePicker.js.map +1 -1
- package/lib/module/RulerDateRangePicker.js +52 -0
- package/lib/module/RulerDateRangePicker.js.map +1 -0
- package/lib/module/RulerHeader.js +101 -0
- package/lib/module/RulerHeader.js.map +1 -0
- package/lib/module/RulerIndicator.js +62 -0
- package/lib/module/RulerIndicator.js.map +1 -0
- package/lib/module/RulerLensTicks.js +50 -0
- package/lib/module/RulerLensTicks.js.map +1 -0
- package/lib/module/RulerLensTrack.js +47 -0
- package/lib/module/RulerLensTrack.js.map +1 -0
- package/lib/module/RulerRange.js +36 -0
- package/lib/module/RulerRange.js.map +1 -0
- package/lib/module/RulerRangeContext.js +12 -0
- package/lib/module/RulerRangeContext.js.map +1 -0
- package/lib/module/RulerRangeHeader.js +149 -0
- package/lib/module/RulerRangeHeader.js.map +1 -0
- package/lib/module/RulerRangeHighlight.js +45 -0
- package/lib/module/RulerRangeHighlight.js.map +1 -0
- package/lib/module/RulerRangeIndicator.js +66 -0
- package/lib/module/RulerRangeIndicator.js.map +1 -0
- package/lib/module/RulerRangeRoot.js +75 -0
- package/lib/module/RulerRangeRoot.js.map +1 -0
- package/lib/module/RulerRangeTicks.js +51 -0
- package/lib/module/RulerRangeTicks.js.map +1 -0
- package/lib/module/RulerRangeTrack.js +41 -0
- package/lib/module/RulerRangeTrack.js.map +1 -0
- package/lib/module/RulerResetButton.js +41 -0
- package/lib/module/RulerResetButton.js.map +1 -0
- package/lib/module/RulerRoot.js +82 -0
- package/lib/module/RulerRoot.js.map +1 -0
- package/lib/module/RulerTicks.js +45 -0
- package/lib/module/RulerTicks.js.map +1 -0
- package/lib/module/RulerTrack.js +41 -0
- package/lib/module/RulerTrack.js.map +1 -0
- package/lib/module/Tick.js +41 -36
- package/lib/module/Tick.js.map +1 -1
- package/lib/module/defaults.js +19 -18
- package/lib/module/defaults.js.map +1 -1
- package/lib/module/index.js +46 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/presets.js +103 -0
- package/lib/module/presets.js.map +1 -0
- package/lib/module/tickResolver.js +97 -0
- package/lib/module/tickResolver.js.map +1 -0
- package/lib/module/useHaptics.js +1 -1
- package/lib/module/useHaptics.js.map +1 -1
- package/lib/module/useHaptics.web.js +39 -0
- package/lib/module/useHaptics.web.js.map +1 -0
- package/lib/module/useRulerDatePicker.js +260 -0
- package/lib/module/useRulerDatePicker.js.map +1 -0
- package/lib/module/useRulerDateRangePicker.js +310 -0
- package/lib/module/useRulerDateRangePicker.js.map +1 -0
- package/lib/module/utils.js +59 -45
- package/lib/module/utils.js.map +1 -1
- package/lib/typescript/LensTick.d.ts +20 -0
- package/lib/typescript/LensTick.d.ts.map +1 -0
- package/lib/typescript/Ruler.d.ts +31 -0
- package/lib/typescript/Ruler.d.ts.map +1 -0
- package/lib/typescript/RulerContext.d.ts +11 -0
- package/lib/typescript/RulerContext.d.ts.map +1 -0
- package/lib/typescript/RulerDatePicker.d.ts +10 -7
- package/lib/typescript/RulerDatePicker.d.ts.map +1 -1
- package/lib/typescript/RulerDateRangePicker.d.ts +26 -0
- package/lib/typescript/RulerDateRangePicker.d.ts.map +1 -0
- package/lib/typescript/RulerHeader.d.ts +14 -0
- package/lib/typescript/RulerHeader.d.ts.map +1 -0
- package/lib/typescript/RulerIndicator.d.ts +17 -0
- package/lib/typescript/RulerIndicator.d.ts.map +1 -0
- package/lib/typescript/RulerLensTicks.d.ts +12 -0
- package/lib/typescript/RulerLensTicks.d.ts.map +1 -0
- package/lib/typescript/RulerLensTrack.d.ts +13 -0
- package/lib/typescript/RulerLensTrack.d.ts.map +1 -0
- package/lib/typescript/RulerRange.d.ts +32 -0
- package/lib/typescript/RulerRange.d.ts.map +1 -0
- package/lib/typescript/RulerRangeContext.d.ts +11 -0
- package/lib/typescript/RulerRangeContext.d.ts.map +1 -0
- package/lib/typescript/RulerRangeHeader.d.ts +12 -0
- package/lib/typescript/RulerRangeHeader.d.ts.map +1 -0
- package/lib/typescript/RulerRangeHighlight.d.ts +8 -0
- package/lib/typescript/RulerRangeHighlight.d.ts.map +1 -0
- package/lib/typescript/RulerRangeIndicator.d.ts +17 -0
- package/lib/typescript/RulerRangeIndicator.d.ts.map +1 -0
- package/lib/typescript/RulerRangeRoot.d.ts +7 -0
- package/lib/typescript/RulerRangeRoot.d.ts.map +1 -0
- package/lib/typescript/RulerRangeTicks.d.ts +14 -0
- package/lib/typescript/RulerRangeTicks.d.ts.map +1 -0
- package/lib/typescript/RulerRangeTrack.d.ts +8 -0
- package/lib/typescript/RulerRangeTrack.d.ts.map +1 -0
- package/lib/typescript/RulerResetButton.d.ts +10 -0
- package/lib/typescript/RulerResetButton.d.ts.map +1 -0
- package/lib/typescript/RulerRoot.d.ts +7 -0
- package/lib/typescript/RulerRoot.d.ts.map +1 -0
- package/lib/typescript/RulerTicks.d.ts +9 -0
- package/lib/typescript/RulerTicks.d.ts.map +1 -0
- package/lib/typescript/RulerTrack.d.ts +8 -0
- package/lib/typescript/RulerTrack.d.ts.map +1 -0
- package/lib/typescript/Tick.d.ts +3 -16
- package/lib/typescript/Tick.d.ts.map +1 -1
- package/lib/typescript/defaults.d.ts +6 -9
- package/lib/typescript/defaults.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +37 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/presets.d.ts +27 -0
- package/lib/typescript/presets.d.ts.map +1 -0
- package/lib/typescript/tickResolver.d.ts +10 -0
- package/lib/typescript/tickResolver.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +302 -85
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/useHaptics.web.d.ts +17 -0
- package/lib/typescript/useHaptics.web.d.ts.map +1 -0
- package/lib/typescript/useRulerDatePicker.d.ts +26 -0
- package/lib/typescript/useRulerDatePicker.d.ts.map +1 -0
- package/lib/typescript/useRulerDateRangePicker.d.ts +40 -0
- package/lib/typescript/useRulerDateRangePicker.d.ts.map +1 -0
- package/lib/typescript/utils.d.ts +14 -12
- package/lib/typescript/utils.d.ts.map +1 -1
- package/package.json +25 -7
- package/src/LensTick.tsx +90 -0
- package/src/Ruler.ts +32 -0
- package/src/RulerContext.tsx +20 -0
- package/src/RulerDatePicker.tsx +41 -439
- package/src/RulerDateRangePicker.tsx +53 -0
- package/src/RulerHeader.tsx +125 -0
- package/src/RulerIndicator.tsx +84 -0
- package/src/RulerLensTicks.tsx +50 -0
- package/src/RulerLensTrack.tsx +45 -0
- package/src/RulerRange.ts +33 -0
- package/src/RulerRangeContext.tsx +20 -0
- package/src/RulerRangeHeader.tsx +180 -0
- package/src/RulerRangeHighlight.tsx +47 -0
- package/src/RulerRangeIndicator.tsx +85 -0
- package/src/RulerRangeRoot.tsx +87 -0
- package/src/RulerRangeTicks.tsx +68 -0
- package/src/RulerRangeTrack.tsx +39 -0
- package/src/RulerResetButton.tsx +59 -0
- package/src/RulerRoot.tsx +93 -0
- package/src/RulerTicks.tsx +57 -0
- package/src/RulerTrack.tsx +39 -0
- package/src/Tick.tsx +60 -49
- package/src/defaults.ts +21 -19
- package/src/index.ts +83 -1
- package/src/presets.ts +108 -0
- package/src/tickResolver.ts +123 -0
- package/src/types.ts +354 -102
- package/src/useHaptics.web.ts +55 -0
- package/src/useRulerDatePicker.ts +373 -0
- package/src/useRulerDateRangePicker.ts +468 -0
- package/src/utils.ts +67 -68
- package/lib/commonjs/package.json +0 -1
- package/lib/module/package.json +0 -1
package/README.md
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
5
|
+
<h1 align="center">react-native-ruler-date-picker</h1>
|
|
4
6
|
|
|
5
|
-
|
|
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
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
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
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
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
|
|
232
|
+
Colors auto-detect system light/dark mode. Provide custom tokens using `theme`:
|
|
100
233
|
|
|
101
234
|
```tsx
|
|
102
235
|
<RulerDatePicker
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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":[]}
|