@sauravluitel/date-time-picker-custom 1.0.1 β 1.0.3
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 +127 -42
- package/dist/date-time-picker-custom.css +1 -1
- package/dist/date-time-picker-custom.es.js +569 -540
- package/dist/date-time-picker-custom.umd.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,56 +1,141 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @sauravluitel/date-time-picker-custom
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@sauravluitel/date-time-picker-custom)
|
|
4
|
+
[](https://github.com/Saurav-627/Custom-Date-Time-Picker)
|
|
5
|
+
|
|
6
|
+
A professional, high-performance, and responsive React Date and Time picker library. Built with **Vite**, **Framer Motion**, and **Lucide React**, it offers dedicated, premium UIs for both Desktop and Mobile devices.
|
|
7
|
+
|
|
8
|
+
---
|
|
4
9
|
|
|
5
10
|
## β¨ Features
|
|
6
11
|
|
|
7
|
-
- **π± Dedicated Mobile UI**:
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
- **
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
12
|
+
- **π± Dedicated Mobile UI**:
|
|
13
|
+
- **Scroll-Wheel Select**: Smooth, iOS-style wheel selects for Years, Months, Days, and Time.
|
|
14
|
+
- **Touch Optimized**: Large tap targets and haptic-friendly scrolling.
|
|
15
|
+
- **React Portal Support (NEW)**: Renders via Portals to stay above all parents, even those with `transform` or `filter`.
|
|
16
|
+
- **π₯οΈ Premium Desktop UI**:
|
|
17
|
+
- **Elegant Calendar**: Full-featured grid with quick navigation between months and years.
|
|
18
|
+
- **Grid Time Select**: Fast and efficient grid selection for precision time setting.
|
|
19
|
+
- **π Form Ready (NEW in v1.0.1)**:
|
|
20
|
+
- **Synthetic Events**: Emits standard `{ target: { name, value } }` objects.
|
|
21
|
+
- **Drop-in Support**: Seamlessly integrates with **React Hook Form**, **Formik**, and **Yup**.
|
|
22
|
+
- **Standard Formats**: Always returns standard strings (`YYYY-MM-DD` and `HH:mm`).
|
|
23
|
+
- **π‘οΈ Submission Protection**: All internal buttons are typed as `type="button"` to prevent accidental parent form submissions.
|
|
24
|
+
- **π¨ Glassmorphism & Themes**:
|
|
25
|
+
- **Manual Theme Control**: Toggle between Dark/Light modes regardless of system settings.
|
|
26
|
+
- **High Visibility**: High z-index (`999999`) ensures pickers always stay on top.
|
|
27
|
+
- **Modern Aesthetics**: Sleek glassmorphism with smooth micro-animations.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## π Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install @sauravluitel/date-time-picker-custom
|
|
35
|
+
# or
|
|
36
|
+
yarn add @sauravluitel/date-time-picker-custom
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### β οΈ Important: CSS Import
|
|
40
|
+
To use the premium styles, import the CSS file in your main entry file (e.g., `main.js` or `App.js`):
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
import '@sauravluitel/date-time-picker-custom/style.css';
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
39
47
|
|
|
40
48
|
## π οΈ Usage
|
|
41
49
|
|
|
50
|
+
### Basic Example
|
|
51
|
+
|
|
42
52
|
```jsx
|
|
43
|
-
import {
|
|
53
|
+
import React, { useState } from 'react';
|
|
54
|
+
import { DatePicker, TimePicker } from '@sauravluitel/date-time-picker-custom';
|
|
44
55
|
|
|
45
|
-
function
|
|
46
|
-
const [date, setDate] = useState(
|
|
47
|
-
const [time, setTime] = useState('
|
|
56
|
+
function App() {
|
|
57
|
+
const [date, setDate] = useState('2024-03-02');
|
|
58
|
+
const [time, setTime] = useState('14:30');
|
|
48
59
|
|
|
49
60
|
return (
|
|
50
|
-
|
|
51
|
-
<DatePicker
|
|
52
|
-
|
|
53
|
-
|
|
61
|
+
<div className="form-group">
|
|
62
|
+
<DatePicker
|
|
63
|
+
value={date}
|
|
64
|
+
onChange={(e) => setDate(e.target.value)}
|
|
65
|
+
/>
|
|
66
|
+
|
|
67
|
+
<TimePicker
|
|
68
|
+
value={time}
|
|
69
|
+
onChange={(e) => setTime(e.target.value)}
|
|
70
|
+
use12h={true}
|
|
71
|
+
/>
|
|
72
|
+
</div>
|
|
54
73
|
);
|
|
55
74
|
}
|
|
56
75
|
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## π Form Integration
|
|
80
|
+
|
|
81
|
+
### React Hook Form
|
|
82
|
+
|
|
83
|
+
```jsx
|
|
84
|
+
import { useForm, Controller } from "react-hook-form";
|
|
85
|
+
import { DatePicker } from "@sauravluitel/date-time-picker-custom";
|
|
86
|
+
|
|
87
|
+
function MyForm() {
|
|
88
|
+
const { control, handleSubmit } = useForm();
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<form onSubmit={handleSubmit(data => console.log(data))}>
|
|
92
|
+
<Controller
|
|
93
|
+
name="birthDate"
|
|
94
|
+
control={control}
|
|
95
|
+
render={({ field }) => (
|
|
96
|
+
<DatePicker
|
|
97
|
+
{...field}
|
|
98
|
+
placeholder="Select your birthday"
|
|
99
|
+
/>
|
|
100
|
+
)}
|
|
101
|
+
/>
|
|
102
|
+
<button type="submit">Submit</button>
|
|
103
|
+
</form>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## βοΈ Props Reference
|
|
111
|
+
|
|
112
|
+
### DatePicker
|
|
113
|
+
| Prop | Type | Default | Description |
|
|
114
|
+
| :--- | :--- | :--- | :--- |
|
|
115
|
+
| `value` | `string` | `""` | Date in `YYYY-MM-DD` format. |
|
|
116
|
+
| `onChange` | `function` | `-` | Returns standard synthetic event. |
|
|
117
|
+
| `placeholder` | `string` | `"YYYY/MM/DD"` | Placeholder for the input field. |
|
|
118
|
+
| `name` | `string` | `-` | Name for form integration. |
|
|
119
|
+
| `disabled` | `boolean` | `false` | Disables all interactions. |
|
|
120
|
+
| `isDarkMode` | `boolean` | `undefined` | Forces Dark Mode (`true`) or Light Mode (`false`). Default follows system. |
|
|
121
|
+
|
|
122
|
+
### TimePicker
|
|
123
|
+
| Prop | Type | Default | Description |
|
|
124
|
+
| :--- | :--- | :--- | :--- |
|
|
125
|
+
| `value` | `string` | `""` | Time in `HH:mm` (24h) format. |
|
|
126
|
+
| `onChange` | `function` | `-` | Returns standard synthetic event. |
|
|
127
|
+
| `use12h` | `boolean` | `true` | Show AM/PM selector. |
|
|
128
|
+
| `showSeconds`| `boolean` | `false` | Show seconds selector. |
|
|
129
|
+
| `disabled` | `boolean` | `false` | Disables all interactions. |
|
|
130
|
+
| `isDarkMode` | `boolean` | `undefined` | Forces Dark Mode (`true`) or Light Mode (`false`). Default follows system. |
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## π» Tech Stack
|
|
135
|
+
- **React** 18+
|
|
136
|
+
- **Framer Motion** (Animations)
|
|
137
|
+
- **Lucide React** (Icons)
|
|
138
|
+
- **date-fns** (Date logic)
|
|
139
|
+
|
|
140
|
+
## π License
|
|
141
|
+
MIT Β© [Saurav Luitel](https://github.com/Saurav-627)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@import"https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap";.datepicker-wrapper,.datepicker-wrapper *,.timepicker-wrapper,.timepicker-wrapper *{box-sizing:border-box;margin:0;padding:0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-tap-highlight-color:transparent;font-family:Outfit,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;color:var(--text)}.datepicker-wrapper button,.timepicker-wrapper button{cursor:pointer;border:none;background:transparent;-moz-appearance:none;appearance:none;-webkit-appearance:none;outline:none;color:inherit}.datepicker-wrapper input,.timepicker-wrapper input{outline:none;border:none;background:transparent;-moz-appearance:none;appearance:none;-webkit-appearance:none;box-shadow:none;color:inherit}:root{--primary: #3b82f6;--primary-glow: rgba(59, 130, 246, .4);--secondary: #6366f1;--bg: #0f172a;--card-bg: rgba(30, 41, 59, 1);--text: #f8fafc;--text-dim: #94a3b8;--border: rgba(255, 255, 255, .1);--border-active: rgba(59, 130, 246, .5);--glass: rgba(15, 23, 42, .6);--hover-overlay: rgba(255, 255, 255, .1);--shadow-heavy: rgba(0, 0, 0, .5);--mobile-sheet-bg: rgba(15, 23, 42, 1);--radius: 12px;--transition: all .3s cubic-bezier(.4, 0, .2, 1)}@media(prefers-color-scheme:light){:root{--bg: #f1f5f9;--card-bg: rgba(255, 255, 255, 1);--text: #0f172a;--text-dim: #64748b;--border: rgba(0, 0, 0, .1);--glass: rgba(255, 255, 255, .8);--hover-overlay: rgba(0, 0, 0, .05);--shadow-heavy: rgba(0, 0, 0, .15);--mobile-sheet-bg: rgba(255, 255, 255, 1)}}.glass-card{background:var(--card-bg);border:1px solid var(--border);border-radius:var(--radius);box-shadow:0 8px 32px #0000004d}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:10px}::-webkit-scrollbar-thumb:hover{background:#fff3}.animate-scale{transition:transform .2s ease}.animate-scale:active{transform:scale(.95)}.picker-dropdown{position:absolute;z-index:
|
|
1
|
+
@import"https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap";.datepicker-wrapper,.datepicker-wrapper *,.timepicker-wrapper,.timepicker-wrapper *,.datepicker-mobile-portal,.datepicker-mobile-portal *,.timepicker-mobile-portal,.timepicker-mobile-portal *{box-sizing:border-box;margin:0;padding:0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-tap-highlight-color:transparent;font-family:Outfit,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;color:var(--text)}.datepicker-wrapper button,.timepicker-wrapper button{cursor:pointer;border:none;background:transparent;-moz-appearance:none;appearance:none;-webkit-appearance:none;outline:none;color:inherit}.datepicker-wrapper input,.timepicker-wrapper input{outline:none;border:none;background:transparent;-moz-appearance:none;appearance:none;-webkit-appearance:none;box-shadow:none;color:inherit}:root,.datepicker-wrapper,.timepicker-wrapper,.datepicker-mobile-portal,.timepicker-mobile-portal{--primary: #3b82f6;--primary-glow: rgba(59, 130, 246, .4);--secondary: #6366f1;--bg: #0f172a;--card-bg: rgba(30, 41, 59, 1);--text: #f8fafc;--text-dim: #94a3b8;--border: rgba(255, 255, 255, .1);--border-active: rgba(59, 130, 246, .5);--glass: rgba(15, 23, 42, .6);--hover-overlay: rgba(255, 255, 255, .1);--shadow-heavy: rgba(0, 0, 0, .5);--mobile-sheet-bg: rgba(15, 23, 42, 1);--radius: 12px;--transition: all .3s cubic-bezier(.4, 0, .2, 1)}@media(prefers-color-scheme:light){:root:not(.dark-theme),.datepicker-wrapper:not(.dark-theme),.timepicker-wrapper:not(.dark-theme),.datepicker-mobile-portal:not(.dark-theme),.timepicker-mobile-portal:not(.dark-theme){--bg: #f1f5f9;--card-bg: rgba(255, 255, 255, 1);--text: #0f172a;--text-dim: #64748b;--border: rgba(0, 0, 0, .1);--glass: rgba(255, 255, 255, .8);--hover-overlay: rgba(0, 0, 0, .05);--shadow-heavy: rgba(0, 0, 0, .15);--mobile-sheet-bg: rgba(255, 255, 255, 1)}}.datepicker-wrapper.light-theme,.timepicker-wrapper.light-theme,.datepicker-mobile-portal.light-theme,.timepicker-mobile-portal.light-theme{--bg: #f1f5f9;--card-bg: rgba(255, 255, 255, 1);--text: #0f172a;--text-dim: #64748b;--border: rgba(0, 0, 0, .1);--glass: rgba(255, 255, 255, .8);--hover-overlay: rgba(0, 0, 0, .05);--shadow-heavy: rgba(0, 0, 0, .15);--mobile-sheet-bg: rgba(255, 255, 255, 1)}.datepicker-wrapper.dark-theme,.timepicker-wrapper.dark-theme,.datepicker-mobile-portal.dark-theme,.timepicker-mobile-portal.dark-theme{--bg: #0f172a;--card-bg: rgba(30, 41, 59, 1);--text: #f8fafc;--text-dim: #94a3b8;--border: rgba(255, 255, 255, .1);--glass: rgba(15, 23, 42, .6);--hover-overlay: rgba(255, 255, 255, .1);--shadow-heavy: rgba(0, 0, 0, .5);--mobile-sheet-bg: rgba(15, 23, 42, 1)}.glass-card{background:var(--card-bg);border:1px solid var(--border);border-radius:var(--radius);box-shadow:0 8px 32px #0000004d}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:10px}::-webkit-scrollbar-thumb:hover{background:#fff3}.animate-scale{transition:transform .2s ease}.animate-scale:active{transform:scale(.95)}.picker-dropdown{position:absolute;z-index:999999;margin-top:8px;overflow:hidden;box-shadow:0 10px 40px var(--shadow-heavy);background:var(--card-bg)!important}.picker-dropdown.mobile{position:fixed!important;inset:auto 0 0!important;border-radius:20px 20px 0 0!important;margin:0!important;max-height:48vh!important;width:100%!important;padding-bottom:calc(10px + env(safe-area-inset-bottom));box-shadow:0 -8px 32px var(--shadow-heavy);background:var(--mobile-sheet-bg)!important;backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px)}@media(max-width:768px){.picker-dropdown.desktop{display:none!important}}.mobile-backdrop{position:fixed;inset:0;background:#0009;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:999998}.input-container.drop-up+.picker-dropdown{top:auto!important;bottom:100%!important;margin-bottom:8px;margin-top:0}.input-container.drop-down+.picker-dropdown{top:100%!important;bottom:auto!important}.scroll-columns{display:flex;justify-content:center;height:120px;min-height:120px;max-height:120px;overflow:hidden;position:relative;width:100%;margin:0 auto}.scroll-columns:after{content:"";position:absolute;top:44px;left:5%;width:90%;height:32px;background:var(--hover-overlay);border-top:1px solid var(--border);border-bottom:1px solid var(--border);pointer-events:none;border-radius:8px}.scroll-col{flex:1;max-width:70px;height:100%;max-height:120px;overflow-y:scroll;-webkit-overflow-scrolling:touch;scrollbar-width:none;display:flex;flex-direction:column;align-items:center;scroll-snap-type:y mandatory;padding:0;overscroll-behavior:none;position:relative;z-index:2}.scroll-col:before,.scroll-col:after{content:"";display:block;min-height:44px;flex-shrink:0;width:100%}.scroll-col::-webkit-scrollbar{display:none}.scroll-item{height:32px;min-height:32px;line-height:32px;display:flex;align-items:center;justify-content:center;font-size:1rem;color:var(--text-dim);transition:var(--transition);cursor:pointer;width:100%;scroll-snap-align:center;margin:0}.scroll-item.selected{font-weight:700;color:var(--primary);opacity:1;font-size:1.15rem}.mobile-scroll-picker{padding:16px 8px}.mobile-header{text-align:center;margin-bottom:12px;padding:0 16px}.mobile-header h3{margin-bottom:2px;font-size:1.2rem}.selected-preview{font-size:.9rem;color:var(--primary);font-weight:600}.confirm-btn{margin-top:16px;background-color:var(--primary)!important;padding:12px;border-radius:12px;font-weight:700;width:calc(100% - 32px);margin-left:16px;margin-right:16px;font-size:1rem;box-shadow:0 4px 12px var(--shadow-heavy);color:#fff!important;display:flex;justify-content:center;align-items:center}.input-container{display:flex;align-items:center;padding:10px 16px;gap:12px;transition:var(--transition);border:1px solid var(--border);width:100%;max-width:320px;position:relative;cursor:pointer}.input-container.focused{border-color:var(--primary);box-shadow:0 0 0 3px var(--primary-glow);background:var(--card-bg)}.input-icon-wrapper{cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-dim);transition:var(--transition)}.input-container.focused .input-icon-wrapper{color:var(--primary)}.shared-input{background:transparent;border:none;color:var(--text);font-size:16px;width:100%;font-weight:500;padding:0;margin:0;line-height:1.2}.shared-input:focus{outline:none!important;box-shadow:none!important}.shared-input::-moz-placeholder{color:var(--text-dim);opacity:.5}.shared-input::placeholder{color:var(--text-dim);opacity:.5}.clear-btn{color:var(--text-dim);opacity:.6;transition:var(--transition);display:flex;align-items:center;padding:4px;border-radius:50%}.clear-btn:hover{opacity:1;background:var(--hover-overlay);color:#ef4444}.input-container.error{border-color:#ef4444}.datepicker-wrapper{position:relative;width:-moz-fit-content;width:fit-content}.selector-view{width:320px;padding:16px}.grid-selector{display:grid;gap:8px;padding:8px}.grid-selector.column-3{grid-template-columns:repeat(3,1fr)}.grid-selector.column-4{grid-template-columns:repeat(4,1fr)}.select-cell{padding:12px 8px;border-radius:8px;font-size:.9rem;transition:var(--transition)}.select-cell:hover{background:var(--primary-glow);color:var(--primary)}.select-cell.active{background:var(--primary);color:#fff}.desktop-calendar{width:320px;padding:16px}.calendar-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;font-weight:600}.header-nav{display:flex;gap:4px}.nav-btn{cursor:pointer;padding:4px 8px;border-radius:6px;transition:var(--transition)}.nav-btn:hover{background:var(--hover-overlay);color:var(--primary)}.calendar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:8px}.calendar-day-header{font-size:.8rem;color:var(--text-dim);text-align:center;font-weight:600}.calendar-day-cell{width:100%;aspect-ratio:1;display:flex;align-items:center;justify-content:center;border-radius:8px;font-size:.9rem;transition:var(--transition);cursor:pointer}.calendar-day-cell:hover{background:var(--primary-glow);color:var(--primary)}.calendar-day-cell.active{background:var(--primary)!important;color:#fff!important}.calendar-day-cell.today{border:1px solid var(--primary);font-weight:700}.timepicker-wrapper{position:relative;width:-moz-fit-content;width:fit-content}.desktop-time-picker{width:260px;padding:12px;transition:width .3s ease}.desktop-time-picker.with-seconds{width:340px}.time-select-grid{display:flex;gap:12px}.time-col{flex:1;display:flex;flex-direction:column}.col-label{font-size:.8rem;color:var(--text-dim);text-transform:uppercase;margin-bottom:8px;text-align:center}.time-scroll{height:200px;overflow-y:auto;display:flex;flex-direction:column;gap:4px}.time-btn{padding:8px;border-radius:6px;font-size:.9rem;transition:var(--transition)}.time-btn:hover{background:var(--hover-overlay);color:var(--primary)}.time-btn.active{background:var(--primary);color:#fff}.desktop-footer{margin-top:12px;padding-top:12px;border-top:1px solid var(--border);display:flex;justify-content:flex-end}.confirm-btn.small{padding:6px 12px;font-size:.85rem;border-radius:8px;background:var(--primary);color:#fff;display:flex;align-items:center;font-weight:600}
|