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
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+ import { View, StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
3
+ import { GestureDetector } from 'react-native-gesture-handler';
4
+ import { useRulerRangeContext } from './RulerRangeContext';
5
+ import { RulerRangeIndicator } from './RulerRangeIndicator';
6
+ import { RulerRangeTicks } from './RulerRangeTicks';
7
+
8
+ export interface RulerRangeTrackProps {
9
+ style?: StyleProp<ViewStyle>;
10
+ children?: React.ReactNode;
11
+ }
12
+
13
+ export function RulerRangeTrack({ style, children }: RulerRangeTrackProps = {}) {
14
+ const { panGesture, rulerHeight, width } = useRulerRangeContext();
15
+
16
+ return (
17
+ <GestureDetector gesture={panGesture}>
18
+ <View style={[styles.rulerContainer, { width, height: rulerHeight }, style]}>
19
+ {children ?? (
20
+ <>
21
+ <RulerRangeIndicator />
22
+ <RulerRangeTicks />
23
+ </>
24
+ )}
25
+ </View>
26
+ </GestureDetector>
27
+ );
28
+ }
29
+
30
+ const styles = StyleSheet.create({
31
+ rulerContainer: {
32
+ position: 'relative',
33
+ flexDirection: 'row',
34
+ alignItems: 'flex-end',
35
+ justifyContent: 'center',
36
+ overflow: 'hidden',
37
+ },
38
+ });
39
+
@@ -0,0 +1,59 @@
1
+ import React from 'react';
2
+ import {
3
+ TouchableOpacity,
4
+ Text,
5
+ StyleSheet,
6
+ type StyleProp,
7
+ type ViewStyle,
8
+ type TextStyle,
9
+ } from 'react-native';
10
+ import { useRulerContext } from './RulerContext';
11
+
12
+ export interface RulerResetButtonProps {
13
+ children?: React.ReactNode;
14
+ style?: StyleProp<ViewStyle>;
15
+ textStyle?: StyleProp<TextStyle>;
16
+ label?: string;
17
+ }
18
+
19
+ export function RulerResetButton({
20
+ children,
21
+ style,
22
+ textStyle,
23
+ label = 'Today',
24
+ }: RulerResetButtonProps = {}) {
25
+ const { resetToToday, theme } = useRulerContext();
26
+
27
+ return (
28
+ <TouchableOpacity
29
+ activeOpacity={0.7}
30
+ onPress={() => resetToToday(true)}
31
+ style={[styles.resetBtn, style]}
32
+ >
33
+ {children ?? (
34
+ <Text
35
+ style={[
36
+ styles.resetText,
37
+ { color: theme.accentColor },
38
+ textStyle,
39
+ ]}
40
+ >
41
+ {label}
42
+ </Text>
43
+ )}
44
+ </TouchableOpacity>
45
+ );
46
+ }
47
+
48
+ const styles = StyleSheet.create({
49
+ resetBtn: {
50
+ paddingVertical: 6,
51
+ paddingHorizontal: 12,
52
+ borderRadius: 16,
53
+ backgroundColor: 'rgba(0,0,0,0.05)',
54
+ },
55
+ resetText: {
56
+ fontSize: 14,
57
+ fontWeight: '600',
58
+ },
59
+ });
@@ -0,0 +1,93 @@
1
+ import React from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import type { RulerDatePickerProps, IndicatorConfig } from './types';
4
+ import { useRulerDatePicker } from './useRulerDatePicker';
5
+ import { RulerContext } from './RulerContext';
6
+ import { DEFAULT_LENS_CONFIG } from './defaults';
7
+
8
+ export interface RulerRootProps extends RulerDatePickerProps {
9
+ children?: React.ReactNode;
10
+ }
11
+
12
+ export function RulerRoot(props: RulerRootProps) {
13
+ const {
14
+ children,
15
+ style,
16
+ indicator,
17
+ lensEffect,
18
+ testID,
19
+ } = props;
20
+
21
+ const ruler = useRulerDatePicker(props);
22
+
23
+ const lensConfig = React.useMemo(() => {
24
+ if (!lensEffect) return null;
25
+ if (typeof lensEffect === 'object') {
26
+ return {
27
+ ...DEFAULT_LENS_CONFIG,
28
+ ...lensEffect,
29
+ };
30
+ }
31
+ return DEFAULT_LENS_CONFIG;
32
+ }, [lensEffect]);
33
+
34
+ const indicatorConfig: IndicatorConfig | undefined =
35
+ typeof indicator === 'object' ? indicator : undefined;
36
+ const headerConfig =
37
+ typeof props.header === 'object' ? props.header : undefined;
38
+
39
+ const contextValue = {
40
+ ...ruler,
41
+ indicatorConfig,
42
+ headerConfig,
43
+ locale: props.locale,
44
+ lensConfig,
45
+ };
46
+
47
+ return (
48
+ <RulerContext.Provider value={contextValue}>
49
+ <View
50
+ testID={testID}
51
+ accessible={true}
52
+ accessibilityRole="adjustable"
53
+ accessibilityLabel={props.accessibilityLabel ?? 'Date picker'}
54
+ accessibilityValue={{ text: ruler.selectedDateStr }}
55
+ accessibilityActions={[
56
+ { name: 'increment', label: 'Next day' },
57
+ { name: 'decrement', label: 'Previous day' },
58
+ ]}
59
+ onAccessibilityAction={(event) => {
60
+ if (event.nativeEvent.actionName === 'increment') {
61
+ const next = new Date(ruler.selectedDate);
62
+ next.setDate(next.getDate() + 1);
63
+ ruler.scrollToDate(next, true);
64
+ } else if (event.nativeEvent.actionName === 'decrement') {
65
+ const prev = new Date(ruler.selectedDate);
66
+ prev.setDate(prev.getDate() - 1);
67
+ ruler.scrollToDate(prev, true);
68
+ }
69
+ }}
70
+ style={[
71
+ styles.container,
72
+ {
73
+ minHeight: ruler.height,
74
+ backgroundColor: ruler.theme.background,
75
+ },
76
+ style,
77
+ ]}
78
+ >
79
+ {children}
80
+ </View>
81
+ </RulerContext.Provider>
82
+ );
83
+ }
84
+
85
+ const styles = StyleSheet.create({
86
+ container: {
87
+ justifyContent: 'center',
88
+ alignItems: 'center',
89
+ position: 'relative',
90
+ width: '100%',
91
+ paddingVertical: 8,
92
+ },
93
+ });
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ import { StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
3
+ import Animated, { useAnimatedStyle } from 'react-native-reanimated';
4
+ import { useRulerContext } from './RulerContext';
5
+ import { Tick } from './Tick';
6
+ import type { ResolvedTick } from './types';
7
+
8
+ export interface RulerTicksProps {
9
+ style?: StyleProp<ViewStyle>;
10
+ renderTick?: (tick: ResolvedTick, tickSpacing: number, rulerHeight: number) => React.ReactNode;
11
+ }
12
+
13
+ export function RulerTicks({ style, renderTick }: RulerTicksProps = {}) {
14
+ const { translateX, visibleTicks, tickSpacing, rulerHeight, width } =
15
+ useRulerContext();
16
+
17
+ const animatedStyle = useAnimatedStyle(
18
+ () => ({
19
+ transform: [{ translateX: translateX.value }],
20
+ }),
21
+ [translateX]
22
+ );
23
+
24
+ return (
25
+ <Animated.View
26
+ style={[
27
+ styles.ticksWrapper,
28
+ { left: width / 2 },
29
+ animatedStyle,
30
+ style,
31
+ ]}
32
+ >
33
+ {visibleTicks.map((tick) =>
34
+ renderTick ? (
35
+ <React.Fragment key={tick.offset}>
36
+ {renderTick(tick, tickSpacing, rulerHeight)}
37
+ </React.Fragment>
38
+ ) : (
39
+ <Tick
40
+ key={tick.offset}
41
+ tick={tick}
42
+ tickSpacing={tickSpacing}
43
+ rulerHeight={rulerHeight}
44
+ />
45
+ )
46
+ )}
47
+ </Animated.View>
48
+ );
49
+ }
50
+
51
+ const styles = StyleSheet.create({
52
+ ticksWrapper: {
53
+ position: 'absolute',
54
+ height: '100%',
55
+ width: 0,
56
+ },
57
+ });
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+ import { View, StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
3
+ import { GestureDetector } from 'react-native-gesture-handler';
4
+ import { useRulerContext } from './RulerContext';
5
+
6
+ import { RulerIndicator } from './RulerIndicator';
7
+ import { RulerTicks } from './RulerTicks';
8
+
9
+ export interface RulerTrackProps {
10
+ children?: React.ReactNode;
11
+ style?: StyleProp<ViewStyle>;
12
+ }
13
+
14
+ export function RulerTrack({ children, style }: RulerTrackProps = {}) {
15
+ const { panGesture, rulerHeight, width } = useRulerContext();
16
+
17
+ return (
18
+ <GestureDetector gesture={panGesture}>
19
+ <View style={[styles.rulerContainer, { width, height: rulerHeight }, style]}>
20
+ {children ?? (
21
+ <>
22
+ <RulerIndicator />
23
+ <RulerTicks />
24
+ </>
25
+ )}
26
+ </View>
27
+ </GestureDetector>
28
+ );
29
+ }
30
+
31
+ const styles = StyleSheet.create({
32
+ rulerContainer: {
33
+ position: 'relative',
34
+ flexDirection: 'row',
35
+ alignItems: 'flex-end',
36
+ justifyContent: 'center',
37
+ overflow: 'hidden',
38
+ },
39
+ });
package/src/Tick.tsx CHANGED
@@ -1,50 +1,45 @@
1
1
  import React from 'react';
2
2
  import { View, Text, StyleSheet } from 'react-native';
3
- import type { ResolvedColors } from './types';
3
+ import type { ResolvedTick } from './types';
4
4
 
5
5
  export interface TickProps {
6
- offset: number;
7
- isLabeled: boolean;
8
- isToday: boolean;
9
- isHighlighted: boolean;
10
- dateStr: string;
6
+ tick: ResolvedTick;
11
7
  tickSpacing: number;
12
- tickHeight: number;
13
- tickTallHeight: number;
14
- tickThickness: number;
15
- tickColor: string;
16
- tickTallColor: string;
17
- labelColor: string;
18
- accentColor: string;
19
- todayDotSize: number;
20
- labelFontSize: number;
21
8
  rulerHeight: number;
22
9
  }
23
10
 
24
11
  /**
25
12
  * Memoized single tick component.
26
- * Renders a vertical bar with optional label and today dot indicator.
27
- * Small and large ticks can be independently colored.
13
+ * Renders a vertical tick bar with optional label, dot indicator, or custom render element.
28
14
  */
29
15
  export const Tick = React.memo(function Tick({
30
- offset,
31
- isLabeled,
32
- isToday,
33
- dateStr,
16
+ tick,
34
17
  tickSpacing,
35
- tickHeight,
36
- tickTallHeight,
37
- tickThickness,
38
- tickColor,
39
- tickTallColor,
40
- labelColor,
41
- accentColor,
42
- todayDotSize,
43
- labelFontSize,
44
18
  rulerHeight,
45
19
  }: TickProps) {
46
- const resolvedTickColor = isLabeled ? tickTallColor : tickColor;
47
- const resolvedTickHeight = isLabeled ? tickTallHeight : tickHeight;
20
+ if (tick.customRender) {
21
+ return (
22
+ <View
23
+ style={[
24
+ styles.tickContainer,
25
+ {
26
+ width: tickSpacing,
27
+ height: rulerHeight,
28
+ position: 'absolute',
29
+ left: tick.offset * tickSpacing - tickSpacing / 2,
30
+ },
31
+ ]}
32
+ >
33
+ {tick.customRender({
34
+ date: tick.date,
35
+ offset: tick.offset,
36
+ isToday: tick.isToday,
37
+ isSelected: tick.isSelected,
38
+ isInRange: tick.isInRange,
39
+ })}
40
+ </View>
41
+ );
42
+ }
48
43
 
49
44
  return (
50
45
  <View
@@ -54,34 +49,50 @@ export const Tick = React.memo(function Tick({
54
49
  width: tickSpacing,
55
50
  height: rulerHeight,
56
51
  position: 'absolute',
57
- left: offset * tickSpacing - tickSpacing / 2,
52
+ left: tick.offset * tickSpacing - tickSpacing / 2,
58
53
  },
59
54
  ]}
60
55
  >
61
- {isLabeled && (
62
- <Text style={[styles.tickLabel, { color: labelColor, fontSize: labelFontSize }]}>
63
- {dateStr}
56
+ {/* Label */}
57
+ {tick.labelText !== undefined && (
58
+ <Text
59
+ numberOfLines={1}
60
+ style={[
61
+ styles.tickLabel,
62
+ {
63
+ color: tick.labelColor,
64
+ fontSize: tick.labelFontSize,
65
+ fontWeight: tick.labelFontWeight,
66
+ },
67
+ ]}
68
+ >
69
+ {tick.labelText}
64
70
  </Text>
65
71
  )}
66
- {isToday && (
72
+
73
+ {/* Dot Badge */}
74
+ {tick.hasDot && (
67
75
  <View
68
76
  style={[
69
- styles.todayDot,
77
+ styles.dot,
70
78
  {
71
- backgroundColor: accentColor,
72
- width: todayDotSize,
73
- height: todayDotSize,
74
- borderRadius: todayDotSize / 2,
79
+ backgroundColor: tick.dotColor,
80
+ width: tick.dotSize,
81
+ height: tick.dotSize,
82
+ borderRadius: tick.dotSize / 2,
83
+ bottom: tick.height + 4,
75
84
  },
76
85
  ]}
77
86
  />
78
87
  )}
88
+
89
+ {/* Bar */}
79
90
  <View
80
91
  style={{
81
- backgroundColor: resolvedTickColor,
82
- width: tickThickness,
83
- height: resolvedTickHeight,
84
- borderRadius: tickThickness / 2,
92
+ backgroundColor: tick.color,
93
+ width: tick.width,
94
+ height: tick.height,
95
+ borderRadius: tick.width / 2,
85
96
  }}
86
97
  />
87
98
  </View>
@@ -95,10 +106,10 @@ const styles = StyleSheet.create({
95
106
  },
96
107
  tickLabel: {
97
108
  position: 'absolute',
98
- top: 10,
109
+ top: 6,
110
+ textAlign: 'center',
99
111
  },
100
- todayDot: {
112
+ dot: {
101
113
  position: 'absolute',
102
- top: 25,
103
114
  },
104
115
  });
package/src/defaults.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ResolvedColors } from './types';
1
+ import type { ResolvedRulerTheme, LensConfig } from './types';
2
2
 
3
3
  // ── Internal constants (not user-configurable) ───────────────────────────
4
4
  export const MS_PER_DAY = 86_400_000;
@@ -7,38 +7,40 @@ export const DEFAULT_DAY_RANGE = 365;
7
7
  // ── User-configurable defaults ───────────────────────────────────────────
8
8
  export const DEFAULTS = {
9
9
  tickSpacing: 24,
10
- tickHeight: 12,
11
- tickTallHeight: 24,
12
- tickThickness: 4,
10
+ tickWidth: 3,
13
11
  height: 120,
14
12
  rulerHeight: 60,
15
13
  indicatorWidth: 2,
16
14
  indicatorHeight: 40,
17
15
  todayDotSize: 6,
18
- labelFontSize: 10,
19
16
  bufferTicks: 10,
20
- updateDebounceMs: 100,
17
+ debounceMs: 100,
21
18
  fastSwipeTickThreshold: 1,
22
19
  continuousHapticIntervalMs: 20,
23
- enableHaptics: true,
24
20
  showResetToToday: false,
25
21
  } as const;
26
22
 
23
+ export const DEFAULT_LENS_CONFIG: Required<LensConfig> = {
24
+ magnification: 1.6,
25
+ radius: 60,
26
+ scaleTicks: true,
27
+ };
28
+
27
29
  // ── Default color palettes ───────────────────────────────────────────────
28
- export const LIGHT_COLORS: ResolvedColors = {
29
- tickColor: '#D1D5DB',
30
- tickTallColor: '#9CA3AF',
31
- labelColor: '#6B7280',
32
- accentColor: '#3B82F6',
30
+ export const LIGHT_THEME: ResolvedRulerTheme = {
31
+ background: 'transparent',
33
32
  indicatorColor: '#3B82F6',
34
- backgroundColor: 'transparent',
33
+ accentColor: '#3B82F6',
34
+ labelColor: '#6B7280',
35
+ defaultTickColor: '#D1D5DB',
36
+ rangeHighlightColor: 'rgba(59, 130, 246, 0.15)',
35
37
  };
36
38
 
37
- export const DARK_COLORS: ResolvedColors = {
38
- tickColor: '#4B5563',
39
- tickTallColor: '#6B7280',
40
- labelColor: '#9CA3AF',
41
- accentColor: '#60A5FA',
39
+ export const DARK_THEME: ResolvedRulerTheme = {
40
+ background: 'transparent',
42
41
  indicatorColor: '#60A5FA',
43
- backgroundColor: 'transparent',
42
+ accentColor: '#60A5FA',
43
+ labelColor: '#9CA3AF',
44
+ defaultTickColor: '#4B5563',
45
+ rangeHighlightColor: 'rgba(96, 165, 250, 0.2)',
44
46
  };
package/src/index.ts CHANGED
@@ -1,2 +1,84 @@
1
+ // ── Components ─────────────────────────────────────────────────────────────
1
2
  export { RulerDatePicker } from './RulerDatePicker';
2
- export type { RulerDatePickerProps } from './types';
3
+ /** @experimental */
4
+ export { RulerDateRangePicker } from './RulerDateRangePicker';
5
+ export { Ruler } from './Ruler';
6
+ /** @experimental */
7
+ export { RulerRange } from './RulerRange';
8
+ export { Tick } from './Tick';
9
+ export { RulerLensTrack } from './RulerLensTrack';
10
+ export { RulerLensTicks } from './RulerLensTicks';
11
+ export { LensTick } from './LensTick';
12
+
13
+ // ── Compound Subcomponents ──────────────────────────────────────────────────
14
+ export { RulerRoot, type RulerRootProps } from './RulerRoot';
15
+ export { RulerTrack, type RulerTrackProps } from './RulerTrack';
16
+ export { RulerIndicator, type RulerIndicatorProps } from './RulerIndicator';
17
+ export { RulerTicks, type RulerTicksProps } from './RulerTicks';
18
+ export { RulerHeader, type RulerHeaderProps } from './RulerHeader';
19
+ export { RulerResetButton, type RulerResetButtonProps } from './RulerResetButton';
20
+
21
+ // ── Compound Subcomponents [EXPERIMENTAL] ───────────────────────────────────
22
+ export { RulerRangeRoot, type RulerRangeRootProps } from './RulerRangeRoot';
23
+ export { RulerRangeTrack, type RulerRangeTrackProps } from './RulerRangeTrack';
24
+ export { RulerRangeIndicator, type RulerRangeIndicatorProps } from './RulerRangeIndicator';
25
+ export { RulerRangeHeader, type RulerRangeHeaderProps } from './RulerRangeHeader';
26
+ export { RulerRangeHighlight, type RulerRangeHighlightProps } from './RulerRangeHighlight';
27
+ export { RulerRangeTicks, type RulerRangeTicksProps } from './RulerRangeTicks';
28
+
29
+ // ── Headless Hooks & Contexts ───────────────────────────────────────────────
30
+ export { useRulerDatePicker, type UseRulerDatePickerReturn } from './useRulerDatePicker';
31
+ /** @experimental */
32
+ export { useRulerDateRangePicker, type UseRulerDateRangePickerReturn } from './useRulerDateRangePicker';
33
+ export { useHaptics } from './useHaptics';
34
+ export { RulerContext, useRulerContext, type RulerContextValue } from './RulerContext';
35
+ /** @experimental */
36
+ export { RulerRangeContext, useRulerRangeContext, type RulerRangeContextValue } from './RulerRangeContext';
37
+
38
+ // ── Presets & Resolvers ───────────────────────────────────────────────────
39
+ export {
40
+ DEFAULT_CALENDAR_TICKS,
41
+ DEFAULT_METRIC_TICKS,
42
+ DEFAULT_MINIMAL_TICKS,
43
+ resolveTickRules,
44
+ } from './presets';
45
+ export { resolveTick, matchesCondition } from './tickResolver';
46
+
47
+ // ── Utilities & Constants ─────────────────────────────────────────────────
48
+ export {
49
+ formatDateString,
50
+ normalizeDate,
51
+ dateToDayOffset,
52
+ dayOffsetToDate,
53
+ computeDayRange,
54
+ useResolvedTheme,
55
+ } from './utils';
56
+ export { DEFAULTS, DEFAULT_LENS_CONFIG, LIGHT_THEME, DARK_THEME, MS_PER_DAY } from './defaults';
57
+
58
+ // ── Types ──────────────────────────────────────────────────────────────────
59
+ export type {
60
+ TickContext,
61
+ TickCondition,
62
+ TickLabelConfig,
63
+ TickDotConfig,
64
+ TickRule,
65
+ ResolvedTick,
66
+ RulerTheme,
67
+ ResolvedRulerTheme,
68
+ IndicatorConfig,
69
+ HeaderConfig,
70
+ RangeHeaderConfig,
71
+ RangeHeaderContext,
72
+ RangeHighlightConfig,
73
+ RangeIndicatorConfig,
74
+ HapticConfig,
75
+ RulerDatePickerProps,
76
+ LensConfig,
77
+ DateRange,
78
+ DateRangeChangePayload,
79
+ RulerDateRangePickerProps,
80
+ } from './types';
81
+ export type { LensTickProps } from './LensTick';
82
+ export type { RulerLensTrackProps } from './RulerLensTrack';
83
+ export type { RulerLensTicksProps } from './RulerLensTicks';
84
+ export type { TickProps } from './Tick';