react-native-smart-date-picker 0.1.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 (74) hide show
  1. package/README.md +163 -0
  2. package/lib/components/DateColumn.d.ts +3 -0
  3. package/lib/components/DateColumn.d.ts.map +1 -0
  4. package/lib/components/DateColumn.js +12 -0
  5. package/lib/components/HourColumn.d.ts +3 -0
  6. package/lib/components/HourColumn.d.ts.map +1 -0
  7. package/lib/components/HourColumn.js +12 -0
  8. package/lib/components/MinuteColumn.d.ts +3 -0
  9. package/lib/components/MinuteColumn.d.ts.map +1 -0
  10. package/lib/components/MinuteColumn.js +12 -0
  11. package/lib/components/MonthColumn.d.ts +3 -0
  12. package/lib/components/MonthColumn.d.ts.map +1 -0
  13. package/lib/components/MonthColumn.js +12 -0
  14. package/lib/components/PickerModal.d.ts +10 -0
  15. package/lib/components/PickerModal.d.ts.map +1 -0
  16. package/lib/components/PickerModal.js +27 -0
  17. package/lib/components/SelectionOverlay.d.ts +10 -0
  18. package/lib/components/SelectionOverlay.d.ts.map +1 -0
  19. package/lib/components/SelectionOverlay.js +26 -0
  20. package/lib/components/SmartDatePicker.d.ts +4 -0
  21. package/lib/components/SmartDatePicker.d.ts.map +1 -0
  22. package/lib/components/SmartDatePicker.js +154 -0
  23. package/lib/components/WheelColumn.d.ts +17 -0
  24. package/lib/components/WheelColumn.d.ts.map +1 -0
  25. package/lib/components/WheelColumn.js +126 -0
  26. package/lib/components/YearColumn.d.ts +3 -0
  27. package/lib/components/YearColumn.d.ts.map +1 -0
  28. package/lib/components/YearColumn.js +12 -0
  29. package/lib/hooks/useDatePicker.d.ts +13 -0
  30. package/lib/hooks/useDatePicker.d.ts.map +1 -0
  31. package/lib/hooks/useDatePicker.js +31 -0
  32. package/lib/hooks/useTheme.d.ts +13 -0
  33. package/lib/hooks/useTheme.d.ts.map +1 -0
  34. package/lib/hooks/useTheme.js +7 -0
  35. package/lib/hooks/useWheel.d.ts +5 -0
  36. package/lib/hooks/useWheel.d.ts.map +1 -0
  37. package/lib/hooks/useWheel.js +12 -0
  38. package/lib/index.d.ts +3 -0
  39. package/lib/index.d.ts.map +1 -0
  40. package/lib/index.js +23 -0
  41. package/lib/types/index.d.ts +59 -0
  42. package/lib/types/index.d.ts.map +1 -0
  43. package/lib/types/index.js +2 -0
  44. package/lib/utils/constants.d.ts +4 -0
  45. package/lib/utils/constants.d.ts.map +1 -0
  46. package/lib/utils/constants.js +19 -0
  47. package/lib/utils/dateUtils.d.ts +4 -0
  48. package/lib/utils/dateUtils.d.ts.map +1 -0
  49. package/lib/utils/dateUtils.js +21 -0
  50. package/lib/utils/generateData.d.ts +21 -0
  51. package/lib/utils/generateData.d.ts.map +1 -0
  52. package/lib/utils/generateData.js +95 -0
  53. package/lib/utils/validateDOB.d.ts +2 -0
  54. package/lib/utils/validateDOB.d.ts.map +1 -0
  55. package/lib/utils/validateDOB.js +17 -0
  56. package/package.json +54 -0
  57. package/src/components/DateColumn.tsx +14 -0
  58. package/src/components/HourColumn.tsx +14 -0
  59. package/src/components/MinuteColumn.tsx +14 -0
  60. package/src/components/MonthColumn.tsx +14 -0
  61. package/src/components/PickerModal.tsx +60 -0
  62. package/src/components/SelectionOverlay.tsx +45 -0
  63. package/src/components/SmartDatePicker.tsx +318 -0
  64. package/src/components/WheelColumn.tsx +231 -0
  65. package/src/components/YearColumn.tsx +14 -0
  66. package/src/hooks/useDatePicker.ts +47 -0
  67. package/src/hooks/useTheme.ts +18 -0
  68. package/src/hooks/useWheel.ts +13 -0
  69. package/src/index.ts +3 -0
  70. package/src/types/index.ts +77 -0
  71. package/src/utils/constants.ts +17 -0
  72. package/src/utils/dateUtils.ts +38 -0
  73. package/src/utils/generateData.ts +134 -0
  74. package/src/utils/validateDOB.ts +24 -0
