@pglejzer/datepicker-ui 1.0.0 → 1.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.
package/README.md CHANGED
@@ -7,7 +7,7 @@ A date picker for web forms. Attach it to an `<input>` and users pick a date, a
7
7
  [![license](https://img.shields.io/badge/license-MIT-green.svg)](https://img.shields.io/npm/l/@pglejzer/datepicker-ui)
8
8
  [![Coverage Status](https://coveralls.io/repos/github/pglejzer/datepicker-ui/badge.svg?branch=main)](https://coveralls.io/github/pglejzer/datepicker-ui?branch=main)
9
9
  [![CI](https://github.com/pglejzer/datepicker-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/pglejzer/datepicker-ui/actions/workflows/ci.yml)
10
- [![Socket Badge](https://badge.socket.dev/npm/package/@pglejzer/datepicker-ui/1.0.0)](https://badge.socket.dev/npm/package/@pglejzer/datepicker-ui/1.0.0)
10
+ [![Socket Badge](https://badge.socket.dev/npm/package/@pglejzer/datepicker-ui/1.1.0)](https://badge.socket.dev/npm/package/@pglejzer/datepicker-ui/1.1.0)
11
11
 
12
12
  [Live demo](https://timepicker-ui.vercel.app/datepicker) · [Documentation](https://timepicker-ui.vercel.app/datepicker/quick-start) · [Changelog](./CHANGELOG.md) · [timepicker-ui](https://timepicker-ui.vercel.app)
13
13
 
@@ -25,7 +25,7 @@ A date picker for web forms. Attach it to an `<input>` and users pick a date, a
25
25
 
26
26
  - [Single date, range and multiple dates](https://timepicker-ui.vercel.app/datepicker/docs/selection-modes), with [range limits](https://timepicker-ui.vercel.app/datepicker/examples/selection/range-limits)
27
27
  - [Docked popover](https://timepicker-ui.vercel.app/datepicker/examples/basic/docked), [modal dialog](https://timepicker-ui.vercel.app/datepicker/examples/basic/modal) and [inline calendar](https://timepicker-ui.vercel.app/datepicker/examples/basic/inline), with a full-screen range picker on small screens ([display modes](https://timepicker-ui.vercel.app/datepicker/docs/display-modes))
28
- - [Typed input](https://timepicker-ui.vercel.app/datepicker/docs/typed-input) with an opt-in mask, and a switch between the calendar and the input view
28
+ - [Typed input](https://timepicker-ui.vercel.app/datepicker/docs/typed-input) with an opt-in mask for the page input, and a switch between the calendar and an input view that always formats typed digits
29
29
  - [Several months side by side](https://timepicker-ui.vercel.app/datepicker/examples/features/several-months)
30
30
  - [Range presets](https://timepicker-ui.vercel.app/datepicker/examples/selection/range-presets) and [two fields for a range](https://timepicker-ui.vercel.app/datepicker/examples/selection/two-fields)
31
31
  - [Month and year pickers](https://timepicker-ui.vercel.app/datepicker/docs/precision)
@@ -50,7 +50,7 @@ From a CDN, the UMD build exposes the class as the global `DatepickerUI`. More i
50
50
  ```
51
51
 
52
52
  ```js
53
- import DatepickerUI from "@pglejzer/datepicker-ui";
53
+ import { DatepickerUI } from "@pglejzer/datepicker-ui";
54
54
  import "@pglejzer/datepicker-ui/index.css";
55
55
 
56
56
  const picker = new DatepickerUI("#date", {
@@ -64,6 +64,8 @@ const picker = new DatepickerUI("#date", {
64
64
  picker.create();
65
65
  ```
66
66
 
67
+ `DatepickerUI` is a named export, and also the default export, so `import DatepickerUI from "@pglejzer/datepicker-ui"` works too.
68
+
67
69
  The first argument is a selector, an `<input>` or an element that contains an `<input>`. The options argument is optional. Step by step: [quick start](https://timepicker-ui.vercel.app/datepicker/quick-start) and [getting started example](https://timepicker-ui.vercel.app/datepicker/examples/basic/getting-started).
68
70
 
69
71
  ## API
@@ -74,14 +76,21 @@ picker.open();
74
76
  picker.close();
75
77
  picker.destroy({ keepInputValue: true });
76
78
  picker.getValue(); // DateValue, { start, end }, DateValue[] or null, by calendar.mode
77
- picker.setValue("2025-03-14"); // a Date or an ISO string; { start, end } or an array in other modes
79
+ picker.setValue("2025-03-14"); // a Date, an ISO string or "today"; { start, end } or an array in other modes
78
80
  picker.setOptions({ ui: { theme: "crane" } });
79
81
  picker.setActiveEnd("end"); // range mode: the end the next pick sets
82
+ picker.clear(); // empty the value, emits "clear" and the input's input + change events
83
+ picker.setValue(null); // empty the value quietly, without those events
84
+ picker.setView("input"); // "calendar" | "input", switch the view
85
+ picker.getView();
86
+ picker.goTo("2025-06-01"); // show that month without selecting
87
+ picker.getVisibleRange(); // { from, to } first and last day shown, or null
88
+ picker.isSelectable("2025-03-14"); // checks a day, a range or an array against every rule
80
89
  picker.getElement(); // the .dp-ui host element
81
90
 
82
91
  const off = picker.on("confirm", ({ value }) => {}); // on() and once() return a function that removes the handler
83
92
  off();
84
- picker.on("cancel", ({ reason }) => {});
93
+ picker.on("cancel", ({ reason }) => {}); // "button" | "escape" | "outside" | "toggle"
85
94
  picker.on("open", ({ mode }) => {});
86
95
  picker.on("close", () => {});
87
96
  picker.on("update", ({ options }) => {});
@@ -89,7 +98,9 @@ picker.on("error", ({ code, message }) => {});
89
98
  picker.on("select:day", ({ value, selected }) => {});
90
99
  picker.on("select:month", ({ year, month }) => {});
91
100
  picker.on("select:year", ({ year }) => {});
92
- picker.on("navigate", ({ year, month, direction, source }) => {});
101
+ picker.on("navigate", ({ year, month, direction, source, from, to }) => {}); // source: drag, wheel, button, keyboard, menu, open, api, resize, scroll
102
+ picker.on("switch:view", ({ view }) => {});
103
+ picker.on("clear", ({ previousValue }) => {});
93
104
  picker.on("range:start", ({ value }) => {});
94
105
  picker.on("range:end", ({ start, end }) => {});
95
106
  picker.once("confirm", handler);
@@ -100,6 +111,8 @@ DatepickerUI.getAllInstances();
100
111
  DatepickerUI.destroyAll();
101
112
  ```
102
113
 
114
+ The main entry also exports the types `PickerView`, `SwitchViewEventData`, `ClearEventData`, `VisibleRange`, `NavigateSource` and `CancelReason`.
115
+
103
116
  Docs: [methods](https://timepicker-ui.vercel.app/datepicker/api/methods), [events](https://timepicker-ui.vercel.app/datepicker/api/events), [events example](https://timepicker-ui.vercel.app/datepicker/examples/advanced/events), [external API example](https://timepicker-ui.vercel.app/datepicker/examples/advanced/external-api)
104
117
 
105
118
  ## Options
@@ -110,9 +123,10 @@ Grouped by area into `calendar`, `ui`, `labels`, `behavior` and `callbacks`. Pas
110
123
  new DatepickerUI(input, {
111
124
  calendar: {
112
125
  mode: "single" | "range" | "multiple", // default "single"
126
+ defaultValue: "today", // starting value of an empty input, shape of setValue()
113
127
  range: { minLength, maxLength, presets: [] },
114
128
  multiple: { max },
115
- months: 1, // months side by side, docked and inline
129
+ months: 1, // months side by side, docked look
116
130
  precision: "day" | "month" | "year", // default "day", single mode only
117
131
  locale: "en-GB", // default: page locale
118
132
  minDate: "today", maxDate: "2026-12-31",
@@ -124,7 +138,13 @@ new DatepickerUI(input, {
124
138
  },
125
139
  ui: {
126
140
  displayMode: "auto" | "docked" | "modal", // default "auto"
127
- inline: { enabled: false, container: "#calendar" | element },
141
+ layout: "auto" | "docked" | "modal" | "fullscreen", // look on any surface, default "auto"
142
+ inline: {
143
+ enabled: false, container: "#calendar" | element,
144
+ headline: true, // false hides the inline headline
145
+ navigation: "menus" | "caption", // "caption": text next to the arrows, no menus
146
+ announceSelection: true, // false leaves selection announcements to the host
147
+ },
128
148
  format: "auto" | "dd.MM.yyyy",
129
149
  theme: "basic" | "m3-green" | "crane" | "blueprint" | ...,
130
150
  colorScheme: "auto" | "light" | "dark", // default "auto"
@@ -134,13 +154,13 @@ new DatepickerUI(input, {
134
154
  mask: false,
135
155
  cssClass: "",
136
156
  },
137
- labels: { title, confirm, cancel, today, clear, previousMonth, nextMonth, invalidDate, ... },
157
+ labels: { title, confirm, cancel, today, clear, previousMonth, nextMonth, invalidDate, inRange, ... },
138
158
  behavior: { closeOnSelect: false, commitOnChange: false, returnFocus: true, id: "" },
139
- callbacks: { onOpen, onClose, onCancel, onConfirm, onUpdate, onError, onSelectDay, onSelectMonth, onSelectYear, onNavigate, onRangeStart, onRangeEnd },
159
+ callbacks: { onOpen, onClose, onCancel, onConfirm, onUpdate, onError, onSelectDay, onSelectMonth, onSelectYear, onNavigate, onRangeStart, onRangeEnd, onSwitchView, onClear },
140
160
  });
141
161
  ```
142
162
 
143
- An invalid value falls back to the default and emits an `error` event with code `invalid-option`. More on [layouts](https://timepicker-ui.vercel.app/datepicker/docs/layouts) and [changing options at runtime](https://timepicker-ui.vercel.app/datepicker/examples/advanced/set-options).
163
+ With `ui.displayMode: "auto"`, a docked picker that fits neither below nor above the field opens as a dialog, so the result depends on where the field is on the page. An invalid value falls back to the default and emits an `error` event with code `invalid-option`. More on [layouts](https://timepicker-ui.vercel.app/datepicker/docs/layouts) and [changing options at runtime](https://timepicker-ui.vercel.app/datepicker/examples/advanced/set-options).
144
164
 
145
165
  ## Themes
146
166
 
@@ -157,13 +177,17 @@ new DatepickerUI("#date", { ui: { theme: "m2" } });
157
177
 
158
178
  Or import `@pglejzer/datepicker-ui/index.css` to get the core and every theme. Writing your own theme: [themes guide](https://timepicker-ui.vercel.app/datepicker/docs/themes), [custom theme example](https://timepicker-ui.vercel.app/datepicker/examples/themes/custom-theme), [CSS classes](https://timepicker-ui.vercel.app/datepicker/api/css-classes) and [CSS variables](https://timepicker-ui.vercel.app/datepicker/api/css-variables).
159
179
 
180
+ New classes: `dp-ui__calendar--modal`, `dp-ui__navigation--caption` with `dp-ui__caption`, and `dp-ui__presets--column`, which gives a presets group outside the picker the column look. `--dp-ui-date-container-min-size` (36px) and `--dp-ui-date-container-max-size` (48px) bound the day cell size.
181
+
182
+ An inline picker narrows to fit its container, down to 36px cells, and scrolls sideways below that. The container needs a width that does not come from the picker: a flex or grid item needs `min-width: 0`, and a centered grid item or an `inline-block` also needs `width: 100%`.
183
+
160
184
  ## Frameworks
161
185
 
162
186
  React:
163
187
 
164
188
  ```tsx
165
189
  import { useEffect, useRef } from "react";
166
- import DatepickerUI from "@pglejzer/datepicker-ui";
190
+ import { DatepickerUI } from "@pglejzer/datepicker-ui";
167
191
  import "@pglejzer/datepicker-ui/index.css";
168
192
 
169
193
  function DateField() {
@@ -184,10 +208,20 @@ The same pattern works in Vue, Svelte and Angular. See the [frameworks and SSR g
184
208
 
185
209
  `@pglejzer/datepicker-ui/kit` is a second entry for packages built on top of the picker. It exports the popover, dialog and inline surfaces (`PopoverHost`, `DialogHost`, `InlineHost`), the rule that picks docked or modal (`resolveSurfaceMode`), color scheme detection and the date text helpers (`parseDate`, `formatDate`, `resolvePattern`, `maskDateText`). Like the main entry, it is safe to import during server rendering. See the [kit guide](https://timepicker-ui.vercel.app/datepicker/docs/kit).
186
210
 
211
+ Also exported:
212
+
213
+ - `applyTheme` and the `SurfaceTheme` type write the theme, color scheme, extra classes and right-to-left state onto a surface root.
214
+ - `createTextButton` builds the picker's text button.
215
+ - `fitsViewport(root, anchor)` tells whether a docked surface fits the window entirely below or entirely above its anchor.
216
+ - `Pager` and `PagerOptions` give the month paging with its drag and wheel gestures.
217
+ - `RANGE_SEPARATOR` and `splitRangeText` write and split range text.
218
+ - `leadingDateLength`, `isDateTextComplete` and `normalizeDigits` help with typed dates.
219
+ - `resolveWeekStart`, `weekdayNames`, `formatMonthYear` and `formatFullDate` are the calendar's week and name helpers. `formatFullDate(date, locale, { year: false })` leaves the year out.
220
+ - The hosts accept a `labelledBy` option, the id of a visible title that names the surface. `setLabel(label, labelledBy?)` renames a shown surface by the same rule.
221
+
187
222
  ```js
188
223
  import { parseDate, resolvePattern } from "@pglejzer/datepicker-ui/kit";
189
224
  ```
190
-
191
225
  ## Need a time picker?
192
226
 
193
227
  [timepicker-ui](https://timepicker-ui.vercel.app) is the companion time picker from the same author. It has no dependencies and uses the same theme names, so the two pickers match.