@nuralyui/timepicker 0.1.1

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.
Files changed (43) hide show
  1. package/controllers/formatting.controller.d.ts +93 -0
  2. package/controllers/formatting.controller.d.ts.map +1 -0
  3. package/controllers/formatting.controller.js +195 -0
  4. package/controllers/formatting.controller.js.map +1 -0
  5. package/controllers/index.d.ts +9 -0
  6. package/controllers/index.d.ts.map +1 -0
  7. package/controllers/index.js +9 -0
  8. package/controllers/index.js.map +1 -0
  9. package/controllers/selection.controller.d.ts +72 -0
  10. package/controllers/selection.controller.d.ts.map +1 -0
  11. package/controllers/selection.controller.js +175 -0
  12. package/controllers/selection.controller.js.map +1 -0
  13. package/controllers/validation.controller.d.ts +88 -0
  14. package/controllers/validation.controller.d.ts.map +1 -0
  15. package/controllers/validation.controller.js +200 -0
  16. package/controllers/validation.controller.js.map +1 -0
  17. package/index.d.ts +12 -0
  18. package/index.js +12 -0
  19. package/interfaces/timepicker.interface.d.ts +103 -0
  20. package/interfaces/timepicker.interface.d.ts.map +1 -0
  21. package/interfaces/timepicker.interface.js +7 -0
  22. package/interfaces/timepicker.interface.js.map +1 -0
  23. package/package.json +63 -0
  24. package/test/timepicker.test.d.ts +7 -0
  25. package/test/timepicker.test.d.ts.map +1 -0
  26. package/test/timepicker.test.js +218 -0
  27. package/test/timepicker.test.js.map +1 -0
  28. package/timepicker.component.backup.d.ts +165 -0
  29. package/timepicker.component.backup.js +890 -0
  30. package/timepicker.component.clean.d.ts +95 -0
  31. package/timepicker.component.clean.js +471 -0
  32. package/timepicker.component.d.ts +117 -0
  33. package/timepicker.component.js +747 -0
  34. package/timepicker.constants.d.ts +85 -0
  35. package/timepicker.constants.js +85 -0
  36. package/timepicker.style.d.ts +7 -0
  37. package/timepicker.style.js +646 -0
  38. package/timepicker.types.d.ts +161 -0
  39. package/timepicker.types.js +125 -0
  40. package/utils/time.utils.d.ts +87 -0
  41. package/utils/time.utils.d.ts.map +1 -0
  42. package/utils/time.utils.js +235 -0
  43. package/utils/time.utils.js.map +1 -0
