@hug/ngx-time-picker 3.0.0 → 3.0.2
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/CHANGELOG.md +31 -0
- package/fesm2022/hug-ngx-time-picker-testing.mjs +69 -0
- package/fesm2022/hug-ngx-time-picker-testing.mjs.map +1 -0
- package/fesm2022/hug-ngx-time-picker.mjs +64 -141
- package/fesm2022/hug-ngx-time-picker.mjs.map +1 -1
- package/package.json +6 -2
- package/testing/index.d.ts +2 -0
- package/testing/time-picker-harness-filters.d.ts +4 -0
- package/testing/time-picker-harness.d.ts +17 -0
- package/time-picker.component.d.ts +13 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
## 3.0.2 (2025-05-12)
|
|
2
|
+
|
|
3
|
+
### 🐛 Fixes
|
|
4
|
+
|
|
5
|
+
- **ngx-time-picker:** fix review ([1a16fef](https://github.com/DSI-HUG/ngx-components/commit/1a16fef))
|
|
6
|
+
- **ngx-time-picker:** améliorer le time-picker pour qu'il soit accessible via cypress FC-95 ([897e0d5](https://github.com/DSI-HUG/ngx-components/commit/897e0d5))
|
|
7
|
+
- **ngx-time-picker:** améliorer le time-picker pour qu'il soit accessible via cypress FC-95 ([ced57e7](https://github.com/DSI-HUG/ngx-components/commit/ced57e7))
|
|
8
|
+
|
|
9
|
+
### 🌱 Dependencies
|
|
10
|
+
|
|
11
|
+
- **@hug/ngx-numeric-stepper:** upgrade to v1.1.12 ([91140c1](https://github.com/DSI-HUG/ngx-components/commit/91140c1))
|
|
12
|
+
|
|
13
|
+
### 🌱 Dependencies
|
|
14
|
+
|
|
15
|
+
- **@hug/ngx-numeric-stepper**: upgraded to `v3.0.2`
|
|
16
|
+
|
|
17
|
+
### ❤️ Thank You
|
|
18
|
+
|
|
19
|
+
- dsi-hug-bot @dsi-hug-bot
|
|
20
|
+
- Serge
|
|
21
|
+
|
|
22
|
+
## 3.0.1 (2025-03-13)
|
|
23
|
+
|
|
24
|
+
### 🌱 Dependencies
|
|
25
|
+
|
|
26
|
+
- **@hug/ngx-numeric-stepper:** upgrade to v3.0.1 ([e286509](https://github.com/DSI-HUG/ngx-components/commit/e286509))
|
|
27
|
+
|
|
28
|
+
### ❤️ Thank You
|
|
29
|
+
|
|
30
|
+
- dsi-hug-bot @dsi-hug-bot
|
|
31
|
+
|
|
1
32
|
# 3.0.0 (2025-02-06)
|
|
2
33
|
|
|
3
34
|
### 🚀 Features
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { HarnessPredicate } from '@angular/cdk/testing';
|
|
2
|
+
import { MatFormFieldControlHarness } from '@angular/material/form-field/testing/control';
|
|
3
|
+
import { MatInputHarness } from '@angular/material/input/testing';
|
|
4
|
+
|
|
5
|
+
/** Harness for interacting with a ngx time picker in tests. */
|
|
6
|
+
class NgxTimePickerHarness extends MatFormFieldControlHarness {
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
8
|
+
static hostSelector = 'ngx-time-picker';
|
|
9
|
+
static with(options = {}) {
|
|
10
|
+
return new HarnessPredicate(NgxTimePickerHarness, options).addOption('value', options.value, (harness, value) => HarnessPredicate.stringMatches(harness.getValue(), value));
|
|
11
|
+
}
|
|
12
|
+
async getHoursInput() {
|
|
13
|
+
return (await this.locatorFactory.harnessLoaderFor('.hours')).getHarness(MatInputHarness.with({ selector: '[matInput]' }));
|
|
14
|
+
}
|
|
15
|
+
async getMinutesInput() {
|
|
16
|
+
return (await this.locatorFactory.harnessLoaderFor('.minutes')).getHarness(MatInputHarness.with({ selector: '[matInput]' }));
|
|
17
|
+
}
|
|
18
|
+
async setValue(value) {
|
|
19
|
+
const hoursMinutes = value.split(':');
|
|
20
|
+
if (hoursMinutes[0].length) {
|
|
21
|
+
await this.getHoursInput().then(async (hoursInput) => {
|
|
22
|
+
await hoursInput.host().then(async (hoursElement) => {
|
|
23
|
+
await hoursElement.clear();
|
|
24
|
+
await hoursInput.setValue(hoursMinutes[0]);
|
|
25
|
+
await hoursInput.blur();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (hoursMinutes[1].length) {
|
|
30
|
+
await this.getMinutesInput().then(async (minutesInput) => {
|
|
31
|
+
await minutesInput.host().then(async (minutesElement) => {
|
|
32
|
+
await minutesElement.clear();
|
|
33
|
+
await minutesInput.setValue(hoursMinutes[1]);
|
|
34
|
+
await minutesElement.blur();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async getValue() {
|
|
40
|
+
return this.getHoursValue().then(hoursValue => this.getMinutesValue().then(minutesValue => `${hoursValue}:${minutesValue}`));
|
|
41
|
+
}
|
|
42
|
+
async getHoursValue() {
|
|
43
|
+
return this.getHoursInput().then(hoursInput => hoursInput.getValue());
|
|
44
|
+
}
|
|
45
|
+
async getMinutesValue() {
|
|
46
|
+
return this.getMinutesInput().then(minutesInput => minutesInput.getValue());
|
|
47
|
+
}
|
|
48
|
+
async sendKeysToHoursInput(...keys) {
|
|
49
|
+
return this.getHoursInput().then(async (hoursInput) => {
|
|
50
|
+
await hoursInput.host().then(async (hoursElement) => {
|
|
51
|
+
await hoursElement.sendKeys(...keys);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
async sendKeysToMinutesInput(...keys) {
|
|
56
|
+
return this.getMinutesInput().then(async (minutesInput) => {
|
|
57
|
+
await minutesInput.host().then(async (minutesElement) => {
|
|
58
|
+
await minutesElement.sendKeys(...keys);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Generated bundle index. Do not edit.
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
export { NgxTimePickerHarness };
|
|
69
|
+
//# sourceMappingURL=hug-ngx-time-picker-testing.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hug-ngx-time-picker-testing.mjs","sources":["../../../projects/time-picker/testing/time-picker-harness.ts","../../../projects/time-picker/testing/hug-ngx-time-picker-testing.ts"],"sourcesContent":["import { HarnessPredicate, TestKey } from '@angular/cdk/testing';\nimport { MatFormFieldControlHarness } from '@angular/material/form-field/testing/control';\nimport { MatInputHarness } from '@angular/material/input/testing';\n\nimport { NgxTimePickerHarnessFilters } from './time-picker-harness-filters';\n\n/** Harness for interacting with a ngx time picker in tests. */\nexport class NgxTimePickerHarness extends MatFormFieldControlHarness {\n\n // eslint-disable-next-line @typescript-eslint/naming-convention\n public static hostSelector = 'ngx-time-picker';\n\n static with(options: NgxTimePickerHarnessFilters = {}): HarnessPredicate<NgxTimePickerHarness> {\n return new HarnessPredicate(NgxTimePickerHarness, options).addOption('value', options.value, (harness, value) => HarnessPredicate.stringMatches(harness.getValue(), value));\n }\n\n public async getHoursInput(): Promise<MatInputHarness> {\n return (await this.locatorFactory.harnessLoaderFor('.hours')).getHarness(MatInputHarness.with({ selector: '[matInput]' }));\n }\n\n public async getMinutesInput(): Promise<MatInputHarness> {\n return (await this.locatorFactory.harnessLoaderFor('.minutes')).getHarness(MatInputHarness.with({ selector: '[matInput]' }));\n }\n\n public async setValue(value: string): Promise<void> {\n const hoursMinutes = value.split(':');\n\n if (hoursMinutes[0].length) {\n await this.getHoursInput().then(async hoursInput => {\n await hoursInput.host().then(async hoursElement => {\n await hoursElement.clear();\n await hoursInput.setValue(hoursMinutes[0]);\n await hoursInput.blur();\n });\n });\n }\n\n if (hoursMinutes[1].length) {\n await this.getMinutesInput().then(async minutesInput => {\n await minutesInput.host().then(async minutesElement => {\n await minutesElement.clear();\n await minutesInput.setValue(hoursMinutes[1]);\n await minutesElement.blur();\n });\n });\n }\n }\n\n public async getValue(): Promise<string> {\n return this.getHoursValue().then(hoursValue => this.getMinutesValue().then(minutesValue => `${hoursValue}:${minutesValue}`));\n }\n\n public async getHoursValue(): Promise<string> {\n return this.getHoursInput().then(hoursInput => hoursInput.getValue());\n }\n\n public async getMinutesValue(): Promise<string> {\n return this.getMinutesInput().then(minutesInput => minutesInput.getValue());\n }\n\n public async sendKeysToHoursInput(...keys: readonly TestKey[]): Promise<void> {\n return this.getHoursInput().then(async hoursInput => {\n await hoursInput.host().then(async hoursElement => {\n await hoursElement.sendKeys(...keys);\n });\n });\n }\n\n public async sendKeysToMinutesInput(...keys: readonly TestKey[]): Promise<void> {\n return this.getMinutesInput().then(async minutesInput => {\n await minutesInput.host().then(async minutesElement => {\n await minutesElement.sendKeys(...keys);\n });\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
|
|
2
2
|
import { DecimalPipe } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { EventEmitter, inject, ChangeDetectorRef,
|
|
4
|
+
import { EventEmitter, inject, ChangeDetectorRef, Input, Output, ViewChild, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
5
5
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
6
6
|
import * as i1 from '@angular/forms';
|
|
7
7
|
import { NgControl, FormsModule } from '@angular/forms';
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
8
|
+
import * as i2 from '@angular/material/form-field';
|
|
9
|
+
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
10
|
+
import * as i3 from '@angular/material/input';
|
|
11
|
+
import { MatInputModule } from '@angular/material/input';
|
|
10
12
|
import { NgxNumericStepperComponent } from '@hug/ngx-numeric-stepper';
|
|
11
|
-
import { set
|
|
12
|
-
import { Subject,
|
|
13
|
+
import { set } from 'date-fns';
|
|
14
|
+
import { Subject, distinctUntilChanged, map, tap, debounceTime, switchMap, EMPTY, timer, mergeWith } from 'rxjs';
|
|
13
15
|
|
|
14
|
-
// TODO sdil refactor rxjs flows
|
|
15
16
|
class NgxTimePickerComponent {
|
|
16
17
|
hours;
|
|
17
18
|
minutes;
|
|
18
19
|
timeChange = new EventEmitter();
|
|
19
20
|
/** Display mode for the time-picker */
|
|
20
21
|
mode = 'fullTime';
|
|
21
|
-
/** Data type to manage (Date or Duration) */
|
|
22
|
-
dataType = 'date';
|
|
23
22
|
/**
|
|
24
23
|
* Force the hour or minute to be null (only if the other field is disabled)
|
|
25
24
|
*
|
|
@@ -57,12 +56,12 @@ class NgxTimePickerComponent {
|
|
|
57
56
|
get disabled() {
|
|
58
57
|
return this._disabled;
|
|
59
58
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
hoursChange$ = new Subject();
|
|
60
|
+
minutesChange$ = new Subject();
|
|
61
|
+
hoursKeyDown$ = new Subject();
|
|
63
62
|
changeDetectorRef = inject(ChangeDetectorRef);
|
|
64
63
|
control = inject(NgControl, { optional: true, self: true });
|
|
65
|
-
|
|
64
|
+
_step = 1;
|
|
66
65
|
_disabled = false;
|
|
67
66
|
_value;
|
|
68
67
|
_autoFocus = true;
|
|
@@ -70,39 +69,23 @@ class NgxTimePickerComponent {
|
|
|
70
69
|
if (this.control) {
|
|
71
70
|
this.control.valueAccessor = this;
|
|
72
71
|
}
|
|
73
|
-
this.
|
|
72
|
+
const hoursChange$ = this.hoursChange$.pipe(distinctUntilChanged(), map(hours => {
|
|
74
73
|
if (typeof hours === 'object') {
|
|
75
74
|
const value = hours.target.value;
|
|
76
75
|
return [value !== undefined ? parseInt(value, 10) : undefined, true];
|
|
77
76
|
}
|
|
78
77
|
return [!isNaN(hours) ? hours : 0, false];
|
|
79
|
-
}),
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
}), tap(([hours, _isEvent]) => {
|
|
79
|
+
const newValue = this.value ? new Date(this.value.getTime()) : new Date();
|
|
80
|
+
if (hours !== undefined) {
|
|
81
|
+
newValue.setHours(hours);
|
|
82
82
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const clone = new Date(value);
|
|
86
|
-
if (hours !== undefined) {
|
|
87
|
-
clone.setHours(hours);
|
|
88
|
-
}
|
|
89
|
-
this.value = clone;
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
this.value = {
|
|
93
|
-
hours: hours && hours < 0 ? 0 : hours,
|
|
94
|
-
minutes: this.value.minutes
|
|
95
|
-
};
|
|
83
|
+
if (this.mode === 'fullTime' || this.mode === 'fullTimeWithMinutesDisabled' || this.mode === 'hoursOnly') {
|
|
84
|
+
this.value = newValue;
|
|
96
85
|
}
|
|
97
86
|
this.changeDetectorRef.markForCheck();
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
preventScroll: true
|
|
101
|
-
});
|
|
102
|
-
this.minutes.nativeElement.select();
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
this.onMinutesChange$.pipe(debounce(minutes => timer(typeof minutes === 'object' ? 0 : 10)), distinctUntilChanged(), map(event => {
|
|
87
|
+
}));
|
|
88
|
+
const minutesChange$ = this.minutesChange$.pipe(distinctUntilChanged(), map(event => {
|
|
106
89
|
let minutes;
|
|
107
90
|
if (typeof event === 'object') {
|
|
108
91
|
const value = event.target.value;
|
|
@@ -112,109 +95,39 @@ class NgxTimePickerComponent {
|
|
|
112
95
|
minutes = event;
|
|
113
96
|
}
|
|
114
97
|
return minutes && !isNaN(minutes) && minutes || 0;
|
|
115
|
-
}),
|
|
116
|
-
|
|
117
|
-
|
|
98
|
+
}), tap(minutes => {
|
|
99
|
+
const newValue = this.value ? new Date(this.value.getTime()) : new Date();
|
|
100
|
+
if (minutes < 0) {
|
|
101
|
+
minutes += 60;
|
|
118
102
|
}
|
|
119
|
-
else if (
|
|
120
|
-
|
|
121
|
-
if (minutes < 0) {
|
|
122
|
-
minutes += 60;
|
|
123
|
-
}
|
|
124
|
-
else if (minutes >= 60) {
|
|
125
|
-
minutes -= 60;
|
|
126
|
-
}
|
|
127
|
-
newValue.setMinutes(minutes);
|
|
128
|
-
if (this.mode !== 'fullTimeWithHoursDisabled' || (this.mode === 'fullTimeWithHoursDisabled' && isSameHour(this.value, newValue))) {
|
|
129
|
-
this.value = newValue;
|
|
130
|
-
}
|
|
103
|
+
else if (minutes >= 60) {
|
|
104
|
+
minutes -= 60;
|
|
131
105
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
minutes: minutes < 0 || minutes >= 60 ? 0 : minutes
|
|
136
|
-
};
|
|
106
|
+
newValue.setMinutes(minutes);
|
|
107
|
+
if (this.mode === 'fullTime' || this.mode === 'fullTimeWithHoursDisabled' || this.mode === 'minutesOnly') {
|
|
108
|
+
this.value = newValue;
|
|
137
109
|
}
|
|
138
110
|
this.changeDetectorRef.markForCheck();
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
this.value = new Date();
|
|
148
|
-
}
|
|
149
|
-
else if (inputElement) {
|
|
150
|
-
if ($event.key?.toLowerCase() === 'a' && $event.ctrlKey) {
|
|
151
|
-
inputElement.select();
|
|
152
|
-
}
|
|
153
|
-
else if ($event.key && !['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Backspace', 'Delete', 'Tab', 'Enter', 'Control', 'Shift'].includes($event.key)) {
|
|
154
|
-
// Set regex for input format validation (differs if we are dealing with a date or a duration)
|
|
155
|
-
let regex;
|
|
156
|
-
if (mode === 'hours') {
|
|
157
|
-
regex = this.dataType === 'date' ? /^(\d|[01]\d|2[0-3])$/ : /^(\d+)$/;
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
regex = /^(\d|[0-5]\d)$/;
|
|
161
|
-
}
|
|
162
|
-
// Get the selection in input element
|
|
111
|
+
}));
|
|
112
|
+
const setFocusToNextInput$ = this.hoursKeyDown$.pipe(debounceTime(200), switchMap(event => {
|
|
113
|
+
const inputElement = this.hours?.nativeElement;
|
|
114
|
+
if (!inputElement) {
|
|
115
|
+
return EMPTY;
|
|
116
|
+
}
|
|
117
|
+
if (event.key && !event.ctrlKey && !event.shiftKey && !event.altKey && !['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Backspace', 'Delete', 'Tab', 'Enter', 'Control', 'Shift'].includes(event.key)) {
|
|
118
|
+
const regex = /^(\d|[01]\d|2[0-3])$/;
|
|
163
119
|
const [selectionStart, selectionEnd] = [inputElement.selectionStart || 0, inputElement.selectionEnd || 0].sort((a, b) => a - b);
|
|
164
|
-
const selectionDiff = selectionEnd - selectionStart;
|
|
165
|
-
// Get the current value in input element and update it with the new touched key
|
|
166
120
|
const inputValue = inputElement.value || '';
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
$event.stopPropagation();
|
|
173
|
-
$event.preventDefault();
|
|
174
|
-
}
|
|
175
|
-
else if (this._autoFocus && mode === 'hours' && ((this.dataType === 'date' && parseFloat(newInputValue) >= 3) || newInputValue.length === 2)) {
|
|
176
|
-
this.onHoursChange$.next($event);
|
|
121
|
+
if (regex.test(inputValue) && this._autoFocus && inputValue.length === 2 && this.minutes?.nativeElement && inputElement === document.activeElement && selectionStart === 2 && selectionEnd === 2) {
|
|
122
|
+
this.minutes.nativeElement.focus();
|
|
123
|
+
return timer(0).pipe(tap(() => {
|
|
124
|
+
this.minutes?.nativeElement.select();
|
|
125
|
+
}));
|
|
177
126
|
}
|
|
178
127
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (!this.value || (this.forceNullValue && this.mode === 'fullTimeWithMinutesDisabled' && !!this.control?.pristine)) {
|
|
183
|
-
return undefined;
|
|
184
|
-
}
|
|
185
|
-
return this.value instanceof Date ? this.value.getHours() : this.value.hours;
|
|
186
|
-
}
|
|
187
|
-
get minutesValue() {
|
|
188
|
-
if (!this.value || (this.forceNullValue && this.mode === 'fullTimeWithHoursDisabled' && !!this.control?.pristine)) {
|
|
189
|
-
return undefined;
|
|
190
|
-
}
|
|
191
|
-
return this.value instanceof Date ? this.value.getMinutes() : this.value.minutes;
|
|
192
|
-
}
|
|
193
|
-
incrementValue(fieldType) {
|
|
194
|
-
if (fieldType === 'hours') {
|
|
195
|
-
this.onHoursChange$.next((this.hoursValue || 0) + 1);
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
this.onMinutesChange$.next((this.minutesValue || 0) + this._step);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
decrementValue(fieldType) {
|
|
202
|
-
if (fieldType === 'hours') {
|
|
203
|
-
this.onHoursChange$.next((this.hoursValue || 0) - 1);
|
|
204
|
-
}
|
|
205
|
-
else {
|
|
206
|
-
this.onMinutesChange$.next((this.minutesValue || 0) - this._step);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
onClick(mode) {
|
|
210
|
-
if (this._autoFocus) {
|
|
211
|
-
if (mode === 'hours') {
|
|
212
|
-
this.hours?.nativeElement.select();
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
this.minutes?.nativeElement.select();
|
|
216
|
-
}
|
|
217
|
-
}
|
|
128
|
+
return EMPTY;
|
|
129
|
+
}));
|
|
130
|
+
hoursChange$.pipe(mergeWith(minutesChange$, setFocusToNextInput$), takeUntilDestroyed()).subscribe();
|
|
218
131
|
}
|
|
219
132
|
// ************* ControlValueAccessor Implementation **************
|
|
220
133
|
/** set accessor including call the onchange callback */
|
|
@@ -253,20 +166,32 @@ class NgxTimePickerComponent {
|
|
|
253
166
|
this.disabled = isDisabled;
|
|
254
167
|
}
|
|
255
168
|
// ************* End of ControlValueAccessor Implementation **************
|
|
169
|
+
get hoursValue() {
|
|
170
|
+
if (!this.value || (this.forceNullValue && this.mode === 'fullTimeWithMinutesDisabled' && !!this.control?.pristine)) {
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
return this.value.getHours();
|
|
174
|
+
}
|
|
175
|
+
get minutesValue() {
|
|
176
|
+
if (!this.value || (this.forceNullValue && this.mode === 'fullTimeWithHoursDisabled' && !!this.control?.pristine)) {
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
return this.value.getMinutes();
|
|
180
|
+
}
|
|
256
181
|
onChangeCallback = (_a) => undefined;
|
|
257
182
|
onTouchedCallback = () => undefined;
|
|
258
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.
|
|
259
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.
|
|
183
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: NgxTimePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
184
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.8", type: NgxTimePickerComponent, isStandalone: true, selector: "ngx-time-picker", inputs: { mode: "mode", forceNullValue: "forceNullValue", appearance: "appearance", autoFocus: "autoFocus", defaultPlaceholderHours: "defaultPlaceholderHours", defaultPlaceholderMinutes: "defaultPlaceholderMinutes", time: "time", step: "step", disabled: "disabled" }, outputs: { timeChange: "timeChange" }, viewQueries: [{ propertyName: "hours", first: true, predicate: ["hours"], descendants: true }, { propertyName: "minutes", first: true, predicate: ["minutes"], descendants: true }], ngImport: i0, template: "<!-- Hours -->\n<mat-form-field\n [appearance]=\"appearance\"\n class=\"hours\"\n [class.disabled]=\"disabled || mode === 'fullTimeWithHoursDisabled'\"\n [style.display]=\"mode === 'minutesOnly' ? 'none' : 'block'\">\n <input\n aria-label=\"hours\"\n #hours\n matInput\n [attr.hours]=\"hoursValue\"\n type=\"text\"\n [ngModel]=\"hoursValue | number: '2.'\"\n (ngModelChange)=\"hoursChange$.next($event)\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n (keydown)=\"hoursKeyDown$.next($event)\"\n [disabled]=\"disabled || mode === 'fullTimeWithHoursDisabled'\"\n [maxLength]=\"2\"\n autocomplete=\"off\"\n [placeholder]=\"defaultPlaceholderHours\"\n (click)=\"hours.select()\" />\n <ngx-numeric-stepper\n (increment)=\"hoursChange$.next((hoursValue || 0) + 1)\"\n (decrement)=\"hoursChange$.next((hoursValue || 0) - 1)\"></ngx-numeric-stepper>\n</mat-form-field>\n\n<!-- Separator -->\n<span class=\"time-separator\" [style.display]=\"mode === 'minutesOnly' || mode === 'hoursOnly' ? 'none' : 'block'\">\n :\n</span>\n\n<!-- Minutes -->\n<mat-form-field\n [appearance]=\"appearance\"\n class=\"minutes\"\n [class.disabled]=\"disabled || mode === 'fullTimeWithMinutesDisabled'\"\n [style.display]=\"mode === 'hoursOnly' ? 'none' : 'block'\">\n <input\n aria-label=\"minutes\"\n #minutes\n matInput\n [attr.minutes]=\"minutesValue\"\n type=\"text\"\n [ngModel]=\"minutesValue | number: '2.'\"\n (ngModelChange)=\"minutesChange$.next($event)\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n [disabled]=\"disabled || mode === 'fullTimeWithMinutesDisabled'\"\n [maxLength]=\"2\"\n autocomplete=\"off\"\n [placeholder]=\"defaultPlaceholderMinutes\"\n (click)=\"minutes.select()\" />\n <ngx-numeric-stepper\n (increment)=\"minutesChange$.next((minutesValue || 0) + _step)\"\n (decrement)=\"minutesChange$.next((minutesValue || 0) - _step)\"></ngx-numeric-stepper>\n</mat-form-field>\n", styles: ["ngx-time-picker{display:flex;flex-direction:row;align-items:baseline;justify-content:center}ngx-time-picker:not([inform]) .mat-form-field-appearance-outline .mat-mdc-form-field-wrapper{padding-bottom:0}ngx-time-picker:not([inform]) .mat-form-field-appearance-outline .mat-mdc-form-field-wrapper .mat-mdc-form-field-infix{border-bottom:.7em solid transparent}ngx-time-picker mat-form-field[ngx-numeric-stepper-form-field]{width:52px}ngx-time-picker .time-separator{width:4px;font-size:14.5px;line-height:17px;margin:0 8px}\n"], dependencies: [{ kind: "pipe", type: DecimalPipe, name: "number" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: NgxNumericStepperComponent, selector: "ngx-numeric-stepper", inputs: ["layout", "input", "arrowIcons", "showOnInit"], outputs: ["increment", "decrement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
260
185
|
}
|
|
261
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.
|
|
186
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.8", ngImport: i0, type: NgxTimePickerComponent, decorators: [{
|
|
262
187
|
type: Component,
|
|
263
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngx-time-picker', encapsulation: ViewEncapsulation.None, imports: [
|
|
188
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngx-time-picker', encapsulation: ViewEncapsulation.None, standalone: true, imports: [
|
|
264
189
|
DecimalPipe,
|
|
265
190
|
FormsModule,
|
|
266
|
-
|
|
267
|
-
|
|
191
|
+
MatFormFieldModule,
|
|
192
|
+
MatInputModule,
|
|
268
193
|
NgxNumericStepperComponent
|
|
269
|
-
], template: "<!-- Hours -->\n<mat-form-field\n [appearance]=\"appearance\"\n class=\"hours\"\n [class.disabled]=\"disabled || mode === 'fullTimeWithHoursDisabled'\"\n [style.display]=\"mode === 'minutesOnly' ? 'none' : 'block'\">\n <input\n #hours\n matInput\n type=\"text\"\n [ngModel]=\"hoursValue | number: '2.'\"\n (
|
|
194
|
+
], template: "<!-- Hours -->\n<mat-form-field\n [appearance]=\"appearance\"\n class=\"hours\"\n [class.disabled]=\"disabled || mode === 'fullTimeWithHoursDisabled'\"\n [style.display]=\"mode === 'minutesOnly' ? 'none' : 'block'\">\n <input\n aria-label=\"hours\"\n #hours\n matInput\n [attr.hours]=\"hoursValue\"\n type=\"text\"\n [ngModel]=\"hoursValue | number: '2.'\"\n (ngModelChange)=\"hoursChange$.next($event)\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n (keydown)=\"hoursKeyDown$.next($event)\"\n [disabled]=\"disabled || mode === 'fullTimeWithHoursDisabled'\"\n [maxLength]=\"2\"\n autocomplete=\"off\"\n [placeholder]=\"defaultPlaceholderHours\"\n (click)=\"hours.select()\" />\n <ngx-numeric-stepper\n (increment)=\"hoursChange$.next((hoursValue || 0) + 1)\"\n (decrement)=\"hoursChange$.next((hoursValue || 0) - 1)\"></ngx-numeric-stepper>\n</mat-form-field>\n\n<!-- Separator -->\n<span class=\"time-separator\" [style.display]=\"mode === 'minutesOnly' || mode === 'hoursOnly' ? 'none' : 'block'\">\n :\n</span>\n\n<!-- Minutes -->\n<mat-form-field\n [appearance]=\"appearance\"\n class=\"minutes\"\n [class.disabled]=\"disabled || mode === 'fullTimeWithMinutesDisabled'\"\n [style.display]=\"mode === 'hoursOnly' ? 'none' : 'block'\">\n <input\n aria-label=\"minutes\"\n #minutes\n matInput\n [attr.minutes]=\"minutesValue\"\n type=\"text\"\n [ngModel]=\"minutesValue | number: '2.'\"\n (ngModelChange)=\"minutesChange$.next($event)\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n [disabled]=\"disabled || mode === 'fullTimeWithMinutesDisabled'\"\n [maxLength]=\"2\"\n autocomplete=\"off\"\n [placeholder]=\"defaultPlaceholderMinutes\"\n (click)=\"minutes.select()\" />\n <ngx-numeric-stepper\n (increment)=\"minutesChange$.next((minutesValue || 0) + _step)\"\n (decrement)=\"minutesChange$.next((minutesValue || 0) - _step)\"></ngx-numeric-stepper>\n</mat-form-field>\n", styles: ["ngx-time-picker{display:flex;flex-direction:row;align-items:baseline;justify-content:center}ngx-time-picker:not([inform]) .mat-form-field-appearance-outline .mat-mdc-form-field-wrapper{padding-bottom:0}ngx-time-picker:not([inform]) .mat-form-field-appearance-outline .mat-mdc-form-field-wrapper .mat-mdc-form-field-infix{border-bottom:.7em solid transparent}ngx-time-picker mat-form-field[ngx-numeric-stepper-form-field]{width:52px}ngx-time-picker .time-separator{width:4px;font-size:14.5px;line-height:17px;margin:0 8px}\n"] }]
|
|
270
195
|
}], ctorParameters: () => [], propDecorators: { hours: [{
|
|
271
196
|
type: ViewChild,
|
|
272
197
|
args: ['hours']
|
|
@@ -277,8 +202,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImpor
|
|
|
277
202
|
type: Output
|
|
278
203
|
}], mode: [{
|
|
279
204
|
type: Input
|
|
280
|
-
}], dataType: [{
|
|
281
|
-
type: Input
|
|
282
205
|
}], forceNullValue: [{
|
|
283
206
|
type: Input
|
|
284
207
|
}], appearance: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hug-ngx-time-picker.mjs","sources":["../../../projects/time-picker/src/time-picker.component.ts","../../../projects/time-picker/src/time-picker.component.html","../../../projects/time-picker/src/hug-ngx-time-picker.ts"],"sourcesContent":["import { BooleanInput, coerceBooleanProperty, coerceNumberProperty, NumberInput } from '@angular/cdk/coercion';\nimport { DecimalPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, ElementRef, EventEmitter, inject, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor, FormsModule, NgControl } from '@angular/forms';\nimport { MatFormField, MatFormFieldAppearance } from '@angular/material/form-field';\nimport { MatInput } from '@angular/material/input';\nimport { NgxNumericStepperComponent } from '@hug/ngx-numeric-stepper';\nimport { isSameHour, set } from 'date-fns';\nimport { debounce, distinctUntilChanged, map, Subject, timer } from 'rxjs';\n\nexport type NgxTimePickerDisplayMode = 'fullTime' | 'fullTimeWithHoursDisabled' | 'fullTimeWithMinutesDisabled' | 'hoursOnly' | 'minutesOnly';\n\nexport type NgxDateOrDuration = Date | Duration;\n\ntype DataType = 'date' | 'duration';\n\ntype FieldType = 'hours' | 'minutes';\n\n// TODO sdil refactor rxjs flows\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-time-picker',\n styleUrls: ['./time-picker.component.scss'],\n templateUrl: './time-picker.component.html',\n encapsulation: ViewEncapsulation.None,\n imports: [\n DecimalPipe,\n FormsModule,\n MatFormField,\n MatInput,\n NgxNumericStepperComponent\n ]\n})\nexport class NgxTimePickerComponent implements ControlValueAccessor {\n @ViewChild('hours') public hours?: ElementRef<HTMLInputElement>;\n @ViewChild('minutes') public minutes?: ElementRef<HTMLInputElement>;\n\n @Output() public readonly timeChange = new EventEmitter<NgxDateOrDuration>();\n\n /** Display mode for the time-picker */\n @Input() public mode: NgxTimePickerDisplayMode = 'fullTime';\n\n /** Data type to manage (Date or Duration) */\n @Input() public dataType: DataType = 'date';\n\n /**\n * Force the hour or minute to be null (only if the other field is disabled)\n *\n * For instance, if set to true and the hours are disabled, the minutes input value will be null\n * This is useful to force the user to provide a value\n */\n @Input() public forceNullValue = false;\n\n @Input() public appearance: MatFormFieldAppearance = 'outline';\n\n @Input()\n public set autoFocus(value: BooleanInput) {\n this._autoFocus = coerceBooleanProperty(value);\n }\n\n @Input() public defaultPlaceholderHours = '_ _';\n @Input() public defaultPlaceholderMinutes = '_ _';\n\n @Input()\n public set time(value: NgxDateOrDuration | undefined) {\n this.writeValue(value);\n }\n\n public get time(): NgxDateOrDuration | undefined {\n return this.value;\n }\n\n /** Step of the arrows */\n @Input()\n public set step(value: NumberInput) {\n this._step = coerceNumberProperty(value);\n this.changeDetectorRef.markForCheck();\n }\n\n /** To get the step of the minutes arrows */\n public get step(): NumberInput {\n return this._step;\n }\n\n /** Disabled property setter. Can be string or empty so you can use it like : <time-picker disabled></time-picker> */\n @Input()\n public set disabled(value: BooleanInput) {\n this._disabled = coerceBooleanProperty(value);\n this.changeDetectorRef.markForCheck();\n }\n\n /** To get disabled attribute. */\n public get disabled(): BooleanInput {\n return this._disabled;\n }\n\n public onHoursChange$ = new Subject<Event | number>();\n public onMinutesChange$ = new Subject<Event | number>();\n public _step = 1;\n\n protected changeDetectorRef = inject(ChangeDetectorRef);\n protected control = inject(NgControl, { optional: true, self: true });\n private destroyRef = inject(DestroyRef);\n\n private _disabled = false;\n private _value?: NgxDateOrDuration;\n private _autoFocus = true;\n\n public constructor() {\n if (this.control) {\n this.control.valueAccessor = this;\n }\n\n this.onHoursChange$.pipe(\n debounce(hours => timer(typeof hours === 'object' ? 0 : 10)),\n distinctUntilChanged(),\n map(hours => {\n if (typeof hours === 'object') {\n const value = (hours.target as HTMLInputElement).value;\n return [value !== undefined ? parseInt(value, 10) : undefined, true] as const;\n }\n return [!isNaN(hours) ? hours : 0, false] as const;\n }),\n takeUntilDestroyed(this.destroyRef)\n ).subscribe(([hours, isEvent]) => {\n if (!this.value) {\n this.value = this.dataType === 'date' ? set(new Date(), { hours, minutes: 0, seconds: 0, milliseconds: 0 }) : { hours, minutes: 0 } as Duration;\n } else if (this.value instanceof Date) {\n const value = this.value?.getTime();\n const clone = new Date(value);\n if (hours !== undefined) {\n clone.setHours(hours);\n }\n this.value = clone;\n } else {\n this.value = {\n hours: hours && hours < 0 ? 0 : hours,\n minutes: this.value.minutes\n };\n }\n this.changeDetectorRef.markForCheck();\n\n if (isEvent && this._autoFocus && this.minutes) {\n this.minutes.nativeElement.focus({\n preventScroll: true\n });\n this.minutes.nativeElement.select();\n }\n });\n\n this.onMinutesChange$.pipe(\n debounce(minutes => timer(typeof minutes === 'object' ? 0 : 10)),\n distinctUntilChanged(),\n map(event => {\n let minutes: number | undefined;\n if (typeof event === 'object') {\n const value = (event.target as HTMLInputElement).value;\n minutes = value !== undefined ? parseInt(value, 10) : undefined;\n } else {\n minutes = event;\n }\n return minutes && !isNaN(minutes) && minutes || 0;\n }),\n takeUntilDestroyed(this.destroyRef)\n ).subscribe(minutes => {\n if (!this.value) {\n this.value = this.dataType === 'date' ? set(new Date(), { hours: 0, minutes, seconds: 0, milliseconds: 0 }) : { hours: 0, minutes } as Duration;\n } else if (this.value instanceof Date) {\n const newValue = new Date(this.value.getTime());\n if (minutes < 0) {\n minutes += 60;\n } else if (minutes >= 60) {\n minutes -= 60;\n }\n newValue.setMinutes(minutes);\n\n if (this.mode !== 'fullTimeWithHoursDisabled' || (this.mode === 'fullTimeWithHoursDisabled' && isSameHour(this.value, newValue))) {\n this.value = newValue;\n }\n } else {\n this.value = {\n hours: this.value.hours,\n minutes: minutes < 0 || minutes >= 60 ? 0 : minutes\n };\n }\n this.changeDetectorRef.markForCheck();\n });\n }\n\n public onKeyDown($event: KeyboardEvent, mode: 'hours' | 'minutes'): void {\n // Get input element\n const inputElement = mode === 'hours' ? this.hours?.nativeElement : this.minutes?.nativeElement;\n if ($event.key?.toLowerCase() === 'd') {\n $event.stopPropagation();\n $event.preventDefault();\n this.value = new Date();\n } else if (inputElement) {\n if ($event.key?.toLowerCase() === 'a' && $event.ctrlKey) {\n inputElement.select();\n } else if ($event.key && !['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Backspace', 'Delete', 'Tab', 'Enter', 'Control', 'Shift'].includes($event.key)) {\n // Set regex for input format validation (differs if we are dealing with a date or a duration)\n let regex;\n if (mode === 'hours') {\n regex = this.dataType === 'date' ? /^(\\d|[01]\\d|2[0-3])$/ : /^(\\d+)$/;\n } else {\n regex = /^(\\d|[0-5]\\d)$/;\n }\n\n // Get the selection in input element\n const [selectionStart, selectionEnd] = [inputElement.selectionStart || 0, inputElement.selectionEnd || 0].sort((a, b) => a - b);\n const selectionDiff = selectionEnd - selectionStart;\n\n // Get the current value in input element and update it with the new touched key\n const inputValue = inputElement.value || '';\n const inputValueArr = Array.from(inputValue);\n inputValueArr.splice(selectionStart, selectionDiff, $event.key);\n const newInputValue = inputValueArr.join('');\n\n // Prevent event if the time is not valid\n if (!regex.test(newInputValue)) {\n $event.stopPropagation();\n $event.preventDefault();\n } else if (this._autoFocus && mode === 'hours' && ((this.dataType === 'date' && parseFloat(newInputValue) >= 3) || newInputValue.length === 2)) {\n this.onHoursChange$.next($event);\n }\n }\n }\n }\n\n public get hoursValue(): number | undefined {\n if (!this.value || (this.forceNullValue && this.mode === 'fullTimeWithMinutesDisabled' && !!this.control?.pristine)) {\n return undefined;\n }\n return this.value instanceof Date ? this.value.getHours() : this.value.hours;\n }\n\n public get minutesValue(): number | undefined {\n if (!this.value || (this.forceNullValue && this.mode === 'fullTimeWithHoursDisabled' && !!this.control?.pristine)) {\n return undefined;\n }\n return this.value instanceof Date ? this.value.getMinutes() : this.value.minutes;\n }\n\n public incrementValue(fieldType: FieldType): void {\n if (fieldType === 'hours') {\n this.onHoursChange$.next((this.hoursValue || 0) + 1);\n } else {\n this.onMinutesChange$.next((this.minutesValue || 0) + this._step);\n }\n }\n\n public decrementValue(fieldType: FieldType): void {\n if (fieldType === 'hours') {\n this.onHoursChange$.next((this.hoursValue || 0) - 1);\n } else {\n this.onMinutesChange$.next((this.minutesValue || 0) - this._step);\n }\n }\n\n public onClick(mode: 'hours' | 'minutes'): void {\n if (this._autoFocus) {\n if (mode === 'hours') {\n this.hours?.nativeElement.select();\n } else {\n this.minutes?.nativeElement.select();\n }\n }\n }\n\n // ************* ControlValueAccessor Implementation **************\n /** set accessor including call the onchange callback */\n public set value(v: NgxDateOrDuration | undefined) {\n if (v !== this._value) {\n this.writeValue(v);\n this.onChangeCallback(v);\n this.timeChange.emit(v);\n }\n }\n\n /** get accessor */\n public get value(): NgxDateOrDuration | undefined {\n return this._value;\n }\n\n /** From ControlValueAccessor interface */\n public writeValue(value: NgxDateOrDuration | undefined): void {\n if ((value ?? null) !== (this._value ?? null)) {\n if (value instanceof Date) {\n this._value = value ? new Date(value.getTime()) : set(new Date(), { hours: 0, minutes: 0, seconds: 0 });\n } else {\n this._value = value;\n }\n\n this.changeDetectorRef.markForCheck();\n }\n }\n\n /** From ControlValueAccessor interface */\n public registerOnChange(fn: (_a: unknown) => void): void {\n this.onChangeCallback = fn;\n }\n\n /** From ControlValueAccessor interface */\n public registerOnTouched(fn: () => void): void {\n this.onTouchedCallback = fn;\n }\n\n public setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n }\n // ************* End of ControlValueAccessor Implementation **************\n\n protected onChangeCallback = (_a: unknown): void => undefined;\n protected onTouchedCallback = (): void => undefined;\n}\n","<!-- Hours -->\n<mat-form-field\n [appearance]=\"appearance\"\n class=\"hours\"\n [class.disabled]=\"disabled || mode === 'fullTimeWithHoursDisabled'\"\n [style.display]=\"mode === 'minutesOnly' ? 'none' : 'block'\">\n <input\n #hours\n matInput\n type=\"text\"\n [ngModel]=\"hoursValue | number: '2.'\"\n (change)=\"onHoursChange$.next($event)\"\n (keydown)=\"onKeyDown($event, 'hours')\"\n [disabled]=\"disabled || mode === 'fullTimeWithHoursDisabled'\"\n [maxLength]=\"2\"\n autocomplete=\"off\"\n [placeholder]=\"defaultPlaceholderHours\"\n (click)=\"onClick('hours')\" />\n <ngx-numeric-stepper\n (increment)=\"incrementValue('hours')\"\n (decrement)=\"decrementValue('hours')\"></ngx-numeric-stepper>\n</mat-form-field>\n\n<!-- Separator -->\n<span class=\"time-separator\" [style.display]=\"mode === 'minutesOnly' || mode === 'hoursOnly' ? 'none' : 'block'\">\n :\n</span>\n\n<!-- Minutes -->\n<mat-form-field\n [appearance]=\"appearance\"\n class=\"minutes\"\n [class.disabled]=\"disabled || mode === 'fullTimeWithMinutesDisabled'\"\n [style.display]=\"mode === 'hoursOnly' ? 'none' : 'block'\">\n <input\n #minutes\n matInput\n type=\"text\"\n [ngModel]=\"minutesValue | number: '2.'\"\n (change)=\"onMinutesChange$.next($event)\"\n (keydown)=\"onKeyDown($event, 'minutes')\"\n [disabled]=\"disabled || mode === 'fullTimeWithMinutesDisabled'\"\n [maxLength]=\"2\"\n autocomplete=\"off\"\n [placeholder]=\"defaultPlaceholderMinutes\"\n (click)=\"onClick('minutes')\" />\n <ngx-numeric-stepper\n (increment)=\"incrementValue('minutes')\"\n (decrement)=\"decrementValue('minutes')\"></ngx-numeric-stepper>\n</mat-form-field>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hug-ngx-time-picker.mjs","sources":["../../../projects/time-picker/src/time-picker.component.ts","../../../projects/time-picker/src/time-picker.component.html","../../../projects/time-picker/src/hug-ngx-time-picker.ts"],"sourcesContent":["import { BooleanInput, coerceBooleanProperty, coerceNumberProperty, NumberInput } from '@angular/cdk/coercion';\nimport { DecimalPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, inject, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ControlValueAccessor, FormsModule, NgControl } from '@angular/forms';\nimport { MatFormFieldAppearance, MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInputModule } from '@angular/material/input';\nimport { NgxNumericStepperComponent } from '@hug/ngx-numeric-stepper';\nimport { set } from 'date-fns';\nimport { debounceTime, distinctUntilChanged, EMPTY, map, mergeWith, Subject, switchMap, tap, timer } from 'rxjs';\n\nexport type NgxTimePickerDisplayMode = 'fullTime' | 'fullTimeWithHoursDisabled' | 'fullTimeWithMinutesDisabled' | 'hoursOnly' | 'minutesOnly';\n\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'ngx-time-picker',\n styleUrls: ['./time-picker.component.scss'],\n templateUrl: './time-picker.component.html',\n encapsulation: ViewEncapsulation.None,\n standalone: true,\n imports: [\n DecimalPipe,\n FormsModule,\n MatFormFieldModule,\n MatInputModule,\n NgxNumericStepperComponent\n ]\n})\nexport class NgxTimePickerComponent implements ControlValueAccessor {\n @ViewChild('hours') public hours?: ElementRef<HTMLInputElement>;\n @ViewChild('minutes') public minutes?: ElementRef<HTMLInputElement>;\n\n @Output() public readonly timeChange = new EventEmitter<Date>();\n\n /** Display mode for the time-picker */\n @Input() public mode: NgxTimePickerDisplayMode = 'fullTime';\n\n /**\n * Force the hour or minute to be null (only if the other field is disabled)\n *\n * For instance, if set to true and the hours are disabled, the minutes input value will be null\n * This is useful to force the user to provide a value\n */\n @Input() public forceNullValue = false;\n\n @Input() public appearance: MatFormFieldAppearance = 'outline';\n\n @Input()\n public set autoFocus(value: BooleanInput) {\n this._autoFocus = coerceBooleanProperty(value);\n }\n\n @Input() public defaultPlaceholderHours = '_ _';\n @Input() public defaultPlaceholderMinutes = '_ _';\n\n @Input()\n public set time(value: Date | undefined) {\n this.writeValue(value);\n }\n\n public get time(): Date | undefined {\n return this.value;\n }\n\n /** Step of the arrows */\n @Input()\n public set step(value: NumberInput) {\n this._step = coerceNumberProperty(value);\n this.changeDetectorRef.markForCheck();\n }\n\n /** To get the step of the minutes arrows */\n public get step(): NumberInput {\n return this._step;\n }\n\n /** Disabled property setter. Can be string or empty so you can use it like : <time-picker disabled></time-picker> */\n @Input()\n public set disabled(value: BooleanInput) {\n this._disabled = coerceBooleanProperty(value);\n this.changeDetectorRef.markForCheck();\n }\n\n /** To get disabled attribute. */\n public get disabled(): BooleanInput {\n return this._disabled;\n }\n\n public readonly hoursChange$ = new Subject<Event | number>();\n public readonly minutesChange$ = new Subject<Event | number>();\n public readonly hoursKeyDown$ = new Subject<KeyboardEvent>();\n\n protected changeDetectorRef = inject(ChangeDetectorRef);\n protected control = inject(NgControl, { optional: true, self: true });\n protected _step = 1;\n\n private _disabled = false;\n private _value?: Date;\n private _autoFocus = true;\n\n public constructor() {\n if (this.control) {\n this.control.valueAccessor = this;\n }\n\n const hoursChange$ = this.hoursChange$.pipe(\n distinctUntilChanged(),\n map(hours => {\n if (typeof hours === 'object') {\n const value = (hours.target as HTMLInputElement).value;\n return [value !== undefined ? parseInt(value, 10) : undefined, true] as const;\n }\n return [!isNaN(hours) ? hours : 0, false] as const;\n }),\n tap(([hours, _isEvent]) => {\n const newValue = this.value ? new Date(this.value.getTime()) : new Date();\n\n if (hours !== undefined) {\n newValue.setHours(hours);\n }\n\n if (this.mode === 'fullTime' || this.mode === 'fullTimeWithMinutesDisabled' || this.mode === 'hoursOnly') {\n this.value = newValue;\n }\n\n this.changeDetectorRef.markForCheck();\n })\n );\n\n const minutesChange$ = this.minutesChange$.pipe(\n distinctUntilChanged(),\n map(event => {\n let minutes: number | undefined;\n if (typeof event === 'object') {\n const value = (event.target as HTMLInputElement).value;\n minutes = value !== undefined ? parseInt(value, 10) : undefined;\n } else {\n minutes = event;\n }\n\n return minutes && !isNaN(minutes) && minutes || 0;\n }),\n tap(minutes => {\n const newValue = this.value ? new Date(this.value.getTime()) : new Date();\n\n if (minutes < 0) {\n minutes += 60;\n } else if (minutes >= 60) {\n minutes -= 60;\n }\n newValue.setMinutes(minutes);\n\n if (this.mode === 'fullTime' || this.mode === 'fullTimeWithHoursDisabled' || this.mode === 'minutesOnly') {\n this.value = newValue;\n }\n\n this.changeDetectorRef.markForCheck();\n })\n );\n\n const setFocusToNextInput$ = this.hoursKeyDown$.pipe(\n debounceTime(200),\n switchMap(event => {\n const inputElement = this.hours?.nativeElement;\n if (!inputElement) {\n return EMPTY;\n }\n\n if (event.key && !event.ctrlKey && !event.shiftKey && !event.altKey && !['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Backspace', 'Delete', 'Tab', 'Enter', 'Control', 'Shift'].includes(event.key)) {\n const regex = /^(\\d|[01]\\d|2[0-3])$/;\n const [selectionStart, selectionEnd] = [inputElement.selectionStart || 0, inputElement.selectionEnd || 0].sort((a, b) => a - b);\n const inputValue = inputElement.value || '';\n if (regex.test(inputValue) && this._autoFocus && inputValue.length === 2 && this.minutes?.nativeElement && inputElement === document.activeElement && selectionStart === 2 && selectionEnd === 2) {\n this.minutes.nativeElement.focus();\n return timer(0).pipe(\n tap(() => {\n this.minutes?.nativeElement.select();\n })\n );\n }\n }\n\n return EMPTY;\n })\n );\n\n hoursChange$.pipe(\n mergeWith(minutesChange$, setFocusToNextInput$),\n takeUntilDestroyed()\n ).subscribe();\n }\n\n // ************* ControlValueAccessor Implementation **************\n /** set accessor including call the onchange callback */\n public set value(v: Date | undefined) {\n if (v !== this._value) {\n this.writeValue(v);\n this.onChangeCallback(v);\n this.timeChange.emit(v);\n }\n }\n\n /** get accessor */\n public get value(): Date | undefined {\n return this._value;\n }\n\n /** From ControlValueAccessor interface */\n public writeValue(value: Date | undefined): void {\n if ((value ?? null) !== (this._value ?? null)) {\n if (value instanceof Date) {\n this._value = value ? new Date(value.getTime()) : set(new Date(), { hours: 0, minutes: 0, seconds: 0 });\n } else {\n this._value = value;\n }\n\n this.changeDetectorRef.markForCheck();\n }\n }\n\n /** From ControlValueAccessor interface */\n public registerOnChange(fn: (_a: unknown) => void): void {\n this.onChangeCallback = fn;\n }\n\n /** From ControlValueAccessor interface */\n public registerOnTouched(fn: () => void): void {\n this.onTouchedCallback = fn;\n }\n\n public setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n }\n // ************* End of ControlValueAccessor Implementation **************\n\n protected get hoursValue(): number | undefined {\n if (!this.value || (this.forceNullValue && this.mode === 'fullTimeWithMinutesDisabled' && !!this.control?.pristine)) {\n return undefined;\n }\n return this.value.getHours();\n }\n\n protected get minutesValue(): number | undefined {\n if (!this.value || (this.forceNullValue && this.mode === 'fullTimeWithHoursDisabled' && !!this.control?.pristine)) {\n return undefined;\n }\n return this.value.getMinutes();\n }\n\n protected onChangeCallback = (_a: unknown): void => undefined;\n protected onTouchedCallback = (): void => undefined;\n}\n","<!-- Hours -->\n<mat-form-field\n [appearance]=\"appearance\"\n class=\"hours\"\n [class.disabled]=\"disabled || mode === 'fullTimeWithHoursDisabled'\"\n [style.display]=\"mode === 'minutesOnly' ? 'none' : 'block'\">\n <input\n aria-label=\"hours\"\n #hours\n matInput\n [attr.hours]=\"hoursValue\"\n type=\"text\"\n [ngModel]=\"hoursValue | number: '2.'\"\n (ngModelChange)=\"hoursChange$.next($event)\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n (keydown)=\"hoursKeyDown$.next($event)\"\n [disabled]=\"disabled || mode === 'fullTimeWithHoursDisabled'\"\n [maxLength]=\"2\"\n autocomplete=\"off\"\n [placeholder]=\"defaultPlaceholderHours\"\n (click)=\"hours.select()\" />\n <ngx-numeric-stepper\n (increment)=\"hoursChange$.next((hoursValue || 0) + 1)\"\n (decrement)=\"hoursChange$.next((hoursValue || 0) - 1)\"></ngx-numeric-stepper>\n</mat-form-field>\n\n<!-- Separator -->\n<span class=\"time-separator\" [style.display]=\"mode === 'minutesOnly' || mode === 'hoursOnly' ? 'none' : 'block'\">\n :\n</span>\n\n<!-- Minutes -->\n<mat-form-field\n [appearance]=\"appearance\"\n class=\"minutes\"\n [class.disabled]=\"disabled || mode === 'fullTimeWithMinutesDisabled'\"\n [style.display]=\"mode === 'hoursOnly' ? 'none' : 'block'\">\n <input\n aria-label=\"minutes\"\n #minutes\n matInput\n [attr.minutes]=\"minutesValue\"\n type=\"text\"\n [ngModel]=\"minutesValue | number: '2.'\"\n (ngModelChange)=\"minutesChange$.next($event)\"\n [ngModelOptions]=\"{ updateOn: 'blur' }\"\n [disabled]=\"disabled || mode === 'fullTimeWithMinutesDisabled'\"\n [maxLength]=\"2\"\n autocomplete=\"off\"\n [placeholder]=\"defaultPlaceholderMinutes\"\n (click)=\"minutes.select()\" />\n <ngx-numeric-stepper\n (increment)=\"minutesChange$.next((minutesValue || 0) + _step)\"\n (decrement)=\"minutesChange$.next((minutesValue || 0) - _step)\"></ngx-numeric-stepper>\n</mat-form-field>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hug/ngx-time-picker",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "HUG Angular - time picker component",
|
|
5
5
|
"homepage": "https://github.com/dsi-hug/ngx-components",
|
|
6
6
|
"license": "GPL-3.0-only",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@angular/material": ">=19 <20",
|
|
29
29
|
"rxjs": ">= 7.4.0",
|
|
30
30
|
"date-fns": "^2.30.0",
|
|
31
|
-
"@hug/ngx-numeric-stepper": "^3.0.
|
|
31
|
+
"@hug/ngx-numeric-stepper": "^3.0.2"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"tslib": "^2.7.0"
|
|
@@ -45,6 +45,10 @@
|
|
|
45
45
|
".": {
|
|
46
46
|
"types": "./index.d.ts",
|
|
47
47
|
"default": "./fesm2022/hug-ngx-time-picker.mjs"
|
|
48
|
+
},
|
|
49
|
+
"./testing": {
|
|
50
|
+
"types": "./testing/index.d.ts",
|
|
51
|
+
"default": "./fesm2022/hug-ngx-time-picker-testing.mjs"
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
54
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { HarnessPredicate, TestKey } from '@angular/cdk/testing';
|
|
2
|
+
import { MatFormFieldControlHarness } from '@angular/material/form-field/testing/control';
|
|
3
|
+
import { MatInputHarness } from '@angular/material/input/testing';
|
|
4
|
+
import { NgxTimePickerHarnessFilters } from './time-picker-harness-filters';
|
|
5
|
+
/** Harness for interacting with a ngx time picker in tests. */
|
|
6
|
+
export declare class NgxTimePickerHarness extends MatFormFieldControlHarness {
|
|
7
|
+
static hostSelector: string;
|
|
8
|
+
static with(options?: NgxTimePickerHarnessFilters): HarnessPredicate<NgxTimePickerHarness>;
|
|
9
|
+
getHoursInput(): Promise<MatInputHarness>;
|
|
10
|
+
getMinutesInput(): Promise<MatInputHarness>;
|
|
11
|
+
setValue(value: string): Promise<void>;
|
|
12
|
+
getValue(): Promise<string>;
|
|
13
|
+
getHoursValue(): Promise<string>;
|
|
14
|
+
getMinutesValue(): Promise<string>;
|
|
15
|
+
sendKeysToHoursInput(...keys: readonly TestKey[]): Promise<void>;
|
|
16
|
+
sendKeysToMinutesInput(...keys: readonly TestKey[]): Promise<void>;
|
|
17
|
+
}
|
|
@@ -5,17 +5,12 @@ import { MatFormFieldAppearance } from '@angular/material/form-field';
|
|
|
5
5
|
import { Subject } from 'rxjs';
|
|
6
6
|
import * as i0 from "@angular/core";
|
|
7
7
|
export type NgxTimePickerDisplayMode = 'fullTime' | 'fullTimeWithHoursDisabled' | 'fullTimeWithMinutesDisabled' | 'hoursOnly' | 'minutesOnly';
|
|
8
|
-
export type NgxDateOrDuration = Date | Duration;
|
|
9
|
-
type DataType = 'date' | 'duration';
|
|
10
|
-
type FieldType = 'hours' | 'minutes';
|
|
11
8
|
export declare class NgxTimePickerComponent implements ControlValueAccessor {
|
|
12
9
|
hours?: ElementRef<HTMLInputElement>;
|
|
13
10
|
minutes?: ElementRef<HTMLInputElement>;
|
|
14
|
-
readonly timeChange: EventEmitter<
|
|
11
|
+
readonly timeChange: EventEmitter<Date>;
|
|
15
12
|
/** Display mode for the time-picker */
|
|
16
13
|
mode: NgxTimePickerDisplayMode;
|
|
17
|
-
/** Data type to manage (Date or Duration) */
|
|
18
|
-
dataType: DataType;
|
|
19
14
|
/**
|
|
20
15
|
* Force the hour or minute to be null (only if the other field is disabled)
|
|
21
16
|
*
|
|
@@ -27,8 +22,8 @@ export declare class NgxTimePickerComponent implements ControlValueAccessor {
|
|
|
27
22
|
set autoFocus(value: BooleanInput);
|
|
28
23
|
defaultPlaceholderHours: string;
|
|
29
24
|
defaultPlaceholderMinutes: string;
|
|
30
|
-
set time(value:
|
|
31
|
-
get time():
|
|
25
|
+
set time(value: Date | undefined);
|
|
26
|
+
get time(): Date | undefined;
|
|
32
27
|
/** Step of the arrows */
|
|
33
28
|
set step(value: NumberInput);
|
|
34
29
|
/** To get the step of the minutes arrows */
|
|
@@ -37,36 +32,31 @@ export declare class NgxTimePickerComponent implements ControlValueAccessor {
|
|
|
37
32
|
set disabled(value: BooleanInput);
|
|
38
33
|
/** To get disabled attribute. */
|
|
39
34
|
get disabled(): BooleanInput;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
readonly hoursChange$: Subject<number | Event>;
|
|
36
|
+
readonly minutesChange$: Subject<number | Event>;
|
|
37
|
+
readonly hoursKeyDown$: Subject<KeyboardEvent>;
|
|
43
38
|
protected changeDetectorRef: ChangeDetectorRef;
|
|
44
39
|
protected control: NgControl | null;
|
|
45
|
-
|
|
40
|
+
protected _step: number;
|
|
46
41
|
private _disabled;
|
|
47
42
|
private _value?;
|
|
48
43
|
private _autoFocus;
|
|
49
44
|
constructor();
|
|
50
|
-
onKeyDown($event: KeyboardEvent, mode: 'hours' | 'minutes'): void;
|
|
51
|
-
get hoursValue(): number | undefined;
|
|
52
|
-
get minutesValue(): number | undefined;
|
|
53
|
-
incrementValue(fieldType: FieldType): void;
|
|
54
|
-
decrementValue(fieldType: FieldType): void;
|
|
55
|
-
onClick(mode: 'hours' | 'minutes'): void;
|
|
56
45
|
/** set accessor including call the onchange callback */
|
|
57
|
-
set value(v:
|
|
46
|
+
set value(v: Date | undefined);
|
|
58
47
|
/** get accessor */
|
|
59
|
-
get value():
|
|
48
|
+
get value(): Date | undefined;
|
|
60
49
|
/** From ControlValueAccessor interface */
|
|
61
|
-
writeValue(value:
|
|
50
|
+
writeValue(value: Date | undefined): void;
|
|
62
51
|
/** From ControlValueAccessor interface */
|
|
63
52
|
registerOnChange(fn: (_a: unknown) => void): void;
|
|
64
53
|
/** From ControlValueAccessor interface */
|
|
65
54
|
registerOnTouched(fn: () => void): void;
|
|
66
55
|
setDisabledState(isDisabled: boolean): void;
|
|
56
|
+
protected get hoursValue(): number | undefined;
|
|
57
|
+
protected get minutesValue(): number | undefined;
|
|
67
58
|
protected onChangeCallback: (_a: unknown) => void;
|
|
68
59
|
protected onTouchedCallback: () => void;
|
|
69
60
|
static ɵfac: i0.ɵɵFactoryDeclaration<NgxTimePickerComponent, never>;
|
|
70
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<NgxTimePickerComponent, "ngx-time-picker", never, { "mode": { "alias": "mode"; "required": false; }; "
|
|
61
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<NgxTimePickerComponent, "ngx-time-picker", never, { "mode": { "alias": "mode"; "required": false; }; "forceNullValue": { "alias": "forceNullValue"; "required": false; }; "appearance": { "alias": "appearance"; "required": false; }; "autoFocus": { "alias": "autoFocus"; "required": false; }; "defaultPlaceholderHours": { "alias": "defaultPlaceholderHours"; "required": false; }; "defaultPlaceholderMinutes": { "alias": "defaultPlaceholderMinutes"; "required": false; }; "time": { "alias": "time"; "required": false; }; "step": { "alias": "step"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, { "timeChange": "timeChange"; }, never, never, true, never>;
|
|
71
62
|
}
|
|
72
|
-
export {};
|