timepicker-ui 3.2.0 → 4.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/README.md +401 -73
- package/dist/css/index.css +1 -1
- package/dist/css/main.css +1 -1
- package/dist/css/themes/theme-ai.css +1 -1
- package/dist/css/themes/theme-crane-straight.css +1 -1
- package/dist/css/themes/theme-crane.css +1 -1
- package/dist/css/themes/theme-cyberpunk.css +1 -1
- package/dist/css/themes/theme-dark.css +1 -1
- package/dist/css/themes/theme-glassmorphic.css +1 -1
- package/dist/css/themes/theme-m2.css +1 -1
- package/dist/css/themes/theme-m3-green.css +1 -1
- package/dist/css/themes/theme-pastel.css +1 -1
- package/dist/index.cjs +1 -56
- package/dist/index.d.cts +435 -603
- package/dist/index.d.ts +435 -603
- package/dist/index.js +1 -56
- package/dist/index.umd.js +1 -1
- package/package.json +2 -3
- package/dist/css/themes/theme-custom.css +0 -1
package/README.md
CHANGED
|
@@ -8,11 +8,12 @@ Modern time picker library built with TypeScript. Works with any framework or va
|
|
|
8
8
|
|
|
9
9
|
[Live Demo](https://timepicker-ui.vercel.app/) • [Documentation](https://timepicker-ui.vercel.app/docs) • [Changelog](./CHANGELOG.md)
|
|
10
10
|
|
|
11
|
-
**Upgrading from
|
|
11
|
+
**Upgrading from v3?** Check the [upgrade guide](#upgrade-guide-v3--v4) below.
|
|
12
|
+
**Upgrading from v2?** Check the [v2 → v3 upgrade guide](#upgrade-guide-v2--v3).
|
|
12
13
|
|
|
13
14
|
## Features
|
|
14
15
|
|
|
15
|
-
-
|
|
16
|
+
- 10 built-in themes (Material, Crane, Dark, Glassmorphic, Cyberpunk, and more)
|
|
16
17
|
- Mobile-first design with touch support
|
|
17
18
|
- Framework agnostic - works with React, Vue, Angular, Svelte, or vanilla JS
|
|
18
19
|
- Full TypeScript support
|
|
@@ -25,10 +26,9 @@ Modern time picker library built with TypeScript. Works with any framework or va
|
|
|
25
26
|
|
|
26
27
|
This project is actively maintained. Some areas planned for improvement:
|
|
27
28
|
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
- No performance monitoring
|
|
29
|
+
- Unit/integration test coverage could be expanded
|
|
30
|
+
- Performance monitoring tooling
|
|
31
|
+
- Further TypeScript strictness improvements
|
|
32
32
|
|
|
33
33
|
Contributions welcome! Feel free to [open an issue or PR](https://github.com/pglejzer/timepicker-ui/issues).
|
|
34
34
|
|
|
@@ -73,12 +73,18 @@ picker.create();
|
|
|
73
73
|
|
|
74
74
|
```javascript
|
|
75
75
|
const picker = new TimepickerUI(input, {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
ui: {
|
|
77
|
+
theme: "dark",
|
|
78
|
+
animation: true,
|
|
79
|
+
backdrop: true,
|
|
80
|
+
},
|
|
81
|
+
clock: {
|
|
82
|
+
type: "24h",
|
|
83
|
+
},
|
|
84
|
+
callbacks: {
|
|
85
|
+
onConfirm: (data) => {
|
|
86
|
+
console.log("Selected time:", data);
|
|
87
|
+
},
|
|
82
88
|
},
|
|
83
89
|
});
|
|
84
90
|
picker.create();
|
|
@@ -97,8 +103,9 @@ function TimePickerComponent() {
|
|
|
97
103
|
useEffect(() => {
|
|
98
104
|
if (inputRef.current) {
|
|
99
105
|
const picker = new TimepickerUI(inputRef.current, {
|
|
100
|
-
|
|
101
|
-
|
|
106
|
+
callbacks: {
|
|
107
|
+
onConfirm: (data) => {
|
|
108
|
+
console.log("Time selected:", data);
|
|
102
109
|
},
|
|
103
110
|
});
|
|
104
111
|
picker.create();
|
|
@@ -115,49 +122,161 @@ function TimePickerComponent() {
|
|
|
115
122
|
|
|
116
123
|
Full documentation available at [timepicker-ui.vercel.app/docs](https://timepicker-ui.vercel.app/docs)
|
|
117
124
|
|
|
118
|
-
###
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
|
135
|
-
|
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
|
146
|
-
|
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
152
|
-
| `
|
|
153
|
-
| `
|
|
154
|
-
| `
|
|
155
|
-
| `
|
|
156
|
-
| `
|
|
157
|
-
| `
|
|
158
|
-
| `
|
|
159
|
-
|
|
160
|
-
|
|
125
|
+
### Options Structure (v4.0.0 Breaking Change)
|
|
126
|
+
|
|
127
|
+
**Options are now organized into 5 logical groups:**
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
const picker = new TimepickerUI(input, {
|
|
131
|
+
clock: ClockOptions, // Clock behavior (type, increments, disabled time)
|
|
132
|
+
ui: UIOptions, // Appearance (theme, animation, mobile, inline)
|
|
133
|
+
labels: LabelsOptions, // Text labels (AM/PM, buttons, headers)
|
|
134
|
+
behavior: BehaviorOptions, // Behavior (focus, delays, ID)
|
|
135
|
+
callbacks: CallbacksOptions, // Event handlers
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Clock Options
|
|
140
|
+
|
|
141
|
+
| Property | Type | Default | Description |
|
|
142
|
+
| --------------------- | -------------- | ----------- | ------------------------------- |
|
|
143
|
+
| `type` | `12h` / `24h` | `12h` | Clock format |
|
|
144
|
+
| `incrementHours` | number | `1` | Hour increment step |
|
|
145
|
+
| `incrementMinutes` | number | `1` | Minute increment step |
|
|
146
|
+
| `autoSwitchToMinutes` | boolean | `false` | Auto-switch after hour selected |
|
|
147
|
+
| `disabledTime` | object | `undefined` | Disable specific hours/minutes |
|
|
148
|
+
| `currentTime` | boolean/object | `undefined` | Set current time to input |
|
|
149
|
+
|
|
150
|
+
### UI Options
|
|
151
|
+
|
|
152
|
+
| Property | Type | Default | Description |
|
|
153
|
+
| --------------------- | ------- | ----------- | ------------------------------- |
|
|
154
|
+
| `theme` | string | `basic` | Theme (11 themes available) |
|
|
155
|
+
| `animation` | boolean | `true` | Enable animations |
|
|
156
|
+
| `backdrop` | boolean | `true` | Show backdrop overlay |
|
|
157
|
+
| `mobile` | boolean | `false` | Force mobile version |
|
|
158
|
+
| `enableSwitchIcon` | boolean | `false` | Show desktop/mobile switch icon |
|
|
159
|
+
| `editable` | boolean | `false` | Allow manual input editing |
|
|
160
|
+
| `enableScrollbar` | boolean | `false` | Enable scroll when picker open |
|
|
161
|
+
| `cssClass` | string | `undefined` | Additional CSS class |
|
|
162
|
+
| `appendModalSelector` | string | `""` | Custom container selector |
|
|
163
|
+
| `iconTemplate` | string | SVG | Desktop switch icon template |
|
|
164
|
+
| `iconTemplateMobile` | string | SVG | Mobile switch icon template |
|
|
165
|
+
| `inline` | object | `undefined` | Inline mode configuration |
|
|
166
|
+
|
|
167
|
+
### Labels Options
|
|
168
|
+
|
|
169
|
+
| Property | Type | Default | Description |
|
|
170
|
+
| -------------- | ------ | ------------- | ------------------- |
|
|
171
|
+
| `am` | string | `AM` | AM label text |
|
|
172
|
+
| `pm` | string | `PM` | PM label text |
|
|
173
|
+
| `ok` | string | `OK` | OK button text |
|
|
174
|
+
| `cancel` | string | `Cancel` | Cancel button text |
|
|
175
|
+
| `time` | string | `Select time` | Desktop time label |
|
|
176
|
+
| `mobileTime` | string | `Enter Time` | Mobile time label |
|
|
177
|
+
| `mobileHour` | string | `Hour` | Mobile hour label |
|
|
178
|
+
| `mobileMinute` | string | `Minute` | Mobile minute label |
|
|
179
|
+
|
|
180
|
+
### Behavior Options
|
|
181
|
+
|
|
182
|
+
| Property | Type | Default | Description |
|
|
183
|
+
| ---------------------- | ------- | -------------- | ----------------------- |
|
|
184
|
+
| `focusInputAfterClose` | boolean | `false` | Focus input after close |
|
|
185
|
+
| `focusTrap` | boolean | `true` | Trap focus in modal |
|
|
186
|
+
| `delayHandler` | number | `300` | Click delay (ms) |
|
|
187
|
+
| `id` | string | auto-generated | Custom instance ID |
|
|
188
|
+
|
|
189
|
+
### Callbacks Options
|
|
190
|
+
|
|
191
|
+
| Property | Type | Description |
|
|
192
|
+
| ---------------- | -------- | ------------------------ |
|
|
193
|
+
| `onConfirm` | function | Time confirmed |
|
|
194
|
+
| `onCancel` | function | Cancelled |
|
|
195
|
+
| `onOpen` | function | Picker opened |
|
|
196
|
+
| `onUpdate` | function | Time updated (real-time) |
|
|
197
|
+
| `onSelectHour` | function | Hour selected |
|
|
198
|
+
| `onSelectMinute` | function | Minute selected |
|
|
199
|
+
| `onSelectAM` | function | AM selected |
|
|
200
|
+
| `onSelectPM` | function | PM selected |
|
|
201
|
+
| `onError` | function | Error occurred |
|
|
202
|
+
|
|
203
|
+
### Migration from v3.x to v4.0.0
|
|
204
|
+
|
|
205
|
+
**All options must be moved into groups:**
|
|
206
|
+
|
|
207
|
+
```diff
|
|
208
|
+
// v3.x (DEPRECATED)
|
|
209
|
+
-const picker = new TimepickerUI(input, {
|
|
210
|
+
- clockType: '24h',
|
|
211
|
+
- theme: 'dark',
|
|
212
|
+
- animation: true,
|
|
213
|
+
- incrementMinutes: 5,
|
|
214
|
+
- amLabel: 'AM',
|
|
215
|
+
- onConfirm: (data) => {}
|
|
216
|
+
-});
|
|
217
|
+
|
|
218
|
+
// v4.0.0 (NEW)
|
|
219
|
+
+const picker = new TimepickerUI(input, {
|
|
220
|
+
+ clock: {
|
|
221
|
+
+ type: '24h',
|
|
222
|
+
+ incrementMinutes: 5
|
|
223
|
+
+ },
|
|
224
|
+
+ ui: {
|
|
225
|
+
+ theme: 'dark',
|
|
226
|
+
+ animation: true
|
|
227
|
+
+ },
|
|
228
|
+
+ labels: {
|
|
229
|
+
+ am: 'AM'
|
|
230
|
+
+ },
|
|
231
|
+
+ callbacks: {
|
|
232
|
+
+ onConfirm: (data) => {}
|
|
233
|
+
+ }
|
|
234
|
+
+});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Full migration table:**
|
|
238
|
+
|
|
239
|
+
| v3.x (flat) | v4.0.0 (grouped) |
|
|
240
|
+
| --------------------------- | ------------------------------- |
|
|
241
|
+
| `clockType` | `clock.type` |
|
|
242
|
+
| `incrementHours` | `clock.incrementHours` |
|
|
243
|
+
| `incrementMinutes` | `clock.incrementMinutes` |
|
|
244
|
+
| `autoSwitchToMinutes` | `clock.autoSwitchToMinutes` |
|
|
245
|
+
| `disabledTime` | `clock.disabledTime` |
|
|
246
|
+
| `currentTime` | `clock.currentTime` |
|
|
247
|
+
| `theme` | `ui.theme` |
|
|
248
|
+
| `animation` | `ui.animation` |
|
|
249
|
+
| `backdrop` | `ui.backdrop` |
|
|
250
|
+
| `mobile` | `ui.mobile` |
|
|
251
|
+
| `enableSwitchIcon` | `ui.enableSwitchIcon` |
|
|
252
|
+
| `editable` | `ui.editable` |
|
|
253
|
+
| `enableScrollbar` | `ui.enableScrollbar` |
|
|
254
|
+
| `cssClass` | `ui.cssClass` |
|
|
255
|
+
| `appendModalSelector` | `ui.appendModalSelector` |
|
|
256
|
+
| `iconTemplate` | `ui.iconTemplate` |
|
|
257
|
+
| `iconTemplateMobile` | `ui.iconTemplateMobile` |
|
|
258
|
+
| `inline` | `ui.inline` |
|
|
259
|
+
| `amLabel` | `labels.am` |
|
|
260
|
+
| `pmLabel` | `labels.pm` |
|
|
261
|
+
| `okLabel` | `labels.ok` |
|
|
262
|
+
| `cancelLabel` | `labels.cancel` |
|
|
263
|
+
| `timeLabel` | `labels.time` |
|
|
264
|
+
| `mobileTimeLabel` | `labels.mobileTime` |
|
|
265
|
+
| `hourMobileLabel` | `labels.mobileHour` |
|
|
266
|
+
| `minuteMobileLabel` | `labels.mobileMinute` |
|
|
267
|
+
| `focusInputAfterCloseModal` | `behavior.focusInputAfterClose` |
|
|
268
|
+
| `focusTrap` | `behavior.focusTrap` |
|
|
269
|
+
| `delayHandler` | `behavior.delayHandler` |
|
|
270
|
+
| `id` | `behavior.id` |
|
|
271
|
+
| `onConfirm` | `callbacks.onConfirm` |
|
|
272
|
+
| `onCancel` | `callbacks.onCancel` |
|
|
273
|
+
| `onOpen` | `callbacks.onOpen` |
|
|
274
|
+
| `onUpdate` | `callbacks.onUpdate` |
|
|
275
|
+
| `onSelectHour` | `callbacks.onSelectHour` |
|
|
276
|
+
| `onSelectMinute` | `callbacks.onSelectMinute` |
|
|
277
|
+
| `onSelectAM` | `callbacks.onSelectAM` |
|
|
278
|
+
| `onSelectPM` | `callbacks.onSelectPM` |
|
|
279
|
+
| `onError` | `callbacks.onError` |
|
|
161
280
|
|
|
162
281
|
### Themes
|
|
163
282
|
|
|
@@ -168,7 +287,9 @@ import "timepicker-ui/main.css"; // Required base styles
|
|
|
168
287
|
import "timepicker-ui/theme-dark.css"; // Specific theme
|
|
169
288
|
|
|
170
289
|
const picker = new TimepickerUI(input, {
|
|
171
|
-
|
|
290
|
+
ui: {
|
|
291
|
+
theme: "dark",
|
|
292
|
+
},
|
|
172
293
|
});
|
|
173
294
|
```
|
|
174
295
|
|
|
@@ -176,10 +297,12 @@ const picker = new TimepickerUI(input, {
|
|
|
176
297
|
|
|
177
298
|
```javascript
|
|
178
299
|
const picker = new TimepickerUI(input, {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
300
|
+
clock: {
|
|
301
|
+
disabledTime: {
|
|
302
|
+
hours: [1, 3, 5, 8],
|
|
303
|
+
minutes: [15, 30, 45],
|
|
304
|
+
interval: "10:00 AM - 2:00 PM",
|
|
305
|
+
},
|
|
183
306
|
},
|
|
184
307
|
});
|
|
185
308
|
```
|
|
@@ -188,11 +311,13 @@ const picker = new TimepickerUI(input, {
|
|
|
188
311
|
|
|
189
312
|
```javascript
|
|
190
313
|
const picker = new TimepickerUI(input, {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
314
|
+
ui: {
|
|
315
|
+
inline: {
|
|
316
|
+
enabled: true,
|
|
317
|
+
containerId: "timepicker-container",
|
|
318
|
+
showButtons: false,
|
|
319
|
+
autoUpdate: true,
|
|
320
|
+
},
|
|
196
321
|
},
|
|
197
322
|
});
|
|
198
323
|
```
|
|
@@ -223,7 +348,7 @@ TimepickerUI.destroyAll(); // Destroy all instances
|
|
|
223
348
|
|
|
224
349
|
## Events
|
|
225
350
|
|
|
226
|
-
Listen to timepicker events using the
|
|
351
|
+
Listen to timepicker events using the **EventEmitter API** (v4+) or callback options:
|
|
227
352
|
|
|
228
353
|
### EventEmitter API (Recommended)
|
|
229
354
|
|
|
@@ -274,21 +399,224 @@ picker.once("confirm", (data) => {
|
|
|
274
399
|
picker.off("confirm", handler);
|
|
275
400
|
```
|
|
276
401
|
|
|
277
|
-
### Legacy DOM Events (
|
|
402
|
+
### Legacy DOM Events (v3.x Only)
|
|
403
|
+
|
|
404
|
+
⚠️ **Only Available in v3.x - Completely Removed in v4.0.0**
|
|
405
|
+
|
|
406
|
+
DOM events (e.g., `timepicker:confirm`) were removed in v4.0.0. Use the **EventEmitter API** shown above or **callback options** instead.
|
|
278
407
|
|
|
279
|
-
**
|
|
408
|
+
**v3.x code (no longer works in v4):**
|
|
280
409
|
|
|
281
410
|
```javascript
|
|
282
411
|
input.addEventListener("timepicker:confirm", (e) => {
|
|
283
412
|
console.log("Time:", e.detail);
|
|
284
413
|
});
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**v4.0.0 alternatives:**
|
|
417
|
+
|
|
418
|
+
```javascript
|
|
419
|
+
// Option 1: EventEmitter API
|
|
420
|
+
picker.on("confirm", (data) => {
|
|
421
|
+
console.log("Time:", data);
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
// Option 2: Callback options
|
|
425
|
+
const picker = new TimepickerUI(input, {
|
|
426
|
+
callbacks: {
|
|
427
|
+
onConfirm: (data) => {
|
|
428
|
+
console.log("Time:", data);
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
});
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
Removed events: `timepicker:open`, `timepicker:cancel`, `timepicker:confirm`, `timepicker:update`, `timepicker:select-hour`, `timepicker:select-minute`, `timepicker:select-am`, `timepicker:select-pm`, `timepicker:error`
|
|
435
|
+
|
|
436
|
+
## Upgrade Guide: v3 → v4
|
|
437
|
+
|
|
438
|
+
### Breaking Changes
|
|
439
|
+
|
|
440
|
+
**1. CSS Class Names Renamed**
|
|
441
|
+
|
|
442
|
+
All CSS classes have been shortened from `timepicker-ui-*` to `tp-ui-*`:
|
|
443
|
+
|
|
444
|
+
```css
|
|
445
|
+
/* v3 */
|
|
446
|
+
.timepicker-ui-wrapper {
|
|
447
|
+
}
|
|
448
|
+
.timepicker-ui-modal {
|
|
449
|
+
}
|
|
450
|
+
.timepicker-ui-clock-face {
|
|
451
|
+
}
|
|
452
|
+
.timepicker-ui-hour {
|
|
453
|
+
}
|
|
454
|
+
.timepicker-ui-minutes {
|
|
455
|
+
}
|
|
456
|
+
.timepicker-ui-am {
|
|
457
|
+
}
|
|
458
|
+
.timepicker-ui-pm {
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/* v4 */
|
|
462
|
+
.tp-ui-wrapper {
|
|
463
|
+
}
|
|
464
|
+
.tp-ui-modal {
|
|
465
|
+
}
|
|
466
|
+
.tp-ui-clock-face {
|
|
467
|
+
}
|
|
468
|
+
.tp-ui-hour {
|
|
469
|
+
}
|
|
470
|
+
.tp-ui-minutes {
|
|
471
|
+
}
|
|
472
|
+
.tp-ui-am {
|
|
473
|
+
}
|
|
474
|
+
.tp-ui-pm {
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
**Impact:** If you have custom CSS targeting timepicker elements, update all class selectors.
|
|
479
|
+
|
|
480
|
+
**2. Grouped Options Structure**
|
|
481
|
+
|
|
482
|
+
All options are now organized into logical groups for better maintainability:
|
|
483
|
+
|
|
484
|
+
```javascript
|
|
485
|
+
// v3
|
|
486
|
+
const picker = new TimepickerUI(input, {
|
|
487
|
+
clockType: "12h",
|
|
488
|
+
theme: "dark",
|
|
489
|
+
enableSwitchIcon: true,
|
|
490
|
+
mobile: true,
|
|
491
|
+
animation: true,
|
|
492
|
+
backdrop: true,
|
|
493
|
+
focusTrap: true,
|
|
494
|
+
editable: true,
|
|
495
|
+
onConfirm: (data) => console.log(data),
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
// v4 - Grouped options
|
|
499
|
+
const picker = new TimepickerUI(input, {
|
|
500
|
+
clock: {
|
|
501
|
+
type: "12h",
|
|
502
|
+
incrementHours: 1,
|
|
503
|
+
incrementMinutes: 1,
|
|
504
|
+
currentTime: { time: new Date(), updateInput: true },
|
|
505
|
+
disabledTime: { hours: [1, 2, 3] },
|
|
506
|
+
autoSwitchToMinutes: false,
|
|
507
|
+
},
|
|
508
|
+
ui: {
|
|
509
|
+
theme: "dark",
|
|
510
|
+
enableSwitchIcon: true,
|
|
511
|
+
mobile: true,
|
|
512
|
+
animation: true,
|
|
513
|
+
backdrop: true,
|
|
514
|
+
editable: true,
|
|
515
|
+
cssClass: "my-custom-class",
|
|
516
|
+
inline: { enabled: false },
|
|
517
|
+
},
|
|
518
|
+
labels: {
|
|
519
|
+
time: "Select Time",
|
|
520
|
+
am: "AM",
|
|
521
|
+
pm: "PM",
|
|
522
|
+
ok: "OK",
|
|
523
|
+
cancel: "Cancel",
|
|
524
|
+
},
|
|
525
|
+
behavior: {
|
|
526
|
+
focusTrap: true,
|
|
527
|
+
focusInputAfterClose: false,
|
|
528
|
+
delayHandler: 300,
|
|
529
|
+
},
|
|
530
|
+
callbacks: {
|
|
531
|
+
onConfirm: (data) => console.log(data),
|
|
532
|
+
onCancel: (data) => console.log(data),
|
|
533
|
+
onOpen: (data) => console.log(data),
|
|
534
|
+
onUpdate: (data) => console.log(data),
|
|
535
|
+
onSelectHour: (data) => console.log(data),
|
|
536
|
+
onSelectMinute: (data) => console.log(data),
|
|
537
|
+
onSelectAM: (data) => console.log(data),
|
|
538
|
+
onSelectPM: (data) => console.log(data),
|
|
539
|
+
onError: (data) => console.log(data),
|
|
540
|
+
},
|
|
541
|
+
});
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
**2. Legacy DOM Events Removed**
|
|
545
|
+
|
|
546
|
+
DOM events have been completely removed. Use EventEmitter API or callback options:
|
|
547
|
+
|
|
548
|
+
```javascript
|
|
549
|
+
// v3 - Deprecated (removed in v4)
|
|
550
|
+
input.addEventListener("timepicker:confirm", (e) => {
|
|
551
|
+
console.log(e.detail);
|
|
552
|
+
});
|
|
285
553
|
|
|
286
|
-
|
|
287
|
-
|
|
554
|
+
// v4 - EventEmitter API (recommended)
|
|
555
|
+
picker.on("confirm", (data) => {
|
|
556
|
+
console.log(data);
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
// v4 - Or use callback options
|
|
560
|
+
const picker = new TimepickerUI(input, {
|
|
561
|
+
callbacks: {
|
|
562
|
+
onConfirm: (data) => console.log(data),
|
|
563
|
+
},
|
|
288
564
|
});
|
|
289
565
|
```
|
|
290
566
|
|
|
291
|
-
|
|
567
|
+
**3. setTheme() Method Removed**
|
|
568
|
+
|
|
569
|
+
Programmatic theme setting via `setTheme()` has been removed. Use CSS classes instead:
|
|
570
|
+
|
|
571
|
+
```javascript
|
|
572
|
+
// v3 - Removed in v4
|
|
573
|
+
picker.setTheme({
|
|
574
|
+
primaryColor: "#ff0000",
|
|
575
|
+
backgroundColor: "#000000",
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
// v4 - Use CSS classes with CSS variables
|
|
579
|
+
const picker = new TimepickerUI(input, {
|
|
580
|
+
ui: { cssClass: "my-custom-theme" },
|
|
581
|
+
});
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
```css
|
|
585
|
+
/* Define custom theme in CSS */
|
|
586
|
+
.tp-ui-wrapper.my-custom-theme {
|
|
587
|
+
--tp-primary: #ff0000;
|
|
588
|
+
--tp-bg: #000000;
|
|
589
|
+
--tp-surface: #f0f0f0;
|
|
590
|
+
}
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
**4. SSR-Safe Architecture**
|
|
594
|
+
|
|
595
|
+
All modules are now SSR-safe and can be imported in Node.js environments without crashing.
|
|
596
|
+
|
|
597
|
+
### Migration Steps
|
|
598
|
+
|
|
599
|
+
1. **Update option structure** - Move options into `clock`, `ui`, `labels`, `behavior`, `callbacks` groups
|
|
600
|
+
2. **Replace DOM events** - Switch to `picker.on()` EventEmitter API or callback options
|
|
601
|
+
3. **Remove setTheme() calls** - Use CSS classes with CSS variable overrides
|
|
602
|
+
4. **Test SSR compatibility** - If using Next.js/Nuxt/Remix, verify hydration works correctly
|
|
603
|
+
|
|
604
|
+
### New in v4
|
|
605
|
+
|
|
606
|
+
- **Composition-based architecture** - No inheritance, pure composition with managers
|
|
607
|
+
- **EventEmitter API** - Type-safe event handling with `on()`, `off()`, `once()`
|
|
608
|
+
- **Callback bridge** - Callbacks automatically connected to EventEmitter
|
|
609
|
+
- **SSR compatibility** - All modules can be imported in Node.js
|
|
610
|
+
- **Better TypeScript types** - Fully typed event payloads and options
|
|
611
|
+
- **Smaller bundle** - Removed unused code, optimized build (63.3 KB ESM)
|
|
612
|
+
- **Focus improvements** - Auto-focus on modal open, auto-focus on minute switch
|
|
613
|
+
|
|
614
|
+
### Bundle Size Comparison
|
|
615
|
+
|
|
616
|
+
- v3: 80 KB ESM
|
|
617
|
+
- v4: 63.3 KB ESM (-20.9%)
|
|
618
|
+
|
|
619
|
+
---
|
|
292
620
|
|
|
293
621
|
## Upgrade Guide: v2 → v3
|
|
294
622
|
|