package/README.md ADDED
@@ -0,0 +1,163 @@
1
+ # react-native-smart-date-picker
2
+
3
+ A lightweight, customizable React Native wheel-style date and datetime picker with a consistent UI on iOS and Android.
4
+
5
+ ## Features
6
+
7
+ - Wheel columns for day, month, year, hour, and minute
8
+ - Modes: `date`, `time`, `datetime` (date then time)
9
+ - Optional center selection overlay row
10
+ - Initial value support and min/max date clamping
11
+ - Theme and style customization via props
12
+ - Custom row height with `itemHeight`
13
+
14
+ ## Installation
15
+
16
+ Install in your React Native project:
17
+
18
+ ```bash
19
+ npm install react-native-smart-date-picker
20
+ ```
21
+
22
+ Peer dependencies: `react` and `react-native` (see package.json).
23
+
24
+ ## Usage
25
+
26
+ Basic example (date then time flow):
27
+
28
+ ```jsx
29
+ import React, { useState } from 'react';
30
+ import SmartDatePicker from 'react-native-smart-date-picker';
31
+
32
+ function Example() {
33
+ const [pickerVisible, setPickerVisible] = useState(false);
34
+ const [selectedDate, setSelectedDate] = useState(new Date());
35
+
36
+ return (
37
+ <>
38
+ <Button title="Open" onPress={() => setPickerVisible(true)} />
39
+
40
+ <SmartDatePicker
41
+ visible={pickerVisible}
42
+ value={selectedDate}
43
+ mode="datetime" // "date" | "time" | "datetime"
44
+ onCancel={() => setPickerVisible(false)}
45
+ onConfirm={(date) => {
46
+ setSelectedDate(date);
47
+ setPickerVisible(false);
48
+ console.log('Selected Date:', date);
49
+ }}
50
+ />
51
+ </>
52
+ );
53
+ }
54
+ ```
55
+
56
+ ### Time-only example
57
+
58
+ ```jsx
59
+ <SmartDatePicker visible={true} mode="time" onConfirm={...} onCancel={...} />
60
+ ```
61
+
62
+ ### Date-only example
63
+
64
+ ```jsx
65
+ <SmartDatePicker visible={true} mode="date" onConfirm={...} onCancel={...} />
66
+ ```
67
+
68
+ ### Theme example
69
+
70
+ ```jsx
71
+ <SmartDatePicker
72
+ visible={pickerVisible}
73
+ value={selectedDate}
74
+ mode="datetime"
75
+ theme={{
76
+ primaryColor: '#0f766e',
77
+ backgroundColor: '#f8fafc',
78
+ wheelBackgroundColor: '#ffffff',
79
+ textColor: '#111827',
80
+ buttonTextColor: '#0f766e',
81
+ }}
82
+ onCancel={() => setPickerVisible(false)}
83
+ onConfirm={(date) => {
84
+ setSelectedDate(date);
85
+ setPickerVisible(false);
86
+ }}
87
+ />
88
+ ```
89
+
90
+ ## Behavior
91
+
92
+ - In `datetime` mode, the picker shows the date wheels first and then transitions to time selection.
93
+ - In `date` mode, the picker renders day/month/year wheels only.
94
+ - In `time` mode, the picker renders hour/minute wheels only.
95
+ - `value` is clamped to `minimumDate` / `maximumDate` before confirmation.
96
+ - `showSelectionOverlay` defaults to `true` and renders a centered highlight bar.
97
+ - The modal slides up from the bottom using React Native `Modal`.
98
+
99
+ ## Props
100
+
101
+ ### Required
102
+
103
+ - `visible: boolean` — whether the picker is visible
104
+ - `onConfirm: (date: Date) => void` — called when the user taps Done
105
+ - `onCancel: () => void` — called when the user taps Cancel
106
+
107
+ ### Core picker props
108
+
109
+ - `mode?: 'date' | 'time' | 'datetime'` — which wheel UI to show (default: `datetime`)
110
+ - `value?: Date` — initial selected date/time (defaults to `new Date()`)
111
+ - `minimumDate?: Date` — earliest selectable date/time
112
+ - `maximumDate?: Date` — latest selectable date/time
113
+ - `showSelectionOverlay?: boolean` — display the center selection overlay row (default: `true`)
114
+ - `itemHeight?: number` — custom row height for wheel items
115
+
116
+ ### Theme and styling
117
+
118
+ - `theme?: Partial<SmartDatePickerTheme>` — partial theme object for colors
119
+ - `customTheme?: SmartDatePickerTheme` — full theme object replacing default theme values
120
+ - `minDateTheme?: Partial<SmartDatePickerTheme>` — theme overrides when the selected date equals `minimumDate`
121
+ - `maxDateTheme?: Partial<SmartDatePickerTheme>` — theme overrides when the selected date equals `maximumDate`
122
+ - `primaryColor?: string`
123
+ - `backgroundColor?: string`
124
+ - `textColor?: string`
125
+ - `buttonTextColor?: string`
126
+ - `overlayBorderColor?: string`
127
+ - `disabledTextColor?: string`
128
+ - `selectionOverlayColor?: string`
129
+ - `headerBackgroundColor?: string`
130
+ - `wheelBackgroundColor?: string`
131
+
132
+ ### Style overrides
133
+
134
+ - `containerStyle?: ViewStyle` — style for the modal container
135
+ - `wheelStyle?: ViewStyle` — style for the wheel columns
136
+ - `overlayStyle?: ViewStyle` — style for the picker panel / overlay
137
+ - `textStyle?: TextStyle` — style for all wheel labels
138
+ - `selectedTextStyle?: TextStyle` — style for the selected wheel label
139
+
140
+ See `src/types/index.ts` for the full TypeScript interface.
141
+
142
+ ## Development
143
+
144
+ Build the library locally:
145
+
146
+ ```bash
147
+ npm install
148
+ npm run build
149
+ ```
150
+
151
+ For development with live compile:
152
+
153
+ ```bash
154
+ npm run watch
155
+ ```
156
+
157
+ ### TypeScript / Editor notes
158
+
159
+ - If your editor shows "Cannot use JSX unless the '--jsx' flag is provided", ensure `tsconfig.json` contains `"jsx": "react-jsx"` and restart the TypeScript server in VS Code: Command Palette → `TypeScript: Restart TS Server`.
160
+
161
+ ## License
162
+
163
+ MIT
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ export default function DateColumn(props: any): React.JSX.Element;
3
+ //# sourceMappingURL=DateColumn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateColumn.d.ts","sourceRoot":"","sources":["../../src/components/DateColumn.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,CAAC,OAAO,UAAU,UAAU,CAC9B,KAAK,EAAE,GAAG,qBAQb"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = DateColumn;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const WheelColumn_1 = __importDefault(require("./WheelColumn"));
9
+ const generateData_1 = require("../utils/generateData");
10
+ function DateColumn(props) {
11
+ return ((0, jsx_runtime_1.jsx)(WheelColumn_1.default, Object.assign({ data: (0, generateData_1.generateDays)() }, props)));
12
+ }
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ export default function HourColumn(props: any): React.JSX.Element;
3
+ //# sourceMappingURL=HourColumn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HourColumn.d.ts","sourceRoot":"","sources":["../../src/components/HourColumn.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,CAAC,OAAO,UAAU,UAAU,CAC9B,KAAK,EAAE,GAAG,qBAQb"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = HourColumn;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const WheelColumn_1 = __importDefault(require("./WheelColumn"));
9
+ const generateData_1 = require("../utils/generateData");
10
+ function HourColumn(props) {
11
+ return ((0, jsx_runtime_1.jsx)(WheelColumn_1.default, Object.assign({ data: (0, generateData_1.generateHours)() }, props)));
12
+ }
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ export default function MinuteColumn(props: any): React.JSX.Element;
3
+ //# sourceMappingURL=MinuteColumn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MinuteColumn.d.ts","sourceRoot":"","sources":["../../src/components/MinuteColumn.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,CAAC,OAAO,UAAU,YAAY,CAChC,KAAK,EAAE,GAAG,qBAQb"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = MinuteColumn;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const WheelColumn_1 = __importDefault(require("./WheelColumn"));
9
+ const generateData_1 = require("../utils/generateData");
10
+ function MinuteColumn(props) {
11
+ return ((0, jsx_runtime_1.jsx)(WheelColumn_1.default, Object.assign({ data: (0, generateData_1.generateMinutes)() }, props)));
12
+ }
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ export default function MonthColumn(props: any): React.JSX.Element;
3
+ //# sourceMappingURL=MonthColumn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MonthColumn.d.ts","sourceRoot":"","sources":["../../src/components/MonthColumn.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,CAAC,OAAO,UAAU,WAAW,CAC/B,KAAK,EAAE,GAAG,qBAQb"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = MonthColumn;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const WheelColumn_1 = __importDefault(require("./WheelColumn"));
9
+ const generateData_1 = require("../utils/generateData");
10
+ function MonthColumn(props) {
11
+ return ((0, jsx_runtime_1.jsx)(WheelColumn_1.default, Object.assign({ data: (0, generateData_1.generateMonths)() }, props)));
12
+ }
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import { ViewStyle } from "react-native";
3
+ export default function PickerModal({ visible, children, backgroundColor, containerStyle, overlayStyle, }: {
4
+ visible: boolean;
5
+ children: React.ReactNode;
6
+ backgroundColor?: string;
7
+ containerStyle?: ViewStyle;
8
+ overlayStyle?: ViewStyle;
9
+ }): React.JSX.Element;
10
+ //# sourceMappingURL=PickerModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PickerModal.d.ts","sourceRoot":"","sources":["../../src/components/PickerModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAIH,SAAS,EACZ,MAAM,cAAc,CAAC;AAEtB,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAChC,OAAO,EACP,QAAQ,EACR,eAAe,EACf,cAAc,EACd,YAAY,GACf,EAAE;IACC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,YAAY,CAAC,EAAE,SAAS,CAAC;CAC5B,qBAuBA"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = PickerModal;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_native_1 = require("react-native");
6
+ function PickerModal({ visible, children, backgroundColor, containerStyle, overlayStyle, }) {
7
+ return ((0, jsx_runtime_1.jsx)(react_native_1.Modal, { transparent: true, visible: visible, animationType: "slide", children: (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [styles.container, containerStyle], children: (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [
8
+ styles.content,
9
+ overlayStyle,
10
+ {
11
+ backgroundColor: backgroundColor || "#fff",
12
+ },
13
+ ], children: children }) }) }));
14
+ }
15
+ const styles = react_native_1.StyleSheet.create({
16
+ container: {
17
+ flex: 1,
18
+ justifyContent: "flex-end",
19
+ backgroundColor: "rgba(0,0,0,0.4)",
20
+ },
21
+ content: {
22
+ height: 320,
23
+ backgroundColor: "#fff",
24
+ borderTopLeftRadius: 20,
25
+ borderTopRightRadius: 20,
26
+ },
27
+ });
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ interface Props {
3
+ itemHeight?: number;
4
+ borderColor?: string;
5
+ selectionOverlayColor?: string;
6
+ overlayStyle?: any;
7
+ }
8
+ export default function SelectionOverlay({ itemHeight, borderColor, selectionOverlayColor, overlayStyle, }: Props): React.JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=SelectionOverlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SelectionOverlay.d.ts","sourceRoot":"","sources":["../../src/components/SelectionOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,UAAU,KAAK;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,GAAG,CAAC;CACtB;AAED,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACrC,UAAe,EACf,WAAuB,EACvB,qBAAqC,EACrC,YAAY,GACf,EAAE,KAAK,qBAgBP"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = SelectionOverlay;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_native_1 = require("react-native");
6
+ function SelectionOverlay({ itemHeight = 44, borderColor = "#D1D5DB", selectionOverlayColor = "transparent", overlayStyle, }) {
7
+ return ((0, jsx_runtime_1.jsx)(react_native_1.View, { pointerEvents: "none", style: [
8
+ styles.overlay,
9
+ overlayStyle,
10
+ {
11
+ top: itemHeight * 2,
12
+ height: itemHeight,
13
+ borderColor,
14
+ backgroundColor: selectionOverlayColor,
15
+ },
16
+ ] }));
17
+ }
18
+ const styles = react_native_1.StyleSheet.create({
19
+ overlay: {
20
+ position: "absolute",
21
+ left: 0,
22
+ right: 0,
23
+ borderTopWidth: 1,
24
+ borderBottomWidth: 1,
25
+ },
26
+ });
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import { SmartDatePickerProps } from "../types";
3
+ export default function SmartDatePicker({ visible, value, onConfirm, onCancel, mode, showSelectionOverlay, minimumDate, maximumDate, primaryColor, backgroundColor, textColor, buttonTextColor, overlayBorderColor, disabledTextColor, selectionOverlayColor, headerBackgroundColor, wheelBackgroundColor, theme, customTheme, minDateTheme, maxDateTheme, containerStyle, wheelStyle, overlayStyle, textStyle, selectedTextStyle, itemHeight, }: SmartDatePickerProps): React.JSX.Element;
4
+ //# sourceMappingURL=SmartDatePicker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SmartDatePicker.d.ts","sourceRoot":"","sources":["../../src/components/SmartDatePicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAiBjD,OAAO,EACH,oBAAoB,EACvB,MAAM,UAAU,CAAC;AAOlB,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EACpC,OAAO,EACP,KAAkB,EAClB,SAAS,EACT,QAAQ,EACR,IAAiB,EACjB,oBAA2B,EAC3B,WAAW,EACX,WAAW,EACX,YAAY,EACZ,eAAe,EACf,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,EACL,WAAW,EACX,YAAY,EACZ,YAAY,EAEZ,cAAc,EACd,UAAU,EACV,YAAY,EACZ,SAAS,EACT,iBAAiB,EACjB,UAAU,GACb,EAAE,oBAAoB,qBA0OtB"}
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.default = SmartDatePicker;
40
+ const jsx_runtime_1 = require("react/jsx-runtime");
41
+ const react_1 = __importStar(require("react"));
42
+ const react_native_1 = require("react-native");
43
+ const PickerModal_1 = __importDefault(require("./PickerModal"));
44
+ const DateColumn_1 = __importDefault(require("./DateColumn"));
45
+ const MonthColumn_1 = __importDefault(require("./MonthColumn"));
46
+ const YearColumn_1 = __importDefault(require("./YearColumn"));
47
+ const HourColumn_1 = __importDefault(require("./HourColumn"));
48
+ const MinuteColumn_1 = __importDefault(require("./MinuteColumn"));
49
+ const SelectionOverlay_1 = __importDefault(require("./SelectionOverlay"));
50
+ const useDatePicker_1 = require("../hooks/useDatePicker");
51
+ const useTheme_1 = require("../hooks/useTheme");
52
+ const dateUtils_1 = require("../utils/dateUtils");
53
+ function SmartDatePicker({ visible, value = new Date(), onConfirm, onCancel, mode = "datetime", showSelectionOverlay = true, minimumDate, maximumDate, primaryColor, backgroundColor, textColor, buttonTextColor, overlayBorderColor, disabledTextColor, selectionOverlayColor, headerBackgroundColor, wheelBackgroundColor, theme, customTheme, minDateTheme, maxDateTheme,
54
+ // style overrides
55
+ containerStyle, wheelStyle, overlayStyle, textStyle, selectedTextStyle, itemHeight, }) {
56
+ const boundedValue = (0, react_1.useMemo)(() => (0, dateUtils_1.clampDate)(value, minimumDate, maximumDate), [value, minimumDate, maximumDate]);
57
+ const picker = (0, useDatePicker_1.useDatePicker)(boundedValue);
58
+ // view toggles between 'date' and 'time' when mode is 'datetime'
59
+ const [view, setView] = (0, react_1.useState)(mode === "time" ? "time" : "date");
60
+ react_1.default.useEffect(() => {
61
+ if (!visible)
62
+ return;
63
+ setView(mode === "time" ? "time" : "date");
64
+ }, [visible, mode]);
65
+ const selectedDate = (0, dateUtils_1.buildDate)(picker.day, picker.month, picker.year, picker.hour, picker.minute);
66
+ const effectiveDate = (0, dateUtils_1.clampDate)(selectedDate, minimumDate, maximumDate);
67
+ const selectedBoundaryTheme = (0, react_1.useMemo)(() => {
68
+ if (minimumDate &&
69
+ effectiveDate.getTime() === minimumDate.getTime()) {
70
+ return minDateTheme;
71
+ }
72
+ if (maximumDate &&
73
+ effectiveDate.getTime() === maximumDate.getTime()) {
74
+ return maxDateTheme;
75
+ }
76
+ return undefined;
77
+ }, [effectiveDate, minimumDate, maximumDate, minDateTheme, maxDateTheme]);
78
+ const themeObj = customTheme !== null && customTheme !== void 0 ? customTheme : (typeof theme === "object" ? theme : undefined);
79
+ const activeTheme = (0, useTheme_1.useTheme)(Object.assign(Object.assign(Object.assign({}, themeObj), selectedBoundaryTheme), { primaryColor,
80
+ backgroundColor,
81
+ textColor,
82
+ buttonTextColor,
83
+ overlayBorderColor,
84
+ disabledTextColor,
85
+ selectionOverlayColor,
86
+ headerBackgroundColor,
87
+ wheelBackgroundColor }));
88
+ const handleDone = () => {
89
+ onConfirm(effectiveDate);
90
+ };
91
+ const handleNext = () => setView("time");
92
+ const renderDateColumns = () => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(DateColumn_1.default, { selected: picker.day, onChange: picker.setDay, textColor: activeTheme.textColor, selectedTextColor: activeTheme.primaryColor, wheelBackgroundColor: activeTheme.wheelBackgroundColor, wheelStyle: wheelStyle, textStyle: textStyle, selectedTextStyle: selectedTextStyle }), (0, jsx_runtime_1.jsx)(MonthColumn_1.default, { selected: picker.month, onChange: picker.setMonth, textColor: activeTheme.textColor, selectedTextColor: activeTheme.primaryColor, wheelBackgroundColor: activeTheme.wheelBackgroundColor, wheelStyle: wheelStyle, textStyle: textStyle, selectedTextStyle: selectedTextStyle }), (0, jsx_runtime_1.jsx)(YearColumn_1.default, { selected: picker.year, onChange: picker.setYear, textColor: activeTheme.textColor, selectedTextColor: activeTheme.primaryColor, wheelBackgroundColor: activeTheme.wheelBackgroundColor, wheelStyle: wheelStyle, textStyle: textStyle, selectedTextStyle: selectedTextStyle })] }));
93
+ const renderTimeColumns = () => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(HourColumn_1.default, { selected: picker.hour, onChange: picker.setHour, textColor: activeTheme.textColor, selectedTextColor: activeTheme.primaryColor, wheelBackgroundColor: activeTheme.wheelBackgroundColor, wheelStyle: wheelStyle, textStyle: textStyle, selectedTextStyle: selectedTextStyle }), (0, jsx_runtime_1.jsx)(MinuteColumn_1.default, { selected: picker.minute, onChange: picker.setMinute, textColor: activeTheme.textColor, selectedTextColor: activeTheme.primaryColor, wheelBackgroundColor: activeTheme.wheelBackgroundColor, wheelStyle: wheelStyle, textStyle: textStyle, selectedTextStyle: selectedTextStyle })] }));
94
+ const selectedText = view === "time"
95
+ ? selectedDate.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
96
+ : selectedDate.toLocaleDateString();
97
+ return ((0, jsx_runtime_1.jsxs)(PickerModal_1.default, { visible: visible, backgroundColor: activeTheme.backgroundColor, containerStyle: containerStyle, overlayStyle: overlayStyle, children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
98
+ styles.header,
99
+ {
100
+ backgroundColor: activeTheme.headerBackgroundColor,
101
+ },
102
+ ], children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { children: [(0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { onPress: onCancel, children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [
103
+ styles.buttonText,
104
+ {
105
+ color: activeTheme.buttonTextColor ||
106
+ activeTheme.primaryColor,
107
+ },
108
+ ], children: "Cancel" }) }), (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [
109
+ styles.previewText,
110
+ {
111
+ color: activeTheme.textColor,
112
+ },
113
+ ], children: selectedText })] }), mode === "datetime" && view === "date" ? ((0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { onPress: handleNext, children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [
114
+ styles.buttonText,
115
+ {
116
+ color: activeTheme.buttonTextColor ||
117
+ activeTheme.primaryColor,
118
+ },
119
+ ], children: "Next" }) })) : ((0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { onPress: handleDone, children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [
120
+ styles.buttonText,
121
+ {
122
+ color: activeTheme.buttonTextColor ||
123
+ activeTheme.primaryColor,
124
+ },
125
+ ], children: "Done" }) }))] }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
126
+ styles.row,
127
+ {
128
+ backgroundColor: activeTheme.wheelBackgroundColor,
129
+ },
130
+ ], children: [view === "date" ? renderDateColumns() : renderTimeColumns(), showSelectionOverlay && ((0, jsx_runtime_1.jsx)(SelectionOverlay_1.default, { itemHeight: itemHeight, borderColor: activeTheme.overlayBorderColor, selectionOverlayColor: activeTheme.selectionOverlayColor, overlayStyle: overlayStyle }))] })] }));
131
+ }
132
+ const styles = react_native_1.StyleSheet.create({
133
+ header: {
134
+ height: 50,
135
+ paddingHorizontal: 20,
136
+ justifyContent: "space-between",
137
+ alignItems: "center",
138
+ flexDirection: "row",
139
+ },
140
+ row: {
141
+ flex: 1,
142
+ flexDirection: "row",
143
+ position: "relative",
144
+ },
145
+ buttonText: {
146
+ fontSize: 16,
147
+ fontWeight: "600",
148
+ },
149
+ previewText: {
150
+ marginTop: 6,
151
+ fontSize: 12,
152
+ color: "#666",
153
+ },
154
+ });
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { TextStyle, ViewStyle } from "react-native";
3
+ interface Props {
4
+ data: any[];
5
+ selected: any;
6
+ onChange: (v: any) => void;
7
+ textColor?: string;
8
+ selectedTextColor?: string;
9
+ wheelBackgroundColor?: string;
10
+ selectedFontSize?: number;
11
+ textStyle?: TextStyle;
12
+ selectedTextStyle?: TextStyle;
13
+ wheelStyle?: ViewStyle;
14
+ }
15
+ export default function WheelColumn({ data, selected, onChange, textColor, selectedTextColor, wheelBackgroundColor, selectedFontSize, textStyle, selectedTextStyle, wheelStyle, }: Props): React.JSX.Element;
16
+ export {};
17
+ //# sourceMappingURL=WheelColumn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WheelColumn.d.ts","sourceRoot":"","sources":["../../src/components/WheelColumn.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAC1D,OAAO,EAOH,SAAS,EACT,SAAS,EACZ,MAAM,cAAc,CAAC;AAEtB,UAAU,KAAK;IACX,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,QAAQ,EAAE,GAAG,CAAC;IACd,QAAQ,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,iBAAiB,CAAC,EAAE,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,SAAS,CAAC;CAC1B;AAMD,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAChC,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAEhB,SAAS,EACT,iBAAiB,EACjB,UAAU,GACb,EAAE,KAAK,qBA+KP"}
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = WheelColumn;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const react_native_1 = require("react-native");
7
+ const ITEM_HEIGHT = 44;
8
+ const VISIBLE_ROWS = 5;
9
+ const WHEEL_HEIGHT = ITEM_HEIGHT * VISIBLE_ROWS;
10
+ function WheelColumn({ data, selected, onChange, textColor, selectedTextColor, wheelBackgroundColor, selectedFontSize,
11
+ // forwarded style props
12
+ textStyle, selectedTextStyle, wheelStyle, }) {
13
+ const listRef = (0, react_1.useRef)(null);
14
+ // Repeat data for infinite effect
15
+ const repeatedData = data;
16
+ // const repeatedData = useMemo(
17
+ // () => [...data, ...data, ...data, ...data, ...data],
18
+ // [data]
19
+ // );
20
+ const selectedIndex = data.findIndex((item) => item.value === selected);
21
+ const middleIndex = selectedIndex >= 0
22
+ ? selectedIndex
23
+ : 0;
24
+ // const middleIndex =
25
+ // selectedIndex >= 0
26
+ // ? selectedIndex + data.length * 2
27
+ // : data.length * 2;
28
+ (0, react_1.useEffect)(() => {
29
+ setTimeout(() => {
30
+ var _a;
31
+ (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.scrollToOffset({
32
+ offset: middleIndex * ITEM_HEIGHT,
33
+ animated: false,
34
+ });
35
+ }, 50);
36
+ }, []);
37
+ // const handleScrollEnd = (
38
+ // e: NativeSyntheticEvent<NativeScrollEvent>
39
+ // ) => {
40
+ // const offsetY =
41
+ // e.nativeEvent.contentOffset.y;
42
+ // const index = Math.round(
43
+ // offsetY / ITEM_HEIGHT
44
+ // );
45
+ // const clampedIndex = Math.max(
46
+ // 0,
47
+ // Math.min(index, data.length - 1)
48
+ // );
49
+ // listRef.current?.scrollToOffset({
50
+ // offset:
51
+ // clampedIndex * ITEM_HEIGHT,
52
+ // animated: true,
53
+ // });
54
+ // const item = data[clampedIndex];
55
+ // if (item) {
56
+ // onChange(item.value);
57
+ // }
58
+ // };
59
+ const handleScrollEnd = (e) => {
60
+ var _a;
61
+ const offsetY = e.nativeEvent.contentOffset.y;
62
+ const index = Math.round(offsetY / ITEM_HEIGHT);
63
+ const clampedIndex = Math.max(0, Math.min(index, data.length - 1));
64
+ (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.scrollToOffset({
65
+ offset: clampedIndex * ITEM_HEIGHT,
66
+ animated: false,
67
+ });
68
+ const item = data[clampedIndex];
69
+ if (item) {
70
+ onChange(item.value);
71
+ }
72
+ };
73
+ return ((0, jsx_runtime_1.jsx)(react_native_1.FlatList, { ref: listRef, data: repeatedData, keyExtractor: (_, index) => index.toString(), style: [
74
+ {
75
+ height: WHEEL_HEIGHT,
76
+ backgroundColor: wheelBackgroundColor || "transparent",
77
+ },
78
+ wheelStyle,
79
+ ], showsVerticalScrollIndicator: false, bounces: false, removeClippedSubviews: false, disableIntervalMomentum: true, snapToInterval: ITEM_HEIGHT, snapToAlignment: "center", decelerationRate: "fast", onMomentumScrollEnd: handleScrollEnd, getItemLayout: (_, index) => ({
80
+ length: ITEM_HEIGHT,
81
+ offset: ITEM_HEIGHT * index,
82
+ index,
83
+ }), renderItem: ({ item }) => ((0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { style: styles.item, onPress: () => {
84
+ var _a;
85
+ const index = data.findIndex((d) => d.value === item.value);
86
+ (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.scrollToOffset({
87
+ offset: index * ITEM_HEIGHT,
88
+ animated: true,
89
+ });
90
+ onChange(item.value);
91
+ }, children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [
92
+ styles.text,
93
+ textStyle,
94
+ {
95
+ color: selectedTextColor ||
96
+ textColor ||
97
+ styles.text.color,
98
+ },
99
+ selected === item.value && [
100
+ {
101
+ fontWeight: "700",
102
+ fontSize: selectedFontSize || 20,
103
+ color: selectedTextColor ||
104
+ textColor ||
105
+ styles.text.color,
106
+ },
107
+ selectedTextStyle,
108
+ ],
109
+ ], children: item.label }) })), contentContainerStyle: {
110
+ paddingTop: ((VISIBLE_ROWS - 1) / 2) *
111
+ ITEM_HEIGHT,
112
+ paddingBottom: ((VISIBLE_ROWS - 1) / 2) *
113
+ ITEM_HEIGHT,
114
+ } }));
115
+ }
116
+ const styles = react_native_1.StyleSheet.create({
117
+ item: {
118
+ height: ITEM_HEIGHT,
119
+ justifyContent: "center",
120
+ alignItems: "center",
121
+ },
122
+ text: {
123
+ fontSize: 18,
124
+ color: "#111827",
125
+ },
126
+ });
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ export default function YearColumn(props: any): React.JSX.Element;
3
+ //# sourceMappingURL=YearColumn.d.ts.map