universal-datetime-picker 2.0.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/LICENSE +21 -0
- package/README.md +452 -0
- package/dist/angular/index.d.mts +15 -0
- package/dist/angular/index.d.ts +15 -0
- package/dist/angular/index.js +2196 -0
- package/dist/angular/index.mjs +2183 -0
- package/dist/cdn/universal-datetime-picker.iife.js +1 -0
- package/dist/core/index.d.mts +58 -0
- package/dist/core/index.d.ts +58 -0
- package/dist/core/index.js +867 -0
- package/dist/core/index.mjs +832 -0
- package/dist/index.d.mts +183 -0
- package/dist/index.d.ts +185 -0
- package/dist/index.js +2054 -0
- package/dist/index.mjs +2030 -0
- package/dist/rangeController-Bq35aBwe.d.mts +271 -0
- package/dist/rangeController-Bq35aBwe.d.ts +271 -0
- package/dist/rangeRenderer-AVv6PJbW.d.mts +21 -0
- package/dist/rangeRenderer-a3hFk-kK.d.ts +21 -0
- package/dist/style.css +1 -0
- package/dist/svelte/index.d.mts +11 -0
- package/dist/svelte/index.d.ts +11 -0
- package/dist/svelte/index.js +2194 -0
- package/dist/svelte/index.mjs +2182 -0
- package/dist/vanilla/index.d.mts +21 -0
- package/dist/vanilla/index.d.ts +21 -0
- package/dist/vanilla/index.js +1831 -0
- package/dist/vanilla/index.mjs +1812 -0
- package/dist/vue/index.d.mts +9 -0
- package/dist/vue/index.d.ts +9 -0
- package/dist/vue/index.js +2193 -0
- package/dist/vue/index.mjs +2181 -0
- package/dist/wc/index.d.mts +43 -0
- package/dist/wc/index.d.ts +43 -0
- package/dist/wc/index.js +2204 -0
- package/dist/wc/index.mjs +2189 -0
- package/package.json +232 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022-2026 Raghav Bhardwaj
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
[](https://www.npmjs.com/package/universal-datetime-picker)
|
|
2
|
+
[](https://www.npmjs.com/package/universal-datetime-picker)
|
|
3
|
+
[](https://www.npmjs.com/package/universal-datetime-picker)
|
|
4
|
+
[](https://github.com/Bhardwaj-Raghav/universal-datetime-picker/actions/workflows/ci.yml)
|
|
5
|
+
[](https://github.com/Bhardwaj-Raghav/universal-datetime-picker/blob/main/LICENSE)
|
|
6
|
+
|
|
7
|
+
# universal-datetime-picker
|
|
8
|
+
|
|
9
|
+
**Date picker, time picker, datetime picker, and date range calendar** — one accessible TypeScript package. The [docs site](https://universal-datetime-picker.vercel.app) home uses **vanilla JS**; **React, Vue, Svelte, Angular, and CDN** each have dedicated demo pages.
|
|
10
|
+
|
|
11
|
+
Native React components share a headless core with a vanilla DOM renderer and Web Components (`<datetime-picker>`, `<datetime-picker-input>`, `<datetime-picker-range>`).
|
|
12
|
+
|
|
13
|
+
- **Live demos:** [universal-datetime-picker.vercel.app](https://universal-datetime-picker.vercel.app) — home page uses the **vanilla** `createDateTimePicker` API; per-framework pages: [`/react/`](https://universal-datetime-picker.vercel.app/react/), [`/vue/`](https://universal-datetime-picker.vercel.app/vue/), [`/svelte/`](https://universal-datetime-picker.vercel.app/svelte/), [`/angular/`](https://universal-datetime-picker.vercel.app/angular/), [`/vanilla/`](https://universal-datetime-picker.vercel.app/vanilla/), [`/web-components/`](https://universal-datetime-picker.vercel.app/web-components/), [`/cdn/`](https://universal-datetime-picker.vercel.app/cdn/), [`/solid/`](https://universal-datetime-picker.vercel.app/solid/), [`/preact/`](https://universal-datetime-picker.vercel.app/preact/), [`/nextjs/`](https://universal-datetime-picker.vercel.app/nextjs/), [`/nuxt/`](https://universal-datetime-picker.vercel.app/nuxt/)
|
|
14
|
+
- **npm:** [universal-datetime-picker](https://www.npmjs.com/package/universal-datetime-picker)
|
|
15
|
+
- **GitHub:** [Bhardwaj-Raghav/universal-datetime-picker](https://github.com/Bhardwaj-Raghav/universal-datetime-picker)
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- React (native), Vue / Svelte / Angular (via Web Components), vanilla JS, and CDN
|
|
20
|
+
- Date picker, time picker, and combined datetime picker
|
|
21
|
+
- Date range picker with keyboard-friendly calendar grid
|
|
22
|
+
- Input + popover or fully inline calendar modes
|
|
23
|
+
- TypeScript types, ESM/CJS builds, React 18+ (optional peer)
|
|
24
|
+
- Accessible UI (dialog, focus trap, arrow-key navigation)
|
|
25
|
+
- Themable via CSS variables; dark theme support
|
|
26
|
+
- Locales via dayjs; custom labels; 12-hour AM/PM mode
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install universal-datetime-picker
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
yarn add universal-datetime-picker
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pnpm add universal-datetime-picker
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
For React apps, peer dependencies are `react` and `react-dom` (≥ 18). They are **optional** if you only use vanilla, Web Components, or CDN.
|
|
43
|
+
|
|
44
|
+
## Package entry points
|
|
45
|
+
|
|
46
|
+
| Import | Use for |
|
|
47
|
+
|--------|---------|
|
|
48
|
+
| `universal-datetime-picker` | React components (`DateTime`, `DateTimeInput`, `DateTimeRange`) |
|
|
49
|
+
| `universal-datetime-picker/vanilla` | `createDateTimePicker` / `createDateTimeRangePicker` |
|
|
50
|
+
| `universal-datetime-picker/wc` | `defineCustomElements()` + custom element classes |
|
|
51
|
+
| `universal-datetime-picker/vue` | Registers elements for Vue |
|
|
52
|
+
| `universal-datetime-picker/svelte` | Registers elements / Svelte action |
|
|
53
|
+
| `universal-datetime-picker/angular` | `registerDateTimePickerElements()` |
|
|
54
|
+
| `universal-datetime-picker/core` | Headless controllers + date logic |
|
|
55
|
+
| `universal-datetime-picker/style.css` | Shared stylesheet |
|
|
56
|
+
|
|
57
|
+
## Screenshots
|
|
58
|
+
|
|
59
|
+
| Date only | Time only |
|
|
60
|
+
|-----------|-----------|
|
|
61
|
+
|  |  |
|
|
62
|
+
|
|
63
|
+
| Combined date & time | Separate view (tabs) |
|
|
64
|
+
|----------------------|----------------------|
|
|
65
|
+
|  |  |
|
|
66
|
+
|
|
67
|
+
| Date range | French locale · week starts Monday |
|
|
68
|
+
|------------|------------------------------------|
|
|
69
|
+
|  |  |
|
|
70
|
+
|
|
71
|
+
| Dark theme | Popover input |
|
|
72
|
+
|------------|---------------|
|
|
73
|
+
|  |  |
|
|
74
|
+
|
|
75
|
+
## Quick start (React)
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { useState } from "react";
|
|
79
|
+
import DateTime, { DateTimeInput } from "universal-datetime-picker";
|
|
80
|
+
import "universal-datetime-picker/style.css";
|
|
81
|
+
|
|
82
|
+
function App() {
|
|
83
|
+
// Prefer asString={false} for Date / TimeValue (recommended going forward)
|
|
84
|
+
const [value, setValue] = useState<Date | null>(null);
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<>
|
|
88
|
+
<DateTimeInput asString={false} value={value} onChange={setValue} />
|
|
89
|
+
<DateTime inline asString={false} value={value} onChange={setValue} />
|
|
90
|
+
</>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Vanilla JS
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { createDateTimePicker } from "universal-datetime-picker/vanilla";
|
|
99
|
+
import "universal-datetime-picker/style.css";
|
|
100
|
+
|
|
101
|
+
const root = document.getElementById("picker")!;
|
|
102
|
+
const handle = createDateTimePicker(root, {
|
|
103
|
+
inline: true,
|
|
104
|
+
mode: "date",
|
|
105
|
+
asString: false,
|
|
106
|
+
onChange: (value) => console.log(value),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// later: handle.update({ open: false }); handle.destroy();
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## CDN / Web Components
|
|
113
|
+
|
|
114
|
+
```html
|
|
115
|
+
<link
|
|
116
|
+
rel="stylesheet"
|
|
117
|
+
href="https://cdn.jsdelivr.net/npm/universal-datetime-picker/style.css"
|
|
118
|
+
/>
|
|
119
|
+
<script src="https://cdn.jsdelivr.net/npm/universal-datetime-picker"></script>
|
|
120
|
+
|
|
121
|
+
<datetime-picker inline mode="date" as-string="false"></datetime-picker>
|
|
122
|
+
<script>
|
|
123
|
+
document
|
|
124
|
+
.querySelector("datetime-picker")
|
|
125
|
+
.addEventListener("change", (e) => console.log(e.detail));
|
|
126
|
+
</script>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Or register from npm:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { defineCustomElements } from "universal-datetime-picker/wc";
|
|
133
|
+
import "universal-datetime-picker/style.css";
|
|
134
|
+
defineCustomElements();
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Custom elements: `<datetime-picker>`, `<datetime-picker-input>`, `<datetime-picker-range>`. They dispatch a bubbling `change` `CustomEvent` whose `detail` is the picker value.
|
|
138
|
+
|
|
139
|
+
## Vue
|
|
140
|
+
|
|
141
|
+
Register once in `main.ts`, then use tags in SFCs. Configure Vue so `datetime-picker*` tags are treated as custom elements.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
// main.ts
|
|
145
|
+
import { createApp } from "vue";
|
|
146
|
+
import App from "./App.vue";
|
|
147
|
+
import { defineCustomElements } from "universal-datetime-picker/vue";
|
|
148
|
+
import "universal-datetime-picker/style.css";
|
|
149
|
+
|
|
150
|
+
defineCustomElements();
|
|
151
|
+
|
|
152
|
+
createApp(App)
|
|
153
|
+
.config.compilerOptions.isCustomElement = (tag) =>
|
|
154
|
+
tag.startsWith("datetime-picker")
|
|
155
|
+
.mount("#app");
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
```vue
|
|
159
|
+
<template>
|
|
160
|
+
<datetime-picker
|
|
161
|
+
inline
|
|
162
|
+
mode="date"
|
|
163
|
+
as-string="false"
|
|
164
|
+
@change="onChange"
|
|
165
|
+
/>
|
|
166
|
+
</template>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
More examples: [Vue demo](https://universal-datetime-picker.vercel.app/vue/) on the docs site.
|
|
170
|
+
|
|
171
|
+
## Svelte
|
|
172
|
+
|
|
173
|
+
Register once in root `+layout.ts` (or app entry), not in every component.
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
// src/routes/+layout.ts
|
|
177
|
+
import { defineCustomElements } from "universal-datetime-picker/svelte";
|
|
178
|
+
import "universal-datetime-picker/style.css";
|
|
179
|
+
|
|
180
|
+
defineCustomElements();
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```svelte
|
|
184
|
+
<datetime-picker
|
|
185
|
+
inline
|
|
186
|
+
mode="date"
|
|
187
|
+
as-string="false"
|
|
188
|
+
on:change={(e) => console.log(e.detail)}
|
|
189
|
+
/>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
More examples: [Svelte demo](https://universal-datetime-picker.vercel.app/svelte/) on the docs site.
|
|
193
|
+
|
|
194
|
+
## Angular
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
import { registerDateTimePickerElements } from "universal-datetime-picker/angular";
|
|
198
|
+
import "universal-datetime-picker/style.css";
|
|
199
|
+
|
|
200
|
+
registerDateTimePickerElements();
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Add `CUSTOM_ELEMENTS_SCHEMA` to your NgModule or standalone component, then use `<datetime-picker>`, `<datetime-picker-input>`, or `<datetime-picker-range>` in templates. Listen with `(change)="onChange($event.detail)"`.
|
|
204
|
+
|
|
205
|
+
## Components
|
|
206
|
+
|
|
207
|
+
| Export | Description |
|
|
208
|
+
|--------|-------------|
|
|
209
|
+
| `DateTime` | React datetime / date / time picker (overlay or inline) |
|
|
210
|
+
| `DateTime.Input` / `DateTimeInput` | Date time input that opens a popover calendar |
|
|
211
|
+
| `DateTime.Range` / `DateTimeRange` | React date range picker |
|
|
212
|
+
|
|
213
|
+
## Return values
|
|
214
|
+
|
|
215
|
+
`onChange` shape depends on `mode` and `asString`:
|
|
216
|
+
|
|
217
|
+
| Mode / flags | `asString` | `onChange` receives |
|
|
218
|
+
|--------------|------------|---------------------|
|
|
219
|
+
| `mode="date"` | `false` | `Date` (start of day) |
|
|
220
|
+
| `mode="datetime"` | `false` | `Date` |
|
|
221
|
+
| `mode="time"` | `false` | `TimeValue` object |
|
|
222
|
+
| any mode | `true` / omitted | formatted `string \| null` |
|
|
223
|
+
| range | `false` | `{ start: Date \| null; end: Date \| null }` |
|
|
224
|
+
| range | `true` / omitted | `{ start: string \| null; end: string \| null }` |
|
|
225
|
+
|
|
226
|
+
**Deprecation:** omitting `asString` still returns a formatted string today, but logs a one-time console warning. Set `asString={true}` to keep strings explicitly, or `asString={false}` to opt into `Date` / `TimeValue` now. A future major release will default to objects.
|
|
227
|
+
|
|
228
|
+
### `TimeValue` (`mode="time"`, `asString={false}`)
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
{
|
|
232
|
+
hour: 2, // 1–12
|
|
233
|
+
hour24: 14, // 0–23
|
|
234
|
+
minute: 30,
|
|
235
|
+
second: 0,
|
|
236
|
+
ampm: "PM",
|
|
237
|
+
formatted: "14:30:00" // or "02:30:00 PM" when use12Hours
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
<DateTime
|
|
243
|
+
inline
|
|
244
|
+
mode="time"
|
|
245
|
+
asString={false}
|
|
246
|
+
onChange={(value) => {
|
|
247
|
+
// value is TimeValue | null
|
|
248
|
+
console.log(value?.hour24, value?.formatted);
|
|
249
|
+
}}
|
|
250
|
+
/>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Props
|
|
254
|
+
|
|
255
|
+
### Shared (`DateTime` / `DateTimeInput`)
|
|
256
|
+
|
|
257
|
+
| Prop | Type | Default | Description |
|
|
258
|
+
|------|------|---------|-------------|
|
|
259
|
+
| `value` | `Date \| string \| Dayjs \| null` | — | Controlled value |
|
|
260
|
+
| `defaultValue` | same | — | Uncontrolled initial value |
|
|
261
|
+
| `onChange` | `(value: Date \| TimeValue \| string \| null) => void` | — | Fired on OK / Clear |
|
|
262
|
+
| `asString` | `boolean` | omitted → string (deprecated) | `true` = string; `false` = `Date` / `TimeValue` |
|
|
263
|
+
| `showSeconds` | `boolean` | `true` | Show seconds column; included in default format |
|
|
264
|
+
| `format` | `string` | derived from mode | dayjs format (auto from mode / `use12Hours` / `showSeconds` when omitted) |
|
|
265
|
+
| `mode` | `"datetime" \| "date" \| "time"` | `"datetime"` | Picker mode |
|
|
266
|
+
| `layout` | `"combined" \| "tabs"` | `"combined"` | When `mode="datetime"`: show both panels, or Date/Time tabs. Hidden for date-only / time-only |
|
|
267
|
+
| `minDate` / `maxDate` | date-like | — | Inclusive bounds |
|
|
268
|
+
| `disablePastDates` | `boolean` | `false` | Disable days before today |
|
|
269
|
+
| `disableFutureDates` | `boolean` | `false` | Disable days after today |
|
|
270
|
+
| `weekStartsOn` | `0–6` | `0` | First day of week (0 = Sunday) |
|
|
271
|
+
| `use12Hours` | `boolean` | `false` | 12-hour clock with AM/PM (`false` = 24-hour) |
|
|
272
|
+
| `locale` | `string` | `"en"` | dayjs locale (import locale first) |
|
|
273
|
+
| `labels` | `DateTimeLabels` | English defaults | Override chrome strings |
|
|
274
|
+
| `theme` | `"light" \| "dark"` | — | Force theme (useful for portaled popovers) |
|
|
275
|
+
| `inline` | `boolean` | `false` | Render without overlay |
|
|
276
|
+
| `className` | `string` | — | Root class |
|
|
277
|
+
|
|
278
|
+
### Overlay control
|
|
279
|
+
|
|
280
|
+
| Prop | Type | Description |
|
|
281
|
+
|------|------|-------------|
|
|
282
|
+
| `open` / `defaultOpen` | `boolean` | Controlled / uncontrolled open state |
|
|
283
|
+
| `onOpenChange` | `(open: boolean) => void` | Open state changes |
|
|
284
|
+
| `popover` | `boolean` | Position near `anchorEl` instead of fullscreen |
|
|
285
|
+
| `anchorEl` | `HTMLElement \| null` | Anchor for popover |
|
|
286
|
+
|
|
287
|
+
`DateTimeInput` always uses popover mode. The popover uses `position: fixed`, flips above the input when needed, repositions on scroll/resize, and closes on outside click or Escape. Time-only popovers use a compact width.
|
|
288
|
+
|
|
289
|
+
### Use any button or input as the trigger
|
|
290
|
+
|
|
291
|
+
Control `open` yourself to open the picker from any element. Add `popover` and pass the trigger element through `anchorEl` to position the picker beside it.
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
import { useState } from "react";
|
|
295
|
+
import { DateTime } from "universal-datetime-picker";
|
|
296
|
+
|
|
297
|
+
function CustomDateTrigger() {
|
|
298
|
+
const [open, setOpen] = useState(false);
|
|
299
|
+
const [value, setValue] = useState<Date | null>(null);
|
|
300
|
+
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
|
301
|
+
|
|
302
|
+
return (
|
|
303
|
+
<>
|
|
304
|
+
<button
|
|
305
|
+
ref={setAnchorEl}
|
|
306
|
+
type="button"
|
|
307
|
+
onClick={() => setOpen(true)}
|
|
308
|
+
aria-haspopup="dialog"
|
|
309
|
+
aria-expanded={open}
|
|
310
|
+
>
|
|
311
|
+
{value ? value.toLocaleDateString() : "Choose a date"}
|
|
312
|
+
</button>
|
|
313
|
+
|
|
314
|
+
<DateTime
|
|
315
|
+
mode="date"
|
|
316
|
+
open={open}
|
|
317
|
+
onOpenChange={setOpen}
|
|
318
|
+
popover
|
|
319
|
+
anchorEl={anchorEl}
|
|
320
|
+
asString={false}
|
|
321
|
+
value={value}
|
|
322
|
+
onChange={(next) => setValue(next instanceof Date ? next : null)}
|
|
323
|
+
/>
|
|
324
|
+
</>
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Leave out `popover` and `anchorEl` to open the same picker as a centered modal:
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
<button type="button" onClick={() => setOpen(true)}>
|
|
333
|
+
Choose a date
|
|
334
|
+
</button>
|
|
335
|
+
<DateTime
|
|
336
|
+
mode="date"
|
|
337
|
+
open={open}
|
|
338
|
+
onOpenChange={setOpen}
|
|
339
|
+
asString={false}
|
|
340
|
+
onChange={setValue}
|
|
341
|
+
/>
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### `DateTimeInput` extras
|
|
345
|
+
|
|
346
|
+
`placeholder`, `id`, `name`, `disabled`, `readOnly`, `aria-label`, `aria-labelledby`, `inputClassName`
|
|
347
|
+
|
|
348
|
+
### `DateTimeRange`
|
|
349
|
+
|
|
350
|
+
Supports `asString` like the single picker. With `asString={false}`, `onChange` receives `{ start: Date | null; end: Date | null }`; with `asString={true}` (or omitted), ends are formatted strings. Also supports keyboard grid navigation, hover range preview, and the same `locale` / `weekStartsOn` / `labels` props.
|
|
351
|
+
|
|
352
|
+
### Labels
|
|
353
|
+
|
|
354
|
+
```tsx
|
|
355
|
+
<DateTime
|
|
356
|
+
inline
|
|
357
|
+
labels={{ ok: "Confirm", clear: "Wipe", close: "Dismiss", date: "Jour" }}
|
|
358
|
+
/>
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Layout
|
|
362
|
+
|
|
363
|
+
By default (`layout="combined"`), datetime mode shows the calendar and time controls together — no Date/Time badges. Use `layout="tabs"` for the classic switcher. When `mode` is `"date"` or `"time"`, the badges are never shown.
|
|
364
|
+
|
|
365
|
+
```tsx
|
|
366
|
+
{/* Default: both panels */}
|
|
367
|
+
<DateTime inline mode="datetime" asString={false} onChange={setValue} />
|
|
368
|
+
|
|
369
|
+
{/* Classic tabs */}
|
|
370
|
+
<DateTime inline mode="datetime" layout="tabs" asString={false} onChange={setValue} />
|
|
371
|
+
|
|
372
|
+
{/* Date only — no badges */}
|
|
373
|
+
<DateTime inline mode="date" asString={false} onChange={setValue} />
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## 12-hour clock & seconds
|
|
377
|
+
|
|
378
|
+
`use12Hours` switches the time UI to AM/PM (`false` keeps 24-hour). When `format` is omitted, it is derived from `mode`, `use12Hours`, and `showSeconds`:
|
|
379
|
+
|
|
380
|
+
```tsx
|
|
381
|
+
{/* 12-hour with seconds */}
|
|
382
|
+
<DateTimeInput asString use12Hours value={value} onChange={setValue} />
|
|
383
|
+
|
|
384
|
+
{/* 24-hour, no seconds */}
|
|
385
|
+
<DateTime inline mode="time" showSeconds={false} asString={false} onChange={setTime} />
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## Theming
|
|
389
|
+
|
|
390
|
+
Override CSS variables (light defaults shown):
|
|
391
|
+
|
|
392
|
+
```css
|
|
393
|
+
:root {
|
|
394
|
+
--ctp-primary: #7cb342;
|
|
395
|
+
--ctp-primary-dark: #558b2f;
|
|
396
|
+
--ctp-surface: #ffffff;
|
|
397
|
+
--ctp-fg: #1f2937;
|
|
398
|
+
--ctp-border: #e5e7eb;
|
|
399
|
+
--ctp-focus: #7cb342;
|
|
400
|
+
--ctp-danger: #dc2626;
|
|
401
|
+
--ctp-selected-bg: #558b2f;
|
|
402
|
+
--ctp-selected-fg: #ffffff;
|
|
403
|
+
--ctp-hover-bg: color-mix(in srgb, var(--ctp-primary) 16%, white);
|
|
404
|
+
--ctp-range-bg: color-mix(in srgb, var(--ctp-primary) 28%, white);
|
|
405
|
+
--ctp-z-index: 1000;
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Dark theme
|
|
410
|
+
|
|
411
|
+
Wrap the picker (or a parent) with `data-ctp-theme="dark"`:
|
|
412
|
+
|
|
413
|
+
```tsx
|
|
414
|
+
<div data-ctp-theme="dark">
|
|
415
|
+
<DateTime inline mode="time" onChange={setValue} />
|
|
416
|
+
<DateTimeInput mode="time" onChange={setValue} />
|
|
417
|
+
</div>
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
Inline pickers inherit theme from the wrapper. Portaled popovers/overlays copy `data-ctp-theme` from the input’s ancestors (or accept an explicit `theme="dark"` prop) so time and datetime popovers stay dark too.
|
|
421
|
+
|
|
422
|
+
Focusable controls use `:focus-visible` rings via `--ctp-focus`. Open animation respects `prefers-reduced-motion`.
|
|
423
|
+
|
|
424
|
+
## Locales
|
|
425
|
+
|
|
426
|
+
Locales are applied per instance (no global dayjs locale mutation). Import the dayjs locale module before use:
|
|
427
|
+
|
|
428
|
+
```tsx
|
|
429
|
+
import "dayjs/locale/fr";
|
|
430
|
+
import { DateTime } from "universal-datetime-picker";
|
|
431
|
+
|
|
432
|
+
<DateTime locale="fr" weekStartsOn={1} inline onChange={console.log} />
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## Migrating from react-calendar-time
|
|
436
|
+
|
|
437
|
+
The package was renamed to **universal-datetime-picker** in v2.0.0.
|
|
438
|
+
|
|
439
|
+
1. Update your dependency: `npm install universal-datetime-picker` (remove `react-calendar-time`).
|
|
440
|
+
2. Change import specifiers from `react-calendar-time` to `universal-datetime-picker` (including subpaths like `/vanilla`, `/wc`, `/style.css`).
|
|
441
|
+
3. Web Components are now `<datetime-picker>`, `<datetime-picker-input>`, and `<datetime-picker-range>` (previously `<calendar-time>` etc.).
|
|
442
|
+
4. React **17** is no longer supported; use React **18+** or use vanilla / Web Components / CDN without React peers.
|
|
443
|
+
|
|
444
|
+
Props, CSS class names (`ctp-*`), and React component exports are unchanged.
|
|
445
|
+
|
|
446
|
+
## Contributing
|
|
447
|
+
|
|
448
|
+
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, scripts, and PR guidelines.
|
|
449
|
+
|
|
450
|
+
## License
|
|
451
|
+
|
|
452
|
+
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { defineCustomElements } from '../wc/index.mjs';
|
|
2
|
+
import '../rangeRenderer-AVv6PJbW.mjs';
|
|
3
|
+
import '../rangeController-Bq35aBwe.mjs';
|
|
4
|
+
import 'dayjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Call once (e.g. in AppModule or main.ts) and add CUSTOM_ELEMENTS_SCHEMA
|
|
8
|
+
* so Angular templates can use <datetime-picker>, <datetime-picker-input>,
|
|
9
|
+
* and <datetime-picker-range>.
|
|
10
|
+
*/
|
|
11
|
+
declare function registerDateTimePickerElements(): void;
|
|
12
|
+
/** @deprecated Use registerDateTimePickerElements */
|
|
13
|
+
declare function registerCalendarTimeElements(): void;
|
|
14
|
+
|
|
15
|
+
export { registerCalendarTimeElements, registerDateTimePickerElements };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { defineCustomElements } from '../wc/index.js';
|
|
2
|
+
import '../rangeRenderer-a3hFk-kK.js';
|
|
3
|
+
import '../rangeController-Bq35aBwe.js';
|
|
4
|
+
import 'dayjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Call once (e.g. in AppModule or main.ts) and add CUSTOM_ELEMENTS_SCHEMA
|
|
8
|
+
* so Angular templates can use <datetime-picker>, <datetime-picker-input>,
|
|
9
|
+
* and <datetime-picker-range>.
|
|
10
|
+
*/
|
|
11
|
+
declare function registerDateTimePickerElements(): void;
|
|
12
|
+
/** @deprecated Use registerDateTimePickerElements */
|
|
13
|
+
declare function registerCalendarTimeElements(): void;
|
|
14
|
+
|
|
15
|
+
export { registerCalendarTimeElements, registerDateTimePickerElements };
|