@@ -0,0 +1,161 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Time format types - supports 12-hour and 24-hour formats
8
+ */
9
+ export declare enum TimeFormat {
10
+ TwentyFourHour = "24h",
11
+ TwelveHour = "12h"
12
+ }
13
+ /**
14
+ * Time picker display modes
15
+ */
16
+ export declare enum TimePickerMode {
17
+ Hours = "hours",
18
+ Minutes = "minutes",
19
+ Seconds = "seconds"
20
+ }
21
+ /**
22
+ * Time picker sizes
23
+ */
24
+ export declare enum TimePickerSize {
25
+ Small = "small",
26
+ Medium = "medium",
27
+ Large = "large"
28
+ }
29
+ /**
30
+ * Time picker variants
31
+ */
32
+ export declare enum TimePickerVariant {
33
+ Default = "default",
34
+ Outlined = "outlined",
35
+ Filled = "filled"
36
+ }
37
+ /**
38
+ * Time picker states for validation
39
+ */
40
+ export declare enum TimePickerState {
41
+ Default = "default",
42
+ Error = "error",
43
+ Warning = "warning",
44
+ Success = "success"
45
+ }
46
+ /**
47
+ * Time picker placement options for dropdown
48
+ */
49
+ export declare enum TimePickerPlacement {
50
+ Bottom = "bottom",
51
+ Top = "top",
52
+ Auto = "auto"
53
+ }
54
+ /**
55
+ * Time selection step increments
56
+ */
57
+ export declare enum TimeStep {
58
+ One = 1,
59
+ Five = 5,
60
+ Ten = 10,
61
+ Fifteen = 15,
62
+ Thirty = 30
63
+ }
64
+ /**
65
+ * Time period for 12-hour format
66
+ */
67
+ export declare enum TimePeriod {
68
+ AM = "AM",
69
+ PM = "PM"
70
+ }
71
+ /**
72
+ * Time structure interface
73
+ */
74
+ export interface TimeValue {
75
+ hours: number;
76
+ minutes: number;
77
+ seconds: number;
78
+ period?: TimePeriod;
79
+ }
80
+ /**
81
+ * Time picker option for dropdowns
82
+ */
83
+ export interface TimePickerOption {
84
+ value: string;
85
+ label: string;
86
+ disabled?: boolean;
87
+ }
88
+ /**
89
+ * Time validation constraints
90
+ */
91
+ export interface TimeConstraints {
92
+ minTime?: string;
93
+ maxTime?: string;
94
+ disabledTimes?: string[];
95
+ enabledTimes?: string[];
96
+ }
97
+ /**
98
+ * Time picker configuration
99
+ */
100
+ export interface TimePickerConfig {
101
+ format: TimeFormat;
102
+ showSeconds: boolean;
103
+ step: {
104
+ hours: TimeStep;
105
+ minutes: TimeStep;
106
+ seconds: TimeStep;
107
+ };
108
+ use12HourClock: boolean;
109
+ minuteInterval: number;
110
+ secondInterval: number;
111
+ }
112
+ /**
113
+ * Time picker event details
114
+ */
115
+ export interface TimeChangeEventDetail {
116
+ value: string;
117
+ timeValue: TimeValue;
118
+ formattedValue: string;
119
+ }
120
+ /**
121
+ * Default time formats
122
+ */
123
+ export declare const DEFAULT_TIME_FORMATS: {
124
+ readonly "24h": "HH:mm";
125
+ readonly "12h": "hh:mm A";
126
+ };
127
+ /**
128
+ * Default time format with seconds
129
+ */
130
+ export declare const DEFAULT_TIME_FORMATS_WITH_SECONDS: {
131
+ readonly "24h": "HH:mm:ss";
132
+ readonly "12h": "hh:mm:ss A";
133
+ };
134
+ /**
135
+ * Time picker constants
136
+ */
137
+ export declare const TIME_PICKER_CONSTANTS: {
138
+ readonly HOURS_24: 24;
139
+ readonly HOURS_12: 12;
140
+ readonly MINUTES: 60;
141
+ readonly SECONDS: 60;
142
+ readonly DEFAULT_STEP: 1;
143
+ readonly DEFAULT_MINUTE_INTERVAL: 1;
144
+ readonly DEFAULT_SECOND_INTERVAL: 1;
145
+ };
146
+ /**
147
+ * Time picker events
148
+ */
149
+ export declare const TIME_PICKER_EVENTS: {
150
+ readonly TIME_CHANGE: "nr-time-change";
151
+ readonly FOCUS: "nr-focus";
152
+ readonly BLUR: "nr-blur";
153
+ readonly CLOCK_OPEN: "nr-clock-open";
154
+ readonly CLOCK_CLOSE: "nr-clock-close";
155
+ readonly VALIDATION: "nr-validation";
156
+ };
157
+ /**
158
+ * Empty time value
159
+ */
160
+ export declare const EMPTY_TIME_VALUE: TimeValue;
161
+ //# sourceMappingURL=timepicker.types.d.ts.map
@@ -0,0 +1,125 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Time format types - supports 12-hour and 24-hour formats
8
+ */
9
+ export var TimeFormat;
10
+ (function (TimeFormat) {
11
+ TimeFormat["TwentyFourHour"] = "24h";
12
+ TimeFormat["TwelveHour"] = "12h";
13
+ })(TimeFormat || (TimeFormat = {}));
14
+ /**
15
+ * Time picker display modes
16
+ */
17
+ export var TimePickerMode;
18
+ (function (TimePickerMode) {
19
+ TimePickerMode["Hours"] = "hours";
20
+ TimePickerMode["Minutes"] = "minutes";
21
+ TimePickerMode["Seconds"] = "seconds";
22
+ })(TimePickerMode || (TimePickerMode = {}));
23
+ /**
24
+ * Time picker sizes
25
+ */
26
+ export var TimePickerSize;
27
+ (function (TimePickerSize) {
28
+ TimePickerSize["Small"] = "small";
29
+ TimePickerSize["Medium"] = "medium";
30
+ TimePickerSize["Large"] = "large";
31
+ })(TimePickerSize || (TimePickerSize = {}));
32
+ /**
33
+ * Time picker variants
34
+ */
35
+ export var TimePickerVariant;
36
+ (function (TimePickerVariant) {
37
+ TimePickerVariant["Default"] = "default";
38
+ TimePickerVariant["Outlined"] = "outlined";
39
+ TimePickerVariant["Filled"] = "filled";
40
+ })(TimePickerVariant || (TimePickerVariant = {}));
41
+ /**
42
+ * Time picker states for validation
43
+ */
44
+ export var TimePickerState;
45
+ (function (TimePickerState) {
46
+ TimePickerState["Default"] = "default";
47
+ TimePickerState["Error"] = "error";
48
+ TimePickerState["Warning"] = "warning";
49
+ TimePickerState["Success"] = "success";
50
+ })(TimePickerState || (TimePickerState = {}));
51
+ /**
52
+ * Time picker placement options for dropdown
53
+ */
54
+ export var TimePickerPlacement;
55
+ (function (TimePickerPlacement) {
56
+ TimePickerPlacement["Bottom"] = "bottom";
57
+ TimePickerPlacement["Top"] = "top";
58
+ TimePickerPlacement["Auto"] = "auto";
59
+ })(TimePickerPlacement || (TimePickerPlacement = {}));
60
+ /**
61
+ * Time selection step increments
62
+ */
63
+ export var TimeStep;
64
+ (function (TimeStep) {
65
+ TimeStep[TimeStep["One"] = 1] = "One";
66
+ TimeStep[TimeStep["Five"] = 5] = "Five";
67
+ TimeStep[TimeStep["Ten"] = 10] = "Ten";
68
+ TimeStep[TimeStep["Fifteen"] = 15] = "Fifteen";
69
+ TimeStep[TimeStep["Thirty"] = 30] = "Thirty";
70
+ })(TimeStep || (TimeStep = {}));
71
+ /**
72
+ * Time period for 12-hour format
73
+ */
74
+ export var TimePeriod;
75
+ (function (TimePeriod) {
76
+ TimePeriod["AM"] = "AM";
77
+ TimePeriod["PM"] = "PM";
78
+ })(TimePeriod || (TimePeriod = {}));
79
+ /**
80
+ * Default time formats
81
+ */
82
+ export const DEFAULT_TIME_FORMATS = {
83
+ [TimeFormat.TwentyFourHour]: 'HH:mm',
84
+ [TimeFormat.TwelveHour]: 'hh:mm A',
85
+ };
86
+ /**
87
+ * Default time format with seconds
88
+ */
89
+ export const DEFAULT_TIME_FORMATS_WITH_SECONDS = {
90
+ [TimeFormat.TwentyFourHour]: 'HH:mm:ss',
91
+ [TimeFormat.TwelveHour]: 'hh:mm:ss A',
92
+ };
93
+ /**
94
+ * Time picker constants
95
+ */
96
+ export const TIME_PICKER_CONSTANTS = {
97
+ HOURS_24: 24,
98
+ HOURS_12: 12,
99
+ MINUTES: 60,
100
+ SECONDS: 60,
101
+ DEFAULT_STEP: 1,
102
+ DEFAULT_MINUTE_INTERVAL: 1,
103
+ DEFAULT_SECOND_INTERVAL: 1,
104
+ };
105
+ /**
106
+ * Time picker events
107
+ */
108
+ export const TIME_PICKER_EVENTS = {
109
+ TIME_CHANGE: 'nr-time-change',
110
+ FOCUS: 'nr-focus',
111
+ BLUR: 'nr-blur',
112
+ CLOCK_OPEN: 'nr-clock-open',
113
+ CLOCK_CLOSE: 'nr-clock-close',
114
+ VALIDATION: 'nr-validation',
115
+ };
116
+ /**
117
+ * Empty time value
118
+ */
119
+ export const EMPTY_TIME_VALUE = {
120
+ hours: 0,
121
+ minutes: 0,
122
+ seconds: 0,
123
+ period: TimePeriod.AM,
124
+ };
125
+ //# sourceMappingURL=timepicker.types.js.map
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { TimeValue, TimePeriod, TimeFormat } from '../timepicker.types.js';
7
+ /**
8
+ * Time utility functions for time picker component
9
+ */
10
+ export declare class TimeUtils {
11
+ /**
12
+ * Create a new TimeValue object
13
+ */
14
+ static createTimeValue(hours: number, minutes: number, seconds?: number, period?: TimePeriod): TimeValue;
15
+ /**
16
+ * Parse time string to TimeValue
17
+ */
18
+ static parseTimeString(timeString: string, format?: TimeFormat): TimeValue | null;
19
+ /**
20
+ * Parse 24-hour format time string
21
+ */
22
+ private static parse24HourTime;
23
+ /**
24
+ * Parse 12-hour format time string
25
+ */
26
+ private static parse12HourTime;
27
+ /**
28
+ * Format TimeValue to string
29
+ */
30
+ static formatTimeValue(time: TimeValue, format?: TimeFormat, showSeconds?: boolean): string;
31
+ /**
32
+ * Format time in 24-hour format
33
+ */
34
+ private static format24HourTime;
35
+ /**
36
+ * Format time in 12-hour format
37
+ */
38
+ private static format12HourTime;
39
+ /**
40
+ * Get current time as TimeValue
41
+ */
42
+ static getCurrentTime(): TimeValue;
43
+ /**
44
+ * Compare two TimeValue objects
45
+ */
46
+ static compareTime(time1: TimeValue, time2: TimeValue): number;
47
+ /**
48
+ * Check if two TimeValue objects are equal
49
+ */
50
+ static isTimeEqual(time1: TimeValue, time2: TimeValue): boolean;
51
+ /**
52
+ * Validate 24-hour time components
53
+ */
54
+ private static isValidTime24;
55
+ /**
56
+ * Validate 12-hour time components
57
+ */
58
+ private static isValidTime12;
59
+ /**
60
+ * Add time to a TimeValue
61
+ */
62
+ static addTime(time: TimeValue, hoursToAdd: number, minutesToAdd: number, secondsToAdd?: number): TimeValue;
63
+ /**
64
+ * Generate time options for dropdowns
65
+ */
66
+ static generateTimeOptions(interval?: number, format?: TimeFormat, showSeconds?: boolean): Array<{
67
+ value: string;
68
+ label: string;
69
+ }>;
70
+ /**
71
+ * Round time to nearest interval
72
+ */
73
+ static roundToInterval(time: TimeValue, intervalMinutes: number): TimeValue;
74
+ /**
75
+ * Check if time is within range
76
+ */
77
+ static isTimeInRange(time: TimeValue, minTime: TimeValue | null, maxTime: TimeValue | null): boolean;
78
+ /**
79
+ * Convert Date object to TimeValue
80
+ */
81
+ static dateToTimeValue(date: Date): TimeValue;
82
+ /**
83
+ * Convert TimeValue to Date object (using current date)
84
+ */
85
+ static timeValueToDate(time: TimeValue, baseDate?: Date): Date;
86
+ }
87
+ //# sourceMappingURL=time.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.utils.d.ts","sourceRoot":"","sources":["../../../../src/components/timepicker/utils/time.utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAG3E;;GAEG;AACH,qBAAa,SAAS;IACpB;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAU,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS;IAS3G;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,GAAE,UAAsC,GAAG,SAAS,GAAG,IAAI;IAc5G;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IAkB9B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IA0B9B;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,GAAE,UAAsC,EAAE,WAAW,GAAE,OAAe,GAAG,MAAM;IAY7H;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAY/B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAsB/B;;OAEG;IACH,MAAM,CAAC,cAAc,IAAI,SAAS;IASlC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM;IAM9D;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO;IAI/D;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAW5B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAW5B;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAE,MAAU,GAAG,SAAS;IAc9G;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,QAAQ,GAAE,MAAW,EAAE,MAAM,GAAE,UAAsC,EAAE,WAAW,GAAE,OAAe,GAAG,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC;IAiBtK;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,GAAG,SAAS;IAU3E;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO;IAYpG;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS;IAQ7C;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI;CAK/D"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { TimePeriod, TimeFormat } from '../timepicker.types.js';
7
+ import { TIME_BOUNDARIES } from '../timepicker.constants.js';
8
+ /**
9
+ * Time utility functions for time picker component
10
+ */
11
+ export class TimeUtils {
12
+ /**
13
+ * Create a new TimeValue object
14
+ */
15
+ static createTimeValue(hours, minutes, seconds = 0, period) {
16
+ return {
17
+ hours: Math.max(0, Math.min(hours, 23)),
18
+ minutes: Math.max(0, Math.min(minutes, 59)),
19
+ seconds: Math.max(0, Math.min(seconds, 59)),
20
+ period,
21
+ };
22
+ }
23
+ /**
24
+ * Parse time string to TimeValue
25
+ */
26
+ static parseTimeString(timeString, format = TimeFormat.TwentyFourHour) {
27
+ if (!(timeString === null || timeString === void 0 ? void 0 : timeString.trim())) {
28
+ return null;
29
+ }
30
+ const cleanTime = timeString.trim().toUpperCase();
31
+ if (format === TimeFormat.TwelveHour) {
32
+ return this.parse12HourTime(cleanTime);
33
+ }
34
+ else {
35
+ return this.parse24HourTime(cleanTime);
36
+ }
37
+ }
38
+ /**
39
+ * Parse 24-hour format time string
40
+ */
41
+ static parse24HourTime(timeString) {
42
+ const match = timeString.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/);
43
+ if (!match) {
44
+ return null;
45
+ }
46
+ const hours = parseInt(match[1], 10);
47
+ const minutes = parseInt(match[2], 10);
48
+ const seconds = match[3] ? parseInt(match[3], 10) : 0;
49
+ if (!this.isValidTime24(hours, minutes, seconds)) {
50
+ return null;
51
+ }
52
+ return this.createTimeValue(hours, minutes, seconds);
53
+ }
54
+ /**
55
+ * Parse 12-hour format time string
56
+ */
57
+ static parse12HourTime(timeString) {
58
+ const match = timeString.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?\s?(AM|PM)$/);
59
+ if (!match) {
60
+ return null;
61
+ }
62
+ let hours = parseInt(match[1], 10);
63
+ const minutes = parseInt(match[2], 10);
64
+ const seconds = match[3] ? parseInt(match[3], 10) : 0;
65
+ const period = match[4];
66
+ if (!this.isValidTime12(hours, minutes, seconds)) {
67
+ return null;
68
+ }
69
+ // Convert to 24-hour format for internal storage
70
+ if (period === TimePeriod.PM && hours !== 12) {
71
+ hours += 12;
72
+ }
73
+ else if (period === TimePeriod.AM && hours === 12) {
74
+ hours = 0;
75
+ }
76
+ return this.createTimeValue(hours, minutes, seconds, period);
77
+ }
78
+ /**
79
+ * Format TimeValue to string
80
+ */
81
+ static formatTimeValue(time, format = TimeFormat.TwentyFourHour, showSeconds = false) {
82
+ if (!time) {
83
+ return '';
84
+ }
85
+ if (format === TimeFormat.TwelveHour) {
86
+ return this.format12HourTime(time, showSeconds);
87
+ }
88
+ else {
89
+ return this.format24HourTime(time, showSeconds);
90
+ }
91
+ }
92
+ /**
93
+ * Format time in 24-hour format
94
+ */
95
+ static format24HourTime(time, showSeconds) {
96
+ const hours = time.hours.toString().padStart(2, '0');
97
+ const minutes = time.minutes.toString().padStart(2, '0');
98
+ if (showSeconds) {
99
+ const seconds = time.seconds.toString().padStart(2, '0');
100
+ return `${hours}:${minutes}:${seconds}`;
101
+ }
102
+ return `${hours}:${minutes}`;
103
+ }
104
+ /**
105
+ * Format time in 12-hour format
106
+ */
107
+ static format12HourTime(time, showSeconds) {
108
+ let hours = time.hours;
109
+ const minutes = time.minutes.toString().padStart(2, '0');
110
+ const period = hours >= 12 ? TimePeriod.PM : TimePeriod.AM;
111
+ // Convert to 12-hour format
112
+ if (hours === 0) {
113
+ hours = 12;
114
+ }
115
+ else if (hours > 12) {
116
+ hours -= 12;
117
+ }
118
+ const hoursStr = hours.toString();
119
+ if (showSeconds) {
120
+ const seconds = time.seconds.toString().padStart(2, '0');
121
+ return `${hoursStr}:${minutes}:${seconds} ${period}`;
122
+ }
123
+ return `${hoursStr}:${minutes} ${period}`;
124
+ }
125
+ /**
126
+ * Get current time as TimeValue
127
+ */
128
+ static getCurrentTime() {
129
+ const now = new Date();
130
+ return this.createTimeValue(now.getHours(), now.getMinutes(), now.getSeconds());
131
+ }
132
+ /**
133
+ * Compare two TimeValue objects
134
+ */
135
+ static compareTime(time1, time2) {
136
+ const totalSeconds1 = time1.hours * 3600 + time1.minutes * 60 + time1.seconds;
137
+ const totalSeconds2 = time2.hours * 3600 + time2.minutes * 60 + time2.seconds;
138
+ return totalSeconds1 - totalSeconds2;
139
+ }
140
+ /**
141
+ * Check if two TimeValue objects are equal
142
+ */
143
+ static isTimeEqual(time1, time2) {
144
+ return this.compareTime(time1, time2) === 0;
145
+ }
146
+ /**
147
+ * Validate 24-hour time components
148
+ */
149
+ static isValidTime24(hours, minutes, seconds = 0) {
150
+ return (hours >= TIME_BOUNDARIES.MIN_HOUR_24 &&
151
+ hours <= TIME_BOUNDARIES.MAX_HOUR_24 &&
152
+ minutes >= TIME_BOUNDARIES.MIN_MINUTE &&
153
+ minutes <= TIME_BOUNDARIES.MAX_MINUTE &&
154
+ seconds >= TIME_BOUNDARIES.MIN_SECOND &&
155
+ seconds <= TIME_BOUNDARIES.MAX_SECOND);
156
+ }
157
+ /**
158
+ * Validate 12-hour time components
159
+ */
160
+ static isValidTime12(hours, minutes, seconds = 0) {
161
+ return (hours >= TIME_BOUNDARIES.MIN_HOUR_12 &&
162
+ hours <= TIME_BOUNDARIES.MAX_HOUR_12 &&
163
+ minutes >= TIME_BOUNDARIES.MIN_MINUTE &&
164
+ minutes <= TIME_BOUNDARIES.MAX_MINUTE &&
165
+ seconds >= TIME_BOUNDARIES.MIN_SECOND &&
166
+ seconds <= TIME_BOUNDARIES.MAX_SECOND);
167
+ }
168
+ /**
169
+ * Add time to a TimeValue
170
+ */
171
+ static addTime(time, hoursToAdd, minutesToAdd, secondsToAdd = 0) {
172
+ let totalSeconds = time.hours * 3600 + time.minutes * 60 + time.seconds;
173
+ totalSeconds += hoursToAdd * 3600 + minutesToAdd * 60 + secondsToAdd;
174
+ // Handle overflow/underflow
175
+ totalSeconds = ((totalSeconds % 86400) + 86400) % 86400;
176
+ const hours = Math.floor(totalSeconds / 3600);
177
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
178
+ const seconds = totalSeconds % 60;
179
+ return this.createTimeValue(hours, minutes, seconds);
180
+ }
181
+ /**
182
+ * Generate time options for dropdowns
183
+ */
184
+ static generateTimeOptions(interval = 15, format = TimeFormat.TwentyFourHour, showSeconds = false) {
185
+ const options = [];
186
+ for (let hour = 0; hour < 24; hour++) {
187
+ for (let minute = 0; minute < 60; minute += interval) {
188
+ const timeValue = this.createTimeValue(hour, minute, 0);
189
+ const formatted = this.formatTimeValue(timeValue, format, showSeconds);
190
+ options.push({
191
+ value: formatted,
192
+ label: formatted,
193
+ });
194
+ }
195
+ }
196
+ return options;
197
+ }
198
+ /**
199
+ * Round time to nearest interval
200
+ */
201
+ static roundToInterval(time, intervalMinutes) {
202
+ const totalMinutes = time.hours * 60 + time.minutes;
203
+ const roundedMinutes = Math.round(totalMinutes / intervalMinutes) * intervalMinutes;
204
+ const hours = Math.floor(roundedMinutes / 60) % 24;
205
+ const minutes = roundedMinutes % 60;
206
+ return this.createTimeValue(hours, minutes, time.seconds);
207
+ }
208
+ /**
209
+ * Check if time is within range
210
+ */
211
+ static isTimeInRange(time, minTime, maxTime) {
212
+ if (minTime && this.compareTime(time, minTime) < 0) {
213
+ return false;
214
+ }
215
+ if (maxTime && this.compareTime(time, maxTime) > 0) {
216
+ return false;
217
+ }
218
+ return true;
219
+ }
220
+ /**
221
+ * Convert Date object to TimeValue
222
+ */
223
+ static dateToTimeValue(date) {
224
+ return this.createTimeValue(date.getHours(), date.getMinutes(), date.getSeconds());
225
+ }
226
+ /**
227
+ * Convert TimeValue to Date object (using current date)
228
+ */
229
+ static timeValueToDate(time, baseDate) {
230
+ const date = baseDate ? new Date(baseDate) : new Date();
231
+ date.setHours(time.hours, time.minutes, time.seconds, 0);
232
+ return date;
233
+ }
234
+ }
235
+ //# sourceMappingURL=time.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.utils.js","sourceRoot":"","sources":["../../../../src/components/timepicker/utils/time.utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\nimport { TimeValue, TimePeriod, TimeFormat } from '../timepicker.types.js';\nimport { TIME_BOUNDARIES } from '../timepicker.constants.js';\n\n/**\n * Time utility functions for time picker component\n */\nexport class TimeUtils {\n /**\n * Create a new TimeValue object\n */\n static createTimeValue(hours: number, minutes: number, seconds: number = 0, period?: TimePeriod): TimeValue {\n return {\n hours: Math.max(0, Math.min(hours, 23)),\n minutes: Math.max(0, Math.min(minutes, 59)),\n seconds: Math.max(0, Math.min(seconds, 59)),\n period,\n };\n }\n\n /**\n * Parse time string to TimeValue\n */\n static parseTimeString(timeString: string, format: TimeFormat = TimeFormat.TwentyFourHour): TimeValue | null {\n if (!timeString?.trim()) {\n return null;\n }\n\n const cleanTime = timeString.trim().toUpperCase();\n\n if (format === TimeFormat.TwelveHour) {\n return this.parse12HourTime(cleanTime);\n } else {\n return this.parse24HourTime(cleanTime);\n }\n }\n\n /**\n * Parse 24-hour format time string\n */\n private static parse24HourTime(timeString: string): TimeValue | null {\n const match = timeString.match(/^(\\d{1,2}):(\\d{2})(?::(\\d{2}))?$/);\n \n if (!match) {\n return null;\n }\n\n const hours = parseInt(match[1], 10);\n const minutes = parseInt(match[2], 10);\n const seconds = match[3] ? parseInt(match[3], 10) : 0;\n\n if (!this.isValidTime24(hours, minutes, seconds)) {\n return null;\n }\n\n return this.createTimeValue(hours, minutes, seconds);\n }\n\n /**\n * Parse 12-hour format time string\n */\n private static parse12HourTime(timeString: string): TimeValue | null {\n const match = timeString.match(/^(\\d{1,2}):(\\d{2})(?::(\\d{2}))?\\s?(AM|PM)$/);\n \n if (!match) {\n return null;\n }\n\n let hours = parseInt(match[1], 10);\n const minutes = parseInt(match[2], 10);\n const seconds = match[3] ? parseInt(match[3], 10) : 0;\n const period = match[4] as TimePeriod;\n\n if (!this.isValidTime12(hours, minutes, seconds)) {\n return null;\n }\n\n // Convert to 24-hour format for internal storage\n if (period === TimePeriod.PM && hours !== 12) {\n hours += 12;\n } else if (period === TimePeriod.AM && hours === 12) {\n hours = 0;\n }\n\n return this.createTimeValue(hours, minutes, seconds, period);\n }\n\n /**\n * Format TimeValue to string\n */\n static formatTimeValue(time: TimeValue, format: TimeFormat = TimeFormat.TwentyFourHour, showSeconds: boolean = false): string {\n if (!time) {\n return '';\n }\n\n if (format === TimeFormat.TwelveHour) {\n return this.format12HourTime(time, showSeconds);\n } else {\n return this.format24HourTime(time, showSeconds);\n }\n }\n\n /**\n * Format time in 24-hour format\n */\n private static format24HourTime(time: TimeValue, showSeconds: boolean): string {\n const hours = time.hours.toString().padStart(2, '0');\n const minutes = time.minutes.toString().padStart(2, '0');\n \n if (showSeconds) {\n const seconds = time.seconds.toString().padStart(2, '0');\n return `${hours}:${minutes}:${seconds}`;\n }\n \n return `${hours}:${minutes}`;\n }\n\n /**\n * Format time in 12-hour format\n */\n private static format12HourTime(time: TimeValue, showSeconds: boolean): string {\n let hours = time.hours;\n const minutes = time.minutes.toString().padStart(2, '0');\n const period = hours >= 12 ? TimePeriod.PM : TimePeriod.AM;\n\n // Convert to 12-hour format\n if (hours === 0) {\n hours = 12;\n } else if (hours > 12) {\n hours -= 12;\n }\n\n const hoursStr = hours.toString();\n \n if (showSeconds) {\n const seconds = time.seconds.toString().padStart(2, '0');\n return `${hoursStr}:${minutes}:${seconds} ${period}`;\n }\n \n return `${hoursStr}:${minutes} ${period}`;\n }\n\n /**\n * Get current time as TimeValue\n */\n static getCurrentTime(): TimeValue {\n const now = new Date();\n return this.createTimeValue(\n now.getHours(),\n now.getMinutes(),\n now.getSeconds()\n );\n }\n\n /**\n * Compare two TimeValue objects\n */\n static compareTime(time1: TimeValue, time2: TimeValue): number {\n const totalSeconds1 = time1.hours * 3600 + time1.minutes * 60 + time1.seconds;\n const totalSeconds2 = time2.hours * 3600 + time2.minutes * 60 + time2.seconds;\n return totalSeconds1 - totalSeconds2;\n }\n\n /**\n * Check if two TimeValue objects are equal\n */\n static isTimeEqual(time1: TimeValue, time2: TimeValue): boolean {\n return this.compareTime(time1, time2) === 0;\n }\n\n /**\n * Validate 24-hour time components\n */\n private static isValidTime24(hours: number, minutes: number, seconds: number = 0): boolean {\n return (\n hours >= TIME_BOUNDARIES.MIN_HOUR_24 && \n hours <= TIME_BOUNDARIES.MAX_HOUR_24 &&\n minutes >= TIME_BOUNDARIES.MIN_MINUTE && \n minutes <= TIME_BOUNDARIES.MAX_MINUTE &&\n seconds >= TIME_BOUNDARIES.MIN_SECOND && \n seconds <= TIME_BOUNDARIES.MAX_SECOND\n );\n }\n\n /**\n * Validate 12-hour time components\n */\n private static isValidTime12(hours: number, minutes: number, seconds: number = 0): boolean {\n return (\n hours >= TIME_BOUNDARIES.MIN_HOUR_12 && \n hours <= TIME_BOUNDARIES.MAX_HOUR_12 &&\n minutes >= TIME_BOUNDARIES.MIN_MINUTE && \n minutes <= TIME_BOUNDARIES.MAX_MINUTE &&\n seconds >= TIME_BOUNDARIES.MIN_SECOND && \n seconds <= TIME_BOUNDARIES.MAX_SECOND\n );\n }\n\n /**\n * Add time to a TimeValue\n */\n static addTime(time: TimeValue, hoursToAdd: number, minutesToAdd: number, secondsToAdd: number = 0): TimeValue {\n let totalSeconds = time.hours * 3600 + time.minutes * 60 + time.seconds;\n totalSeconds += hoursToAdd * 3600 + minutesToAdd * 60 + secondsToAdd;\n\n // Handle overflow/underflow\n totalSeconds = ((totalSeconds % 86400) + 86400) % 86400;\n\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n return this.createTimeValue(hours, minutes, seconds);\n }\n\n /**\n * Generate time options for dropdowns\n */\n static generateTimeOptions(interval: number = 15, format: TimeFormat = TimeFormat.TwentyFourHour, showSeconds: boolean = false): Array<{value: string, label: string}> {\n const options: Array<{value: string, label: string}> = [];\n \n for (let hour = 0; hour < 24; hour++) {\n for (let minute = 0; minute < 60; minute += interval) {\n const timeValue = this.createTimeValue(hour, minute, 0);\n const formatted = this.formatTimeValue(timeValue, format, showSeconds);\n options.push({\n value: formatted,\n label: formatted,\n });\n }\n }\n\n return options;\n }\n\n /**\n * Round time to nearest interval\n */\n static roundToInterval(time: TimeValue, intervalMinutes: number): TimeValue {\n const totalMinutes = time.hours * 60 + time.minutes;\n const roundedMinutes = Math.round(totalMinutes / intervalMinutes) * intervalMinutes;\n \n const hours = Math.floor(roundedMinutes / 60) % 24;\n const minutes = roundedMinutes % 60;\n\n return this.createTimeValue(hours, minutes, time.seconds);\n }\n\n /**\n * Check if time is within range\n */\n static isTimeInRange(time: TimeValue, minTime: TimeValue | null, maxTime: TimeValue | null): boolean {\n if (minTime && this.compareTime(time, minTime) < 0) {\n return false;\n }\n \n if (maxTime && this.compareTime(time, maxTime) > 0) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Convert Date object to TimeValue\n */\n static dateToTimeValue(date: Date): TimeValue {\n return this.createTimeValue(\n date.getHours(),\n date.getMinutes(),\n date.getSeconds()\n );\n }\n\n /**\n * Convert TimeValue to Date object (using current date)\n */\n static timeValueToDate(time: TimeValue, baseDate?: Date): Date {\n const date = baseDate ? new Date(baseDate) : new Date();\n date.setHours(time.hours, time.minutes, time.seconds, 0);\n return date;\n }\n}\n"]}