@oneluiz/dual-datepicker 3.2.0 → 3.4.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 +161 -8
- package/THEMING.md +313 -0
- package/dual-datepicker.component.d.ts +31 -1
- package/esm2022/dual-datepicker.component.mjs +197 -9
- package/esm2022/public-api.mjs +1 -1
- package/fesm2022/oneluiz-dual-datepicker.mjs +196 -8
- package/fesm2022/oneluiz-dual-datepicker.mjs.map +1 -1
- package/package.json +2 -2
- package/public-api.d.ts +1 -1
- package/src/themes/bootstrap.scss +202 -0
- package/src/themes/bulma.scss +209 -0
- package/src/themes/custom.scss +236 -0
- package/src/themes/foundation.scss +201 -0
- package/src/themes/tailwind.scss +109 -0
- package/themes/bootstrap.scss +202 -0
- package/themes/bulma.scss +209 -0
- package/themes/custom.scss +236 -0
- package/themes/foundation.scss +201 -0
- package/themes/tailwind.scss +109 -0
package/README.md
CHANGED
|
@@ -31,11 +31,13 @@ npm install @oneluiz/dual-datepicker
|
|
|
31
31
|
- [Disabled Dates](#disabled-dates)
|
|
32
32
|
- [Display Format](#display-format)
|
|
33
33
|
- [Apply/Confirm Button](#applyconfirm-button)
|
|
34
|
+
- [Time Picker](#time-picker)
|
|
34
35
|
- [Hover Range Preview](#hover-range-preview)
|
|
35
36
|
- [Custom Presets](#custom-presets)
|
|
36
37
|
- [Date Adapter System](#date-adapter-system)
|
|
37
38
|
- [Keyboard Navigation](#keyboard-navigation)
|
|
38
39
|
- [Customization](#-customization)
|
|
40
|
+
- [Theming System](#theming-system)
|
|
39
41
|
- [Styling Options](#styling-options)
|
|
40
42
|
- [Localization (i18n)](#localization-i18n)
|
|
41
43
|
- [API Reference](#-api-reference)
|
|
@@ -60,7 +62,8 @@ npm install @oneluiz/dual-datepicker
|
|
|
60
62
|
- 🚫 **Disabled Dates** – Block weekends, holidays, or custom logic
|
|
61
63
|
- 🎨 **Display Format** – Customize date display (DD/MM/YYYY, MM/DD/YYYY, etc.)
|
|
62
64
|
- ✅ **Apply/Confirm Button** – Require confirmation before emitting (perfect for dashboards)
|
|
63
|
-
-
|
|
65
|
+
- � **Theming System** – Built-in themes for Bootstrap, Bulma, Foundation, Tailwind, + Custom
|
|
66
|
+
- �🎨 **Fully Customizable** – Every color, padding, border configurable
|
|
64
67
|
- 📦 **Lightweight** – ~60 KB gzipped total bundle
|
|
65
68
|
- 🚀 **Performance** – OnPush change detection + trackBy optimization
|
|
66
69
|
- ♿ **Accessible** – Full keyboard navigation, ARIA labels, WCAG 2.1 AA compliant
|
|
@@ -468,6 +471,109 @@ export class DashboardExample {
|
|
|
468
471
|
| User control | Automatic | Explicit confirmation |
|
|
469
472
|
| Best for | Simple forms | Dashboards, reports |
|
|
470
473
|
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
### Time Picker
|
|
477
|
+
|
|
478
|
+
**Select precise datetime ranges with optional time picker.** Choose exact start and end times in addition to dates, with support for 12h/24h formats and configurable minute steps.
|
|
479
|
+
|
|
480
|
+
#### Basic Usage
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
import { Component } from '@angular/core';
|
|
484
|
+
import { DateRange } from '@oneluiz/dual-datepicker';
|
|
485
|
+
|
|
486
|
+
@Component({
|
|
487
|
+
template: `
|
|
488
|
+
<ngx-dual-datepicker
|
|
489
|
+
[enableTimePicker]="true"
|
|
490
|
+
(dateRangeChange)="onDateRangeChange($event)">
|
|
491
|
+
</ngx-dual-datepicker>
|
|
492
|
+
`
|
|
493
|
+
})
|
|
494
|
+
export class AppointmentComponent {
|
|
495
|
+
onDateRangeChange(range: DateRange) {
|
|
496
|
+
console.log('Start:', range.startDate, 'at', range.startTime);
|
|
497
|
+
console.log('End:', range.endDate, 'at', range.endTime);
|
|
498
|
+
// startTime and endTime are in 'HH:mm' format
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
#### Configuration Options
|
|
504
|
+
|
|
505
|
+
```typescript
|
|
506
|
+
// 12-hour format with AM/PM
|
|
507
|
+
<ngx-dual-datepicker
|
|
508
|
+
[enableTimePicker]="true"
|
|
509
|
+
timeFormat="12h"
|
|
510
|
+
defaultStartTime="09:00"
|
|
511
|
+
defaultEndTime="17:00"
|
|
512
|
+
(dateRangeChange)="onDateRangeChange($event)">
|
|
513
|
+
</ngx-dual-datepicker>
|
|
514
|
+
|
|
515
|
+
// 30-minute intervals
|
|
516
|
+
<ngx-dual-datepicker
|
|
517
|
+
[enableTimePicker]="true"
|
|
518
|
+
[minuteStep]="30"
|
|
519
|
+
(dateRangeChange)="onDateRangeChange($event)">
|
|
520
|
+
</ngx-dual-datepicker>
|
|
521
|
+
|
|
522
|
+
// With Apply button for controlled changes
|
|
523
|
+
<ngx-dual-datepicker
|
|
524
|
+
[enableTimePicker]="true"
|
|
525
|
+
[requireApply]="true"
|
|
526
|
+
(dateRangeChange)="onDateRangeChange($event)">
|
|
527
|
+
</ngx-dual-datepicker>
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
#### DateRange with Time
|
|
531
|
+
|
|
532
|
+
When `enableTimePicker` is true, the DateRange includes optional time properties:
|
|
533
|
+
|
|
534
|
+
```typescript
|
|
535
|
+
interface DateRange {
|
|
536
|
+
startDate: string; // 'YYYY-MM-DD'
|
|
537
|
+
endDate: string; // 'YYYY-MM-DD'
|
|
538
|
+
rangeText: string; // Display text
|
|
539
|
+
startTime?: string; // 'HH:mm' or 'HH:mm AM/PM'
|
|
540
|
+
endTime?: string; // 'HH:mm' or 'HH:mm AM/PM'
|
|
541
|
+
}
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
#### Configuration Inputs
|
|
545
|
+
|
|
546
|
+
| Input | Type | Default | Description |
|
|
547
|
+
|-------|------|---------|-------------|
|
|
548
|
+
| `enableTimePicker` | boolean | `false` | Enable time selection |
|
|
549
|
+
| `timeFormat` | `'12h'` \| `'24h'` | `'24h'` | Time display format |
|
|
550
|
+
| `minuteStep` | number | `15` | Minute intervals (1, 5, 15, or 30) |
|
|
551
|
+
| `defaultStartTime` | string | `'00:00'` | Default start time (HH:mm) |
|
|
552
|
+
| `defaultEndTime` | string | `'23:59'` | Default end time (HH:mm) |
|
|
553
|
+
|
|
554
|
+
#### Perfect Use Cases
|
|
555
|
+
|
|
556
|
+
- 📅 **Appointment booking systems** - Schedule meetings with exact times
|
|
557
|
+
- 🎫 **Event scheduling** - Create events with start and end times
|
|
558
|
+
- 🏢 **Meeting planners** - Book conference rooms with time slots
|
|
559
|
+
- 📊 **Time-based reporting** - Generate reports for specific time ranges
|
|
560
|
+
- 👥 **Shift management** - Assign work shifts with precise times
|
|
561
|
+
- 🎬 **Reservation systems** - Book resources with time constraints
|
|
562
|
+
|
|
563
|
+
#### Key Features
|
|
564
|
+
|
|
565
|
+
- ✅ Optional - disabled by default (backward compatible)
|
|
566
|
+
- ✅ 12h (AM/PM) or 24h time format
|
|
567
|
+
- ✅ Configurable minute steps (1, 5, 15, 30)
|
|
568
|
+
- ✅ Default start/end times support
|
|
569
|
+
- ✅ Works with all themes
|
|
570
|
+
- ✅ Integrates with requireApply mode
|
|
571
|
+
- ✅ Fully accessible with keyboard navigation
|
|
572
|
+
|
|
573
|
+
**For complete documentation, see [TIME_PICKER.md](TIME_PICKER.md)**
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
471
577
|
### Hover Range Preview
|
|
472
578
|
|
|
473
579
|
**Automatic visual feedback while selecting dates.** Provides instant visual preview of the date range when hovering over dates before clicking to confirm.
|
|
@@ -662,6 +768,29 @@ export class AppComponent {}
|
|
|
662
768
|
|
|
663
769
|
## 🎨 Customization
|
|
664
770
|
|
|
771
|
+
### Theming System
|
|
772
|
+
|
|
773
|
+
The datepicker now supports 6 built-in themes: `default`, `bootstrap`, `bulma`, `foundation`, `tailwind`, and `custom`.
|
|
774
|
+
|
|
775
|
+
```typescript
|
|
776
|
+
<ngx-dual-datepicker theme="bootstrap"></ngx-dual-datepicker>
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
```scss
|
|
780
|
+
// In your styles.scss
|
|
781
|
+
@import '@oneluiz/dual-datepicker/themes/bootstrap';
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
**Available Themes:**
|
|
785
|
+
- `default` - Original styling (no import needed)
|
|
786
|
+
- `bootstrap` - Bootstrap 5 compatible styling
|
|
787
|
+
- `bulma` - Bulma CSS compatible styling
|
|
788
|
+
- `foundation` - Foundation CSS compatible styling
|
|
789
|
+
- `tailwind` - Tailwind CSS compatible styling
|
|
790
|
+
- `custom` - CSS variables-based customization
|
|
791
|
+
|
|
792
|
+
**📚 For detailed theming documentation, see [THEMING.md](./THEMING.md)**
|
|
793
|
+
|
|
665
794
|
### Styling Options
|
|
666
795
|
|
|
667
796
|
```html
|
|
@@ -734,6 +863,12 @@ spanishLocale: LocaleConfig = {
|
|
|
734
863
|
| `disabledDates` | `Date[] \| ((date: Date) => boolean)` | `undefined` | Array of dates or function to disable specific dates |
|
|
735
864
|
| `displayFormat` | `string` | `'D MMM'` | Format for displaying dates in input (tokens: YYYY, YY, MMMM, MMM, MM, M, DD, D) |
|
|
736
865
|
| `requireApply` | `boolean` | `false` | Require Apply button confirmation before emitting changes |
|
|
866
|
+
| `enableTimePicker` | `boolean` | `false` | Enable time selection |
|
|
867
|
+
| `timeFormat` | `'12h' \| '24h'` | `'24h'` | Time display format (12-hour with AM/PM or 24-hour) |
|
|
868
|
+
| `minuteStep` | `number` | `15` | Step for minute selector (1, 5, 15, or 30) |
|
|
869
|
+
| `defaultStartTime` | `string` | `'00:00'` | Default start time in HH:mm format |
|
|
870
|
+
| `defaultEndTime` | `string` | `'23:59'` | Default end time in HH:mm format |
|
|
871
|
+
| `theme` | `ThemeType` | `'default'` | Theme preset: 'default', 'bootstrap', 'bulma', 'foundation', 'tailwind', 'custom' |
|
|
737
872
|
| `enableKeyboardNavigation` | `boolean` | `true` | Enable keyboard navigation |
|
|
738
873
|
| `inputBackgroundColor` | `string` | `'#fff'` | Input background color |
|
|
739
874
|
| `inputTextColor` | `string` | `'#495057'` | Input text color |
|
|
@@ -784,6 +919,8 @@ interface DateRange {
|
|
|
784
919
|
startDate: string; // ISO format: 'YYYY-MM-DD'
|
|
785
920
|
endDate: string; // ISO format: 'YYYY-MM-DD'
|
|
786
921
|
rangeText: string; // Display text: 'DD Mon - DD Mon'
|
|
922
|
+
startTime?: string; // Optional: 'HH:mm' or 'HH:mm AM/PM' (when enableTimePicker=true)
|
|
923
|
+
endTime?: string; // Optional: 'HH:mm' or 'HH:mm AM/PM' (when enableTimePicker=true)
|
|
787
924
|
}
|
|
788
925
|
|
|
789
926
|
interface MultiDateRange {
|
|
@@ -1861,20 +1998,36 @@ export class ExampleComponent {
|
|
|
1861
1998
|
|
|
1862
1999
|
Recently shipped:
|
|
1863
2000
|
|
|
2001
|
+
**v3.3.0:**
|
|
2002
|
+
- ✅ **Theming System** - Pre-built themes for Bootstrap, Bulma, Foundation, Tailwind CSS, and Custom
|
|
2003
|
+
- ✅ **CSS Variables Support** - 13 customizable variables for branding
|
|
2004
|
+
- ✅ **Framework Integration** - Match your existing design system seamlessly
|
|
2005
|
+
|
|
2006
|
+
**v3.2.0:**
|
|
2007
|
+
- ✅ **Hover Range Preview** - Visual feedback before confirming selection
|
|
2008
|
+
- ✅ **Apply/Confirm Button** - Require confirmation for enterprise dashboards
|
|
2009
|
+
- ✅ **Display Format** - Customize date display (DD/MM/YYYY, MM/DD/YYYY, etc.)
|
|
2010
|
+
- ✅ **Disabled Dates** - Block weekends, holidays, or custom logic
|
|
2011
|
+
|
|
2012
|
+
**v3.1.0:**
|
|
2013
|
+
- ✅ **Complete Keyboard Navigation** - Arrow keys, Enter/Space, Tab, Escape, Home/End, PageUp/Down
|
|
2014
|
+
- ✅ **Full Accessibility Audit** - WCAG 2.1 Level AA compliance
|
|
2015
|
+
|
|
2016
|
+
**v2.7.0:**
|
|
2017
|
+
- ✅ **Multi-range Support** - Select UNLIMITED date ranges (Material CAN'T do this!)
|
|
2018
|
+
|
|
1864
2019
|
**v2.6.0:**
|
|
1865
|
-
- ✅ **Flexible Preset System** - `getValue()` pattern for custom date logic
|
|
2020
|
+
- ✅ **Flexible Preset System** - `getValue()` pattern for custom date logic
|
|
1866
2021
|
- ✅ **Pre-built Preset Utilities** - CommonPresets for Dashboard, Reporting, Financial, Analytics
|
|
1867
|
-
- ✅ **Real Differentiator** - Perfect for ERP, BI, POS, and Reporting systems
|
|
1868
2022
|
|
|
1869
2023
|
**v2.5.0:**
|
|
1870
2024
|
- ✅ **Date Adapter System** - Support for DayJS, date-fns, Luxon, and custom date libraries
|
|
1871
2025
|
|
|
1872
|
-
Planned features
|
|
2026
|
+
Planned features:
|
|
1873
2027
|
|
|
1874
|
-
- ⬜ **
|
|
1875
|
-
- ⬜ **
|
|
1876
|
-
- ⬜ **
|
|
1877
|
-
- ⬜ **Theming system** - Pre-built theme presets
|
|
2028
|
+
- ⬜ **Time Picker** - Select date + time ranges
|
|
2029
|
+
- ⬜ **Mobile Optimizations** - Enhanced touch gestures and responsive layout
|
|
2030
|
+
- ⬜ **Range Shortcuts** - Quick selection buttons (Today, This Week, etc.)
|
|
1878
2031
|
|
|
1879
2032
|
## 📄 License
|
|
1880
2033
|
|
package/THEMING.md
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# Theming System
|
|
2
|
+
|
|
3
|
+
The `ng-dual-datepicker` component comes with a flexible theming system that allows you to style it according to your preferred CSS framework or custom design.
|
|
4
|
+
|
|
5
|
+
## Available Themes
|
|
6
|
+
|
|
7
|
+
- **default** - Original styling (no additional imports needed)
|
|
8
|
+
- **bootstrap** - Bootstrap 5 compatible styling
|
|
9
|
+
- **bulma** - Bulma CSS compatible styling
|
|
10
|
+
- **foundation** - Foundation CSS compatible styling
|
|
11
|
+
- **tailwind** - Tailwind CSS compatible styling
|
|
12
|
+
- **custom** - Customizable theme with CSS variables
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
### 1. Set the Theme
|
|
17
|
+
|
|
18
|
+
Add the `theme` input to your component:
|
|
19
|
+
|
|
20
|
+
```html
|
|
21
|
+
<ngx-dual-datepicker
|
|
22
|
+
theme="bootstrap"
|
|
23
|
+
[presets]="presets"
|
|
24
|
+
(dateRangeChange)="onDateRangeChange($event)">
|
|
25
|
+
</ngx-dual-datepicker>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 2. Import the Theme Styles
|
|
29
|
+
|
|
30
|
+
Import the corresponding theme stylesheet in your global `styles.scss`:
|
|
31
|
+
|
|
32
|
+
```scss
|
|
33
|
+
// For Bootstrap theme
|
|
34
|
+
@import '@oneluiz/dual-datepicker/themes/bootstrap';
|
|
35
|
+
|
|
36
|
+
// For Bulma theme
|
|
37
|
+
@import '@oneluiz/dual-datepicker/themes/bulma';
|
|
38
|
+
|
|
39
|
+
// For Foundation theme
|
|
40
|
+
@import '@oneluiz/dual-datepicker/themes/foundation';
|
|
41
|
+
|
|
42
|
+
// For Tailwind theme
|
|
43
|
+
@import '@oneluiz/dual-datepicker/themes/tailwind';
|
|
44
|
+
|
|
45
|
+
// For Custom theme
|
|
46
|
+
@import '@oneluiz/dual-datepicker/themes/custom';
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Theme Details
|
|
50
|
+
|
|
51
|
+
### Default Theme
|
|
52
|
+
|
|
53
|
+
No additional configuration needed. This is the original styling that works out of the box.
|
|
54
|
+
|
|
55
|
+
```html
|
|
56
|
+
<ngx-dual-datepicker [presets]="presets"></ngx-dual-datepicker>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Bootstrap Theme
|
|
60
|
+
|
|
61
|
+
Compatible with Bootstrap 5. Make sure you have Bootstrap CSS loaded in your project.
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<ngx-dual-datepicker theme="bootstrap" [presets]="presets"></ngx-dual-datepicker>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```scss
|
|
68
|
+
@import '@oneluiz/dual-datepicker/themes/bootstrap';
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Bulma Theme
|
|
72
|
+
|
|
73
|
+
Compatible with Bulma CSS. Make sure you have Bulma CSS loaded in your project.
|
|
74
|
+
|
|
75
|
+
```html
|
|
76
|
+
<ngx-dual-datepicker theme="bulma" [presets]="presets"></ngx-dual-datepicker>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```scss
|
|
80
|
+
@import '@oneluiz/dual-datepicker/themes/bulma';
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Foundation Theme
|
|
84
|
+
|
|
85
|
+
Compatible with Foundation CSS. Make sure you have Foundation CSS loaded in your project.
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<ngx-dual-datepicker theme="foundation" [presets]="presets"></ngx-dual-datepicker>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```scss
|
|
92
|
+
@import '@oneluiz/dual-datepicker/themes/foundation';
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Tailwind CSS Theme
|
|
96
|
+
|
|
97
|
+
Compatible with Tailwind CSS. Make sure you have Tailwind configured in your project.
|
|
98
|
+
|
|
99
|
+
```html
|
|
100
|
+
<ngx-dual-datepicker theme="tailwind" [presets]="presets"></ngx-dual-datepicker>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```scss
|
|
104
|
+
@import '@oneluiz/dual-datepicker/themes/tailwind';
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Custom Theme
|
|
108
|
+
|
|
109
|
+
The custom theme provides CSS variables that you can easily override to match your brand colors.
|
|
110
|
+
|
|
111
|
+
```html
|
|
112
|
+
<ngx-dual-datepicker theme="custom" [presets]="presets"></ngx-dual-datepicker>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
```scss
|
|
116
|
+
@import '@oneluiz/dual-datepicker/themes/custom';
|
|
117
|
+
|
|
118
|
+
// Override the CSS variables
|
|
119
|
+
.datepicker-wrapper.theme-custom {
|
|
120
|
+
--dp-primary-color: #ff6b6b;
|
|
121
|
+
--dp-primary-hover: #ee5a6f;
|
|
122
|
+
--dp-danger-color: #fa5252;
|
|
123
|
+
--dp-danger-hover: #e03131;
|
|
124
|
+
--dp-text-color: #2d3748;
|
|
125
|
+
--dp-text-muted: #718096;
|
|
126
|
+
--dp-border-color: #e2e8f0;
|
|
127
|
+
--dp-border-hover: #cbd5e0;
|
|
128
|
+
--dp-bg-color: #ffffff;
|
|
129
|
+
--dp-bg-hover: #f7fafc;
|
|
130
|
+
--dp-bg-disabled: #edf2f7;
|
|
131
|
+
--dp-border-radius: 0.5rem;
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Available CSS Variables (Custom Theme)
|
|
136
|
+
|
|
137
|
+
| Variable | Default Value | Description |
|
|
138
|
+
|----------|--------------|-------------|
|
|
139
|
+
| `--dp-primary-color` | `#3b82f6` | Primary button and selection color |
|
|
140
|
+
| `--dp-primary-hover` | `#2563eb` | Primary hover state color |
|
|
141
|
+
| `--dp-danger-color` | `#ef4444` | Danger/close button color |
|
|
142
|
+
| `--dp-danger-hover` | `#dc2626` | Danger hover state color |
|
|
143
|
+
| `--dp-text-color` | `#1f2937` | Main text color |
|
|
144
|
+
| `--dp-text-muted` | `#6b7280` | Muted/placeholder text color |
|
|
145
|
+
| `--dp-border-color` | `#d1d5db` | Border color |
|
|
146
|
+
| `--dp-border-hover` | `#9ca3af` | Border hover color |
|
|
147
|
+
| `--dp-bg-color` | `#ffffff` | Background color |
|
|
148
|
+
| `--dp-bg-hover` | `#f3f4f6` | Hover background color |
|
|
149
|
+
| `--dp-bg-disabled` | `#f9fafb` | Disabled state background |
|
|
150
|
+
| `--dp-border-radius` | `0.375rem` | Border radius for elements |
|
|
151
|
+
| `--dp-transition` | `all 0.15s ease` | Transition effect |
|
|
152
|
+
|
|
153
|
+
## Creating Your Own Theme
|
|
154
|
+
|
|
155
|
+
You can create your own theme by:
|
|
156
|
+
|
|
157
|
+
1. Creating a new SCSS file (e.g., `my-theme.scss`)
|
|
158
|
+
2. Targeting the `.datepicker-wrapper.theme-custom` class
|
|
159
|
+
3. Defining your custom styles
|
|
160
|
+
|
|
161
|
+
Example:
|
|
162
|
+
|
|
163
|
+
```scss
|
|
164
|
+
// my-theme.scss
|
|
165
|
+
.datepicker-wrapper.theme-custom {
|
|
166
|
+
.datepicker-input {
|
|
167
|
+
// Your custom styles
|
|
168
|
+
border: 2px solid #your-color;
|
|
169
|
+
border-radius: 12px;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.date-picker-dropdown {
|
|
173
|
+
// Your custom styles
|
|
174
|
+
box-shadow: 0 20px 25px rgba(0, 0, 0, 0.15);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.day.selected {
|
|
178
|
+
// Your custom styles
|
|
179
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## TypeScript Type
|
|
185
|
+
|
|
186
|
+
The theme type is exported from the library:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
import { ThemeType } from '@oneluiz/dual-datepicker';
|
|
190
|
+
|
|
191
|
+
const myTheme: ThemeType = 'bootstrap';
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Mixing Themes and Custom Inputs
|
|
195
|
+
|
|
196
|
+
You can still use the custom styling inputs (`inputBackgroundColor`, `inputBorderColor`, etc.) along with themes. The input properties will override the theme styles:
|
|
197
|
+
|
|
198
|
+
```html
|
|
199
|
+
<ngx-dual-datepicker
|
|
200
|
+
theme="bootstrap"
|
|
201
|
+
inputBorderColor="#ff0000"
|
|
202
|
+
inputBorderColorFocus="#00ff00"
|
|
203
|
+
[presets]="presets">
|
|
204
|
+
</ngx-dual-datepicker>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Best Practices
|
|
208
|
+
|
|
209
|
+
1. **Choose One Theme**: Select one theme that matches your project's CSS framework
|
|
210
|
+
2. **Import Only What You Need**: Only import the theme stylesheet you're using
|
|
211
|
+
3. **Consistent Styling**: Use the same theme across all datepicker instances
|
|
212
|
+
4. **Custom Variables**: For small adjustments, use the Custom theme with CSS variables instead of creating a whole new theme
|
|
213
|
+
|
|
214
|
+
## Examples
|
|
215
|
+
|
|
216
|
+
### Bootstrap Project
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
// app.component.ts
|
|
220
|
+
import { Component } from '@angular/core';
|
|
221
|
+
import { DualDatepickerComponent } from '@oneluiz/dual-datepicker';
|
|
222
|
+
|
|
223
|
+
@Component({
|
|
224
|
+
selector: 'app-root',
|
|
225
|
+
standalone: true,
|
|
226
|
+
imports: [DualDatepickerComponent],
|
|
227
|
+
template: `
|
|
228
|
+
<ngx-dual-datepicker
|
|
229
|
+
theme="bootstrap"
|
|
230
|
+
[presets]="presets"
|
|
231
|
+
(dateRangeChange)="onDateRangeChange($event)">
|
|
232
|
+
</ngx-dual-datepicker>
|
|
233
|
+
`
|
|
234
|
+
})
|
|
235
|
+
export class AppComponent {
|
|
236
|
+
// ...
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
```scss
|
|
241
|
+
// styles.scss
|
|
242
|
+
@import 'bootstrap/scss/bootstrap';
|
|
243
|
+
@import '@oneluiz/dual-datepicker/themes/bootstrap';
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Tailwind Project
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
// app.component.ts
|
|
250
|
+
template: `
|
|
251
|
+
<ngx-dual-datepicker
|
|
252
|
+
theme="tailwind"
|
|
253
|
+
[presets]="presets">
|
|
254
|
+
</ngx-dual-datepicker>
|
|
255
|
+
`
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
```scss
|
|
259
|
+
// styles.scss
|
|
260
|
+
@import 'tailwindcss/base';
|
|
261
|
+
@import 'tailwindcss/components';
|
|
262
|
+
@import 'tailwindcss/utilities';
|
|
263
|
+
@import '@oneluiz/dual-datepicker/themes/tailwind';
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Custom Branded Theme
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// app.component.ts
|
|
270
|
+
template: `
|
|
271
|
+
<ngx-dual-datepicker
|
|
272
|
+
theme="custom"
|
|
273
|
+
[presets]="presets">
|
|
274
|
+
</ngx-dual-datepicker>
|
|
275
|
+
`
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
```scss
|
|
279
|
+
// styles.scss
|
|
280
|
+
@import '@oneluiz/dual-datepicker/themes/custom';
|
|
281
|
+
|
|
282
|
+
.datepicker-wrapper.theme-custom {
|
|
283
|
+
--dp-primary-color: #your-brand-color;
|
|
284
|
+
--dp-primary-hover: #your-brand-hover-color;
|
|
285
|
+
--dp-border-radius: 0.75rem;
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## FAQ
|
|
290
|
+
|
|
291
|
+
**Q: Can I use multiple themes in the same application?**
|
|
292
|
+
A: Yes, but you'll need to import all the theme stylesheets you plan to use. Each component can have its own theme.
|
|
293
|
+
|
|
294
|
+
**Q: Do I need to import Bootstrap/Bulma/Foundation/Tailwind CSS separately?**
|
|
295
|
+
A: Yes, the theme stylesheets only provide datepicker-specific styles. You need to have the base framework CSS loaded in your project.
|
|
296
|
+
|
|
297
|
+
**Q: Can I switch themes dynamically?**
|
|
298
|
+
A: Yes, you can bind the `theme` input to a variable and change it at runtime.
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
currentTheme: ThemeType = 'bootstrap';
|
|
302
|
+
|
|
303
|
+
switchTheme() {
|
|
304
|
+
this.currentTheme = this.currentTheme === 'bootstrap' ? 'bulma' : 'bootstrap';
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**Q: What happens if I don't import the theme stylesheet?**
|
|
309
|
+
A: The component will still work but will use the default inline styles. The theme-specific styles won't be applied.
|
|
310
|
+
|
|
311
|
+
## Support
|
|
312
|
+
|
|
313
|
+
For issues or questions about theming, please visit [GitHub Issues](https://github.com/oneluiz/ng-dual-datepicker/issues).
|
|
@@ -5,6 +5,8 @@ export interface DateRange {
|
|
|
5
5
|
startDate: string;
|
|
6
6
|
endDate: string;
|
|
7
7
|
rangeText: string;
|
|
8
|
+
startTime?: string;
|
|
9
|
+
endTime?: string;
|
|
8
10
|
}
|
|
9
11
|
export interface MultiDateRange {
|
|
10
12
|
ranges: DateRange[];
|
|
@@ -24,6 +26,7 @@ export interface LocaleConfig {
|
|
|
24
26
|
dayNamesShort?: string[];
|
|
25
27
|
firstDayOfWeek?: number;
|
|
26
28
|
}
|
|
29
|
+
export type ThemeType = 'default' | 'bootstrap' | 'bulma' | 'foundation' | 'tailwind' | 'custom';
|
|
27
30
|
export declare class DualDatepickerComponent implements OnInit, OnChanges, ControlValueAccessor {
|
|
28
31
|
private elementRef;
|
|
29
32
|
placeholder: string;
|
|
@@ -37,6 +40,7 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
|
|
|
37
40
|
closeOnClickOutside: boolean;
|
|
38
41
|
enableKeyboardNavigation: boolean;
|
|
39
42
|
presets: PresetConfig[];
|
|
43
|
+
theme: ThemeType;
|
|
40
44
|
inputBackgroundColor: string;
|
|
41
45
|
inputTextColor: string;
|
|
42
46
|
inputBorderColor: string;
|
|
@@ -47,6 +51,11 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
|
|
|
47
51
|
disabledDates: Date[] | ((date: Date) => boolean) | undefined;
|
|
48
52
|
displayFormat: string;
|
|
49
53
|
requireApply: boolean;
|
|
54
|
+
enableTimePicker: boolean;
|
|
55
|
+
timeFormat: '12h' | '24h';
|
|
56
|
+
minuteStep: number;
|
|
57
|
+
defaultStartTime: string;
|
|
58
|
+
defaultEndTime: string;
|
|
50
59
|
dateRangeChange: EventEmitter<DateRange>;
|
|
51
60
|
dateRangeSelected: EventEmitter<DateRange>;
|
|
52
61
|
multiDateRangeChange: EventEmitter<MultiDateRange>;
|
|
@@ -63,6 +72,12 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
|
|
|
63
72
|
pendingStartDate: string;
|
|
64
73
|
pendingEndDate: string;
|
|
65
74
|
hasPendingChanges: import("@angular/core").WritableSignal<boolean>;
|
|
75
|
+
startHour: number;
|
|
76
|
+
startMinute: number;
|
|
77
|
+
endHour: number;
|
|
78
|
+
endMinute: number;
|
|
79
|
+
showStartTimePicker: import("@angular/core").WritableSignal<boolean>;
|
|
80
|
+
showEndTimePicker: import("@angular/core").WritableSignal<boolean>;
|
|
66
81
|
hoverDate: import("@angular/core").WritableSignal<string>;
|
|
67
82
|
selectedRanges: import("@angular/core").WritableSignal<DateRange[]>;
|
|
68
83
|
currentRangeIndex: import("@angular/core").WritableSignal<number>;
|
|
@@ -121,10 +136,25 @@ export declare class DualDatepickerComponent implements OnInit, OnChanges, Contr
|
|
|
121
136
|
private emitMultiChange;
|
|
122
137
|
private emitMultiSelection;
|
|
123
138
|
private getDateRangeValue;
|
|
139
|
+
toggleStartTimePicker(): void;
|
|
140
|
+
toggleEndTimePicker(): void;
|
|
141
|
+
incrementStartHour(): void;
|
|
142
|
+
decrementStartHour(): void;
|
|
143
|
+
incrementStartMinute(): void;
|
|
144
|
+
decrementStartMinute(): void;
|
|
145
|
+
incrementEndHour(): void;
|
|
146
|
+
decrementEndHour(): void;
|
|
147
|
+
incrementEndMinute(): void;
|
|
148
|
+
decrementEndMinute(): void;
|
|
149
|
+
formatTime(hour: number, minute: number): string;
|
|
150
|
+
parseTime(timeString: string): {
|
|
151
|
+
hour: number;
|
|
152
|
+
minute: number;
|
|
153
|
+
};
|
|
124
154
|
writeValue(value: DateRange | null): void;
|
|
125
155
|
registerOnChange(fn: (value: DateRange | null) => void): void;
|
|
126
156
|
registerOnTouched(fn: () => void): void;
|
|
127
157
|
setDisabledState(isDisabled: boolean): void;
|
|
128
158
|
static ɵfac: i0.ɵɵFactoryDeclaration<DualDatepickerComponent, never>;
|
|
129
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<DualDatepickerComponent, "ngx-dual-datepicker", never, { "placeholder": { "alias": "placeholder"; "required": false; }; "startDate": { "alias": "startDate"; "required": false; }; "endDate": { "alias": "endDate"; "required": false; }; "showPresets": { "alias": "showPresets"; "required": false; }; "showClearButton": { "alias": "showClearButton"; "required": false; }; "multiRange": { "alias": "multiRange"; "required": false; }; "closeOnSelection": { "alias": "closeOnSelection"; "required": false; }; "closeOnPresetSelection": { "alias": "closeOnPresetSelection"; "required": false; }; "closeOnClickOutside": { "alias": "closeOnClickOutside"; "required": false; }; "enableKeyboardNavigation": { "alias": "enableKeyboardNavigation"; "required": false; }; "presets": { "alias": "presets"; "required": false; }; "inputBackgroundColor": { "alias": "inputBackgroundColor"; "required": false; }; "inputTextColor": { "alias": "inputTextColor"; "required": false; }; "inputBorderColor": { "alias": "inputBorderColor"; "required": false; }; "inputBorderColorHover": { "alias": "inputBorderColorHover"; "required": false; }; "inputBorderColorFocus": { "alias": "inputBorderColorFocus"; "required": false; }; "inputPadding": { "alias": "inputPadding"; "required": false; }; "locale": { "alias": "locale"; "required": false; }; "disabledDates": { "alias": "disabledDates"; "required": false; }; "displayFormat": { "alias": "displayFormat"; "required": false; }; "requireApply": { "alias": "requireApply"; "required": false; }; }, { "dateRangeChange": "dateRangeChange"; "dateRangeSelected": "dateRangeSelected"; "multiDateRangeChange": "multiDateRangeChange"; "multiDateRangeSelected": "multiDateRangeSelected"; }, never, never, true, never>;
|
|
159
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<DualDatepickerComponent, "ngx-dual-datepicker", never, { "placeholder": { "alias": "placeholder"; "required": false; }; "startDate": { "alias": "startDate"; "required": false; }; "endDate": { "alias": "endDate"; "required": false; }; "showPresets": { "alias": "showPresets"; "required": false; }; "showClearButton": { "alias": "showClearButton"; "required": false; }; "multiRange": { "alias": "multiRange"; "required": false; }; "closeOnSelection": { "alias": "closeOnSelection"; "required": false; }; "closeOnPresetSelection": { "alias": "closeOnPresetSelection"; "required": false; }; "closeOnClickOutside": { "alias": "closeOnClickOutside"; "required": false; }; "enableKeyboardNavigation": { "alias": "enableKeyboardNavigation"; "required": false; }; "presets": { "alias": "presets"; "required": false; }; "theme": { "alias": "theme"; "required": false; }; "inputBackgroundColor": { "alias": "inputBackgroundColor"; "required": false; }; "inputTextColor": { "alias": "inputTextColor"; "required": false; }; "inputBorderColor": { "alias": "inputBorderColor"; "required": false; }; "inputBorderColorHover": { "alias": "inputBorderColorHover"; "required": false; }; "inputBorderColorFocus": { "alias": "inputBorderColorFocus"; "required": false; }; "inputPadding": { "alias": "inputPadding"; "required": false; }; "locale": { "alias": "locale"; "required": false; }; "disabledDates": { "alias": "disabledDates"; "required": false; }; "displayFormat": { "alias": "displayFormat"; "required": false; }; "requireApply": { "alias": "requireApply"; "required": false; }; "enableTimePicker": { "alias": "enableTimePicker"; "required": false; }; "timeFormat": { "alias": "timeFormat"; "required": false; }; "minuteStep": { "alias": "minuteStep"; "required": false; }; "defaultStartTime": { "alias": "defaultStartTime"; "required": false; }; "defaultEndTime": { "alias": "defaultEndTime"; "required": false; }; }, { "dateRangeChange": "dateRangeChange"; "dateRangeSelected": "dateRangeSelected"; "multiDateRangeChange": "multiDateRangeChange"; "multiDateRangeSelected": "multiDateRangeSelected"; }, never, never, true, never>;
|
|
130
160
|
}
|