ngx-kit 5.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +3 -2
  2. package/angle-selector/README.md +34 -0
  3. package/box-shadow/README.md +33 -0
  4. package/color-picker/README.md +52 -0
  5. package/data-table/README.md +120 -0
  6. package/date-picker/README.md +74 -0
  7. package/dialog/README.md +94 -169
  8. package/drawer-menu/README.md +76 -0
  9. package/dropzone/README.md +59 -0
  10. package/fesm2022/ngx-kit-angle-selector.mjs +2 -2
  11. package/fesm2022/ngx-kit-angle-selector.mjs.map +1 -1
  12. package/fesm2022/ngx-kit-box-shadow.mjs +28 -27
  13. package/fesm2022/ngx-kit-box-shadow.mjs.map +1 -1
  14. package/fesm2022/ngx-kit-color-picker.mjs +173 -43
  15. package/fesm2022/ngx-kit-color-picker.mjs.map +1 -1
  16. package/fesm2022/ngx-kit-data-table.mjs +9 -2
  17. package/fesm2022/ngx-kit-data-table.mjs.map +1 -1
  18. package/fesm2022/ngx-kit-date-picker.mjs +120 -86
  19. package/fesm2022/ngx-kit-date-picker.mjs.map +1 -1
  20. package/fesm2022/ngx-kit-dialog.mjs +38 -7
  21. package/fesm2022/ngx-kit-dialog.mjs.map +1 -1
  22. package/fesm2022/ngx-kit-drawer-menu.mjs +190 -0
  23. package/fesm2022/ngx-kit-drawer-menu.mjs.map +1 -0
  24. package/fesm2022/ngx-kit-dropzone.mjs +272 -0
  25. package/fesm2022/ngx-kit-dropzone.mjs.map +1 -0
  26. package/fesm2022/ngx-kit-form-field.mjs +87 -0
  27. package/fesm2022/ngx-kit-form-field.mjs.map +1 -0
  28. package/fesm2022/ngx-kit-gallery.mjs +419 -0
  29. package/fesm2022/ngx-kit-gallery.mjs.map +1 -0
  30. package/fesm2022/ngx-kit-gradient-picker.mjs +12 -4
  31. package/fesm2022/ngx-kit-gradient-picker.mjs.map +1 -1
  32. package/fesm2022/ngx-kit-image-editor.mjs +501 -0
  33. package/fesm2022/ngx-kit-image-editor.mjs.map +1 -0
  34. package/fesm2022/ngx-kit-menu.mjs +9 -4
  35. package/fesm2022/ngx-kit-menu.mjs.map +1 -1
  36. package/fesm2022/ngx-kit-message.mjs +50 -24
  37. package/fesm2022/ngx-kit-message.mjs.map +1 -1
  38. package/fesm2022/ngx-kit-notify.mjs +1 -4
  39. package/fesm2022/ngx-kit-notify.mjs.map +1 -1
  40. package/fesm2022/ngx-kit-shared.mjs +126 -83
  41. package/fesm2022/ngx-kit-shared.mjs.map +1 -1
  42. package/fesm2022/ngx-kit-time-picker.mjs +562 -0
  43. package/fesm2022/ngx-kit-time-picker.mjs.map +1 -0
  44. package/fesm2022/ngx-kit.mjs.map +1 -1
  45. package/gallery/README.md +71 -0
  46. package/gradient-picker/README.md +41 -0
  47. package/image-editor/README.md +44 -0
  48. package/menu/README.md +85 -0
  49. package/message/README.md +70 -0
  50. package/notify/README.md +56 -0
  51. package/package.json +25 -1
  52. package/shared/README.md +117 -0
  53. package/styles/all.css +27 -0
  54. package/styles/image-viewer.css +12 -0
  55. package/types/ngx-kit-box-shadow.d.ts +1 -2
  56. package/types/ngx-kit-data-table.d.ts +1 -0
  57. package/types/ngx-kit-date-picker.d.ts +1 -1
  58. package/types/ngx-kit-dialog.d.ts +1 -0
  59. package/types/ngx-kit-drawer-menu.d.ts +101 -0
  60. package/types/ngx-kit-dropzone.d.ts +84 -0
  61. package/types/ngx-kit-form-field.d.ts +31 -0
  62. package/types/ngx-kit-gallery.d.ts +168 -0
  63. package/types/ngx-kit-image-editor.d.ts +175 -0
  64. package/types/ngx-kit-menu.d.ts +1 -0
  65. package/types/ngx-kit-message.d.ts +13 -3
  66. package/types/ngx-kit-notify.d.ts +0 -1
  67. package/types/ngx-kit-shared.d.ts +44 -13
  68. package/types/ngx-kit-time-picker.d.ts +150 -0
@@ -0,0 +1,562 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, inject, output, model, input, viewChild, signal, computed, forwardRef, Component, ViewContainerRef, Renderer2, HostListener, Directive } from '@angular/core';
3
+ import { CommonModule } from '@angular/common';
4
+ import { BrowserService, OverlayService } from 'ngx-kit/shared';
5
+ import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
6
+
7
+ class NgxTimePickerConfig {
8
+ cancelButtonText = 'Cancel';
9
+ confirmButtonText = 'Ok';
10
+ amText = 'AM';
11
+ pmText = 'PM';
12
+ format = '12';
13
+ minuteStep = 1;
14
+ autoSwitchToMinute = true;
15
+ }
16
+ const DEFAULT_TIME_PICKER_CONFIG = new NgxTimePickerConfig();
17
+ const NGX_TIME_PICKER_CONFIG = new InjectionToken('ngx-time-picker-config', {
18
+ factory: () => DEFAULT_TIME_PICKER_CONFIG,
19
+ });
20
+
21
+ class NgxInputTimePickerComponent {
22
+ browserService = inject(BrowserService);
23
+ change = output();
24
+ cancel = output();
25
+ config = inject(NGX_TIME_PICKER_CONFIG);
26
+ isDisabled = false;
27
+ /**
28
+ * Time value.
29
+ *
30
+ * Example:
31
+ * 14:35
32
+ */
33
+ value = model('12:00', /* @ts-ignore */
34
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
35
+ /**
36
+ * 12h or 24h.
37
+ */
38
+ format = input(this.config.format, /* @ts-ignore */
39
+ ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
40
+ amOrPm = model(this.config.format == '12' ? 'AM' : undefined, /* @ts-ignore */
41
+ ...(ngDevMode ? [{ debugName: "amOrPm" }] : /* istanbul ignore next */ []));
42
+ /**
43
+ * Minute step.
44
+ */
45
+ minuteStep = input(this.config.minuteStep, /* @ts-ignore */
46
+ ...(ngDevMode ? [{ debugName: "minuteStep" }] : /* istanbul ignore next */ []));
47
+ /**
48
+ * Whether the clock is disabled.
49
+ */
50
+ disabled = input(false, /* @ts-ignore */
51
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
52
+ /**
53
+ * Whether to automatically switch from hour to minute.
54
+ */
55
+ autoSwitchToMinute = input(this.config.autoSwitchToMinute, /* @ts-ignore */
56
+ ...(ngDevMode ? [{ debugName: "autoSwitchToMinute" }] : /* istanbul ignore next */ []));
57
+ clock = viewChild('clock', /* @ts-ignore */
58
+ ...(ngDevMode ? [{ debugName: "clock" }] : /* istanbul ignore next */ []));
59
+ mode = signal('hour', /* @ts-ignore */
60
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
61
+ dragging = false;
62
+ parsedTime = computed(() => {
63
+ const value = this.value();
64
+ const [hour, minute] = value.split(':').map(Number);
65
+ return {
66
+ hour: Number.isFinite(hour) ? hour : 12,
67
+ minute: Number.isFinite(minute) ? minute : 0,
68
+ };
69
+ }, /* @ts-ignore */
70
+ ...(ngDevMode ? [{ debugName: "parsedTime" }] : /* istanbul ignore next */ []));
71
+ displayHour = computed(() => {
72
+ const { hour } = this.parsedTime();
73
+ if (this.format() === '12') {
74
+ const h = hour % 12;
75
+ return h === 0 ? 12 : h;
76
+ }
77
+ return hour;
78
+ }, /* @ts-ignore */
79
+ ...(ngDevMode ? [{ debugName: "displayHour" }] : /* istanbul ignore next */ []));
80
+ displayMinute = computed(() => {
81
+ return this.parsedTime().minute;
82
+ }, /* @ts-ignore */
83
+ ...(ngDevMode ? [{ debugName: "displayMinute" }] : /* istanbul ignore next */ []));
84
+ hourNumbers = computed(() => {
85
+ if (this.format() === '24') {
86
+ return Array.from({ length: 24 }, (_, i) => i);
87
+ }
88
+ return Array.from({ length: 12 }, (_, i) => i + 1);
89
+ }, /* @ts-ignore */
90
+ ...(ngDevMode ? [{ debugName: "hourNumbers" }] : /* istanbul ignore next */ []));
91
+ minuteNumbers = computed(() => {
92
+ const step = Math.max(1, 5);
93
+ const values = [];
94
+ for (let i = 0; i < 60; i += step) {
95
+ values.push(i);
96
+ }
97
+ return values;
98
+ }, /* @ts-ignore */
99
+ ...(ngDevMode ? [{ debugName: "minuteNumbers" }] : /* istanbul ignore next */ []));
100
+ hourAngle = computed(() => {
101
+ const { hour } = this.parsedTime();
102
+ if (this.format() === '24') {
103
+ /*
104
+ * MUI-like 24 hour clock.
105
+ *
106
+ * 0 -> 0°
107
+ * 6 -> 90°
108
+ * 12 -> 180°
109
+ * 18 -> 270°
110
+ */
111
+ return (hour % 12) * 30;
112
+ }
113
+ const h = hour % 12;
114
+ return h * 30;
115
+ }, /* @ts-ignore */
116
+ ...(ngDevMode ? [{ debugName: "hourAngle" }] : /* istanbul ignore next */ []));
117
+ minuteAngle = computed(() => {
118
+ return this.parsedTime().minute * 6;
119
+ }, /* @ts-ignore */
120
+ ...(ngDevMode ? [{ debugName: "minuteAngle" }] : /* istanbul ignore next */ []));
121
+ currentAngle = computed(() => {
122
+ return this.mode() === 'hour' ? this.hourAngle() : this.minuteAngle();
123
+ }, /* @ts-ignore */
124
+ ...(ngDevMode ? [{ debugName: "currentAngle" }] : /* istanbul ignore next */ []));
125
+ handLength = computed(() => {
126
+ if (this.mode() === 'hour' && this.format() === '24') {
127
+ const hour = this.parsedTime().hour;
128
+ if (hour >= 13 && hour <= 23) {
129
+ return 58;
130
+ }
131
+ }
132
+ return 86;
133
+ }, /* @ts-ignore */
134
+ ...(ngDevMode ? [{ debugName: "handLength" }] : /* istanbul ignore next */ []));
135
+ handEnd = computed(() => {
136
+ const angle = this.currentAngle();
137
+ const radians = ((angle - 90) * Math.PI) / 180;
138
+ const radius = this.handLength();
139
+ return {
140
+ x: 120 + Math.cos(radians) * radius,
141
+ y: 120 + Math.sin(radians) * radius,
142
+ };
143
+ }, /* @ts-ignore */
144
+ ...(ngDevMode ? [{ debugName: "handEnd" }] : /* istanbul ignore next */ []));
145
+ selectedPosition = computed(() => {
146
+ const angle = this.currentAngle();
147
+ const radians = ((angle - 90) * Math.PI) / 180;
148
+ const radius = this.mode() === 'hour' ? 82 : 82;
149
+ return {
150
+ x: 120 + Math.cos(radians) * radius,
151
+ y: 120 + Math.sin(radians) * radius,
152
+ };
153
+ }, /* @ts-ignore */
154
+ ...(ngDevMode ? [{ debugName: "selectedPosition" }] : /* istanbul ignore next */ []));
155
+ _onChange = (value) => { };
156
+ _onTouched = () => { };
157
+ _validatorOnChange = () => { };
158
+ constructor() { }
159
+ ngOnInit() { }
160
+ writeValue(value) {
161
+ if (!value)
162
+ value = '12:00';
163
+ const s = value.split(':');
164
+ if (this.format() == '12') {
165
+ if (+s[0] > 12) {
166
+ s[0] = (+s[0] - 12).toString().padStart(2, '0');
167
+ this.amOrPm.set('PM');
168
+ }
169
+ else {
170
+ this.amOrPm.set('AM');
171
+ }
172
+ }
173
+ this.value.set(s.join(':') + ' ' + this.amOrPm());
174
+ }
175
+ validate(control) {
176
+ return null;
177
+ }
178
+ registerOnChange(fn) {
179
+ this._onChange = fn;
180
+ }
181
+ registerOnTouched(fn) {
182
+ this._onTouched = fn;
183
+ }
184
+ registerOnValidatorChange(fn) {
185
+ this._validatorOnChange = fn;
186
+ }
187
+ setDisabledState(disabled) {
188
+ this.isDisabled = disabled;
189
+ }
190
+ startPointer(event) {
191
+ if (this.disabled()) {
192
+ return;
193
+ }
194
+ event.preventDefault();
195
+ this.dragging = true;
196
+ const target = event.currentTarget;
197
+ target.setPointerCapture?.(event.pointerId);
198
+ this.updateFromPointer(event);
199
+ }
200
+ movePointer(event) {
201
+ if (!this.dragging || this.disabled()) {
202
+ return;
203
+ }
204
+ event.preventDefault();
205
+ this.updateFromPointer(event);
206
+ }
207
+ endPointer(event) {
208
+ if (!this.dragging) {
209
+ return;
210
+ }
211
+ this.dragging = false;
212
+ const target = event.currentTarget;
213
+ target.releasePointerCapture?.(event.pointerId);
214
+ if (this.mode() === 'hour' && this.autoSwitchToMinute()) {
215
+ this.mode.set('minute');
216
+ }
217
+ }
218
+ selectHour(hour) {
219
+ if (this.disabled()) {
220
+ return;
221
+ }
222
+ let normalizedHour = hour;
223
+ if (this.format() === '12') {
224
+ const currentHour = this.parsedTime().hour;
225
+ const isPm = currentHour >= 12;
226
+ normalizedHour = hour === 12 ? (isPm ? 12 : 0) : isPm ? hour + 12 : hour;
227
+ }
228
+ this.setTime(normalizedHour, this.parsedTime().minute);
229
+ if (this.autoSwitchToMinute()) {
230
+ this.mode.set('minute');
231
+ }
232
+ }
233
+ selectMinute(minute) {
234
+ if (this.disabled()) {
235
+ return;
236
+ }
237
+ this.setTime(this.parsedTime().hour, minute);
238
+ }
239
+ setMode(mode) {
240
+ if (!this.disabled()) {
241
+ this.mode.set(mode);
242
+ }
243
+ }
244
+ updateFromPointer(event) {
245
+ const svg = this.clock()?.nativeElement;
246
+ if (!svg) {
247
+ return;
248
+ }
249
+ const rect = svg.getBoundingClientRect();
250
+ /*
251
+ * SVG viewBox = 0 0 240 240
252
+ *
253
+ * Convert browser coordinates
254
+ * to SVG coordinates.
255
+ */
256
+ const x = ((event.clientX - rect.left) / rect.width) * 240;
257
+ const y = ((event.clientY - rect.top) / rect.height) * 240;
258
+ const dx = x - 120;
259
+ const dy = y - 120;
260
+ let angle = (Math.atan2(dy, dx) * 180) / Math.PI + 90;
261
+ if (angle < 0) {
262
+ angle += 360;
263
+ }
264
+ if (this.mode() === 'hour') {
265
+ this.updateHourFromAngle(angle);
266
+ }
267
+ else {
268
+ this.updateMinuteFromAngle(angle);
269
+ }
270
+ }
271
+ updateHourFromAngle(angle) {
272
+ let hour = Math.round(angle / 30);
273
+ if (hour === 0 || hour === 12) {
274
+ hour = 12;
275
+ }
276
+ if (this.format() === '24') {
277
+ /*
278
+ * Determine whether pointer is closer
279
+ * to inner or outer 12-hour ring.
280
+ *
281
+ * For a full 24-hour implementation we use
282
+ * the current half-day when possible.
283
+ */
284
+ const currentHour = this.parsedTime().hour;
285
+ const currentIsPm = currentHour >= 12;
286
+ if (hour !== 12) {
287
+ hour = currentIsPm ? hour + 12 : hour;
288
+ }
289
+ else {
290
+ hour = currentIsPm ? 12 : 0;
291
+ }
292
+ }
293
+ this.setTime(hour, this.parsedTime().minute);
294
+ }
295
+ updateMinuteFromAngle(angle) {
296
+ let minute = Math.round(angle / 6);
297
+ minute = minute % 60;
298
+ const step = Math.max(1, this.minuteStep());
299
+ minute = Math.round(minute / step) * step;
300
+ if (minute >= 60) {
301
+ minute = 0;
302
+ }
303
+ this.setTime(this.parsedTime().hour, minute);
304
+ }
305
+ setTime(hour, minute) {
306
+ const h = String(hour).padStart(2, '0');
307
+ const m = String(minute).padStart(2, '0');
308
+ this.value.set(`${h}:${m}`);
309
+ }
310
+ isSelectedHour(hour) {
311
+ const current = this.displayHour();
312
+ return current === hour;
313
+ }
314
+ isSelectedMinute(minute) {
315
+ return this.displayMinute() === minute;
316
+ }
317
+ formatHour(hour) {
318
+ if (this.format() === '24') {
319
+ return String(hour).padStart(2, '0');
320
+ }
321
+ return String(hour);
322
+ }
323
+ formatMinute(minute) {
324
+ return String(minute).padStart(2, '0');
325
+ }
326
+ numberPosition(index, total, radius = 94) {
327
+ const angle = (index / total) * 360 - 90;
328
+ const radians = (angle * Math.PI) / 180;
329
+ return {
330
+ x: 120 + Math.cos(radians) * radius,
331
+ y: 120 + Math.sin(radians) * radius,
332
+ };
333
+ }
334
+ hourPosition(hour, inner = false) {
335
+ const normalized = hour % 12;
336
+ const angle = normalized * 30 - 90;
337
+ const radians = (angle * Math.PI) / 180;
338
+ const radius = inner ? 58 : 94;
339
+ return {
340
+ x: 120 + Math.cos(radians) * radius,
341
+ y: 120 + Math.sin(radians) * radius,
342
+ };
343
+ }
344
+ minutePosition(minute) {
345
+ const angle = minute * 6 - 90;
346
+ const radians = (angle * Math.PI) / 180;
347
+ return {
348
+ x: 120 + Math.cos(radians) * 94,
349
+ y: 120 + Math.sin(radians) * 94,
350
+ };
351
+ }
352
+ ok() {
353
+ if (this.format() == '12') {
354
+ this.value.update((u) => u + ` ${this.amOrPm()}`);
355
+ }
356
+ this.change.emit(this.value());
357
+ this._onChange(this.value());
358
+ }
359
+ close() {
360
+ this.cancel.emit();
361
+ }
362
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxInputTimePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
363
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: NgxInputTimePickerComponent, isStandalone: true, selector: "ngx-time-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, amOrPm: { classPropertyName: "amOrPm", publicName: "amOrPm", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, autoSwitchToMinute: { classPropertyName: "autoSwitchToMinute", publicName: "autoSwitchToMinute", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { change: "change", cancel: "cancel", value: "valueChange", amOrPm: "amOrPmChange" }, providers: [
364
+ {
365
+ provide: NG_VALUE_ACCESSOR,
366
+ useExisting: forwardRef(() => NgxInputTimePickerComponent),
367
+ multi: true,
368
+ },
369
+ {
370
+ provide: NG_VALIDATORS,
371
+ useExisting: forwardRef(() => NgxInputTimePickerComponent),
372
+ multi: true,
373
+ },
374
+ ], viewQueries: [{ propertyName: "clock", first: true, predicate: ["clock"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ngx-time-picker\" [class.ngx-time-picker--disabled]=\"disabled()\">\n <!-- Header -->\n <div class=\"ngx-time-picker__header\">\n <button\n type=\"button\"\n class=\"ngx-time-picker__value\"\n [class.active]=\"mode() === 'hour'\"\n [disabled]=\"disabled()\"\n (click)=\"setMode('hour')\">\n {{ formatHour(displayHour()) }}\n </button>\n\n <span class=\"ngx-time-picker__separator\">:</span>\n\n <button\n type=\"button\"\n class=\"ngx-time-picker__value\"\n [class.active]=\"mode() === 'minute'\"\n [disabled]=\"disabled()\"\n (click)=\"setMode('minute')\">\n {{ formatMinute(displayMinute()) }}\n </button>\n\n @if (format() == '12') {\n <div class=\"ngx-time-picker_format\">\n <button [class.active]=\"amOrPm() == 'AM'\" (click)=\"amOrPm.set('AM')\">\n {{ config.amText }}\n </button>\n <button [class.active]=\"amOrPm() == 'PM'\" (click)=\"amOrPm.set('PM')\">\n {{ config.pmText }}\n </button>\n </div>\n }\n </div>\n\n <!-- Clock -->\n <div class=\"ngx-time-picker__clock-wrapper\">\n <svg\n #clock\n class=\"ngx-time-picker__clock\"\n viewBox=\"0 0 240 240\"\n xmlns=\"http://www.w3.org/2000/svg\"\n (pointerdown)=\"startPointer($event)\"\n (pointermove)=\"movePointer($event)\"\n (pointerup)=\"endPointer($event)\"\n (pointercancel)=\"endPointer($event)\">\n <!-- Background -->\n <circle class=\"clock-background\" cx=\"120\" cy=\"120\" r=\"112\" />\n\n <!-- Selected hand line -->\n <line class=\"clock-hand\" x1=\"120\" y1=\"120\" [attr.x2]=\"handEnd().x\" [attr.y2]=\"handEnd().y\" />\n\n <!-- Selected circle -->\n <circle\n class=\"clock-selected\"\n [attr.cx]=\"selectedPosition().x\"\n [attr.cy]=\"selectedPosition().y\"\n r=\"18\" />\n\n <!-- Center -->\n <circle class=\"clock-center\" cx=\"120\" cy=\"120\" r=\"5\" />\n\n <!-- HOURS -->\n @if (mode() === 'hour') {\n @for (hour of hourNumbers(); track hour) {\n @if (format() === '24' && hour >= 13) {\n <g\n class=\"clock-number clock-number--inner\"\n [class.selected]=\"isSelectedHour(hour)\"\n (click)=\"selectHour(hour)\">\n <circle\n [attr.cx]=\"hourPosition(hour - 12, true).x\"\n [attr.cy]=\"hourPosition(hour - 12, true).y\"\n r=\"16\" />\n\n <text\n [attr.x]=\"hourPosition(hour - 12, true).x\"\n [attr.y]=\"hourPosition(hour - 12, true).y\">\n {{ formatHour(hour) }}\n </text>\n </g>\n } @else {\n <g\n class=\"clock-number\"\n [class.selected]=\"isSelectedHour(hour)\"\n (click)=\"selectHour(hour)\">\n <circle [attr.cx]=\"hourPosition(hour).x\" [attr.cy]=\"hourPosition(hour).y\" r=\"18\" />\n\n <text [attr.x]=\"hourPosition(hour).x\" [attr.y]=\"hourPosition(hour).y\">\n {{ formatHour(hour) }}\n </text>\n </g>\n }\n }\n }\n\n <!-- MINUTES -->\n @if (mode() === 'minute') {\n @for (minute of minuteNumbers(); track minute) {\n <g\n class=\"clock-number\"\n [class.selected]=\"isSelectedMinute(minute)\"\n (click)=\"selectMinute(minute)\">\n <circle\n [attr.cx]=\"minutePosition(minute).x\"\n [attr.cy]=\"minutePosition(minute).y\"\n r=\"18\" />\n\n <text [attr.x]=\"minutePosition(minute).x\" [attr.y]=\"minutePosition(minute).y\">\n {{ formatMinute(minute) }}\n </text>\n </g>\n }\n }\n </svg>\n </div>\n <div class=\"ngx-time-picker--footer\">\n <button (click)=\"close()\">\n {{ config.cancelButtonText }}\n </button>\n\n <button (click)=\"ok()\">\n {{ config.confirmButtonText }}\n </button>\n </div>\n</div>\n", styles: [":host{--ngx-time-picker-clock-bg: light-dark(#f8f8f8, #181818);--ngx-time-picker-header-bg: #6200ee;--ngx-time-picker-header-fg: #fff;--ngx-clock-bg: light-dark(#e8e8e8, #35363c);display:inline-block}.ngx-time-picker{width:270px;max-width:100%;border-radius:15px;overflow:hidden;direction:ltr;user-select:none;-webkit-user-select:none;border:1px rgba(191,191,191,.4) solid;box-shadow:0 0 20px #9090904f}.ngx-time-picker__header{display:flex;align-items:center;justify-content:center;height:82px;background:var(--ngx-time-picker-header-bg, );color:var(--ngx-time-picker-header-fg)}.ngx-time-picker__value{border:0;padding:0;background:transparent;color:#ffffff8c;font-size:48px;line-height:1;font-weight:400;cursor:pointer;transition:color .16s ease,opacity .16s ease;font-variant-numeric:tabular-nums}.ngx-time-picker__value:hover{color:#fffc}.ngx-time-picker__value.active{color:#fff}.ngx-time-picker__value:disabled{cursor:default}.ngx-time-picker__separator{margin-inline:4px;font-size:44px;line-height:1;color:#fff}.ngx-time-picker__clock-wrapper{display:flex;align-items:center;justify-content:center;padding:20px;background:var(--ngx-time-picker-clock-bg)}.ngx-time-picker__clock{width:250px;height:250px;touch-action:none;overflow:visible;cursor:pointer}.clock-background{fill:var(--ngx-clock-bg)}.clock-hand{stroke:#1976d2;stroke-width:2;stroke-linecap:round;pointer-events:none}.clock-center,.clock-selected{fill:#1976d2;pointer-events:none}.clock-number{cursor:pointer}.clock-number circle{fill:transparent;transition:fill .12s ease,transform .12s ease}.clock-number text{fill:currentColor;font-size:14px;font-family:Roboto,Arial,sans-serif;text-anchor:middle;dominant-baseline:central;pointer-events:none;transition:fill .12s ease}.clock-number:hover circle{fill:#1976d21f}.clock-number.selected circle{fill:#1976d2}.clock-number.selected text{fill:#fff;font-weight:500}.clock-number--inner text{font-size:12px}.ngx-time-picker--disabled{opacity:.5;pointer-events:none}.ngx-time-picker--footer{display:flex;justify-content:flex-end;gap:5px;padding:5px 10px 20px;background:var(--ngx-time-picker-clock-bg)}.ngx-time-picker--footer button{outline:none;background:none;color:inherit;border:none;border-radius:4px;padding:8px 15px;box-shadow:none;transition:all .3s}.ngx-time-picker--footer button:not([disabled]):hover{cursor:pointer;background:#816ef175}.ngx-time-picker_format{display:flex;flex-direction:column;margin:0 15px;gap:5px}.ngx-time-picker_format button{all:unset;opacity:.4;cursor:pointer}.ngx-time-picker_format button.active{opacity:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
375
+ }
376
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxInputTimePickerComponent, decorators: [{
377
+ type: Component,
378
+ args: [{ selector: 'ngx-time-picker', imports: [CommonModule], providers: [
379
+ {
380
+ provide: NG_VALUE_ACCESSOR,
381
+ useExisting: forwardRef(() => NgxInputTimePickerComponent),
382
+ multi: true,
383
+ },
384
+ {
385
+ provide: NG_VALIDATORS,
386
+ useExisting: forwardRef(() => NgxInputTimePickerComponent),
387
+ multi: true,
388
+ },
389
+ ], template: "<div class=\"ngx-time-picker\" [class.ngx-time-picker--disabled]=\"disabled()\">\n <!-- Header -->\n <div class=\"ngx-time-picker__header\">\n <button\n type=\"button\"\n class=\"ngx-time-picker__value\"\n [class.active]=\"mode() === 'hour'\"\n [disabled]=\"disabled()\"\n (click)=\"setMode('hour')\">\n {{ formatHour(displayHour()) }}\n </button>\n\n <span class=\"ngx-time-picker__separator\">:</span>\n\n <button\n type=\"button\"\n class=\"ngx-time-picker__value\"\n [class.active]=\"mode() === 'minute'\"\n [disabled]=\"disabled()\"\n (click)=\"setMode('minute')\">\n {{ formatMinute(displayMinute()) }}\n </button>\n\n @if (format() == '12') {\n <div class=\"ngx-time-picker_format\">\n <button [class.active]=\"amOrPm() == 'AM'\" (click)=\"amOrPm.set('AM')\">\n {{ config.amText }}\n </button>\n <button [class.active]=\"amOrPm() == 'PM'\" (click)=\"amOrPm.set('PM')\">\n {{ config.pmText }}\n </button>\n </div>\n }\n </div>\n\n <!-- Clock -->\n <div class=\"ngx-time-picker__clock-wrapper\">\n <svg\n #clock\n class=\"ngx-time-picker__clock\"\n viewBox=\"0 0 240 240\"\n xmlns=\"http://www.w3.org/2000/svg\"\n (pointerdown)=\"startPointer($event)\"\n (pointermove)=\"movePointer($event)\"\n (pointerup)=\"endPointer($event)\"\n (pointercancel)=\"endPointer($event)\">\n <!-- Background -->\n <circle class=\"clock-background\" cx=\"120\" cy=\"120\" r=\"112\" />\n\n <!-- Selected hand line -->\n <line class=\"clock-hand\" x1=\"120\" y1=\"120\" [attr.x2]=\"handEnd().x\" [attr.y2]=\"handEnd().y\" />\n\n <!-- Selected circle -->\n <circle\n class=\"clock-selected\"\n [attr.cx]=\"selectedPosition().x\"\n [attr.cy]=\"selectedPosition().y\"\n r=\"18\" />\n\n <!-- Center -->\n <circle class=\"clock-center\" cx=\"120\" cy=\"120\" r=\"5\" />\n\n <!-- HOURS -->\n @if (mode() === 'hour') {\n @for (hour of hourNumbers(); track hour) {\n @if (format() === '24' && hour >= 13) {\n <g\n class=\"clock-number clock-number--inner\"\n [class.selected]=\"isSelectedHour(hour)\"\n (click)=\"selectHour(hour)\">\n <circle\n [attr.cx]=\"hourPosition(hour - 12, true).x\"\n [attr.cy]=\"hourPosition(hour - 12, true).y\"\n r=\"16\" />\n\n <text\n [attr.x]=\"hourPosition(hour - 12, true).x\"\n [attr.y]=\"hourPosition(hour - 12, true).y\">\n {{ formatHour(hour) }}\n </text>\n </g>\n } @else {\n <g\n class=\"clock-number\"\n [class.selected]=\"isSelectedHour(hour)\"\n (click)=\"selectHour(hour)\">\n <circle [attr.cx]=\"hourPosition(hour).x\" [attr.cy]=\"hourPosition(hour).y\" r=\"18\" />\n\n <text [attr.x]=\"hourPosition(hour).x\" [attr.y]=\"hourPosition(hour).y\">\n {{ formatHour(hour) }}\n </text>\n </g>\n }\n }\n }\n\n <!-- MINUTES -->\n @if (mode() === 'minute') {\n @for (minute of minuteNumbers(); track minute) {\n <g\n class=\"clock-number\"\n [class.selected]=\"isSelectedMinute(minute)\"\n (click)=\"selectMinute(minute)\">\n <circle\n [attr.cx]=\"minutePosition(minute).x\"\n [attr.cy]=\"minutePosition(minute).y\"\n r=\"18\" />\n\n <text [attr.x]=\"minutePosition(minute).x\" [attr.y]=\"minutePosition(minute).y\">\n {{ formatMinute(minute) }}\n </text>\n </g>\n }\n }\n </svg>\n </div>\n <div class=\"ngx-time-picker--footer\">\n <button (click)=\"close()\">\n {{ config.cancelButtonText }}\n </button>\n\n <button (click)=\"ok()\">\n {{ config.confirmButtonText }}\n </button>\n </div>\n</div>\n", styles: [":host{--ngx-time-picker-clock-bg: light-dark(#f8f8f8, #181818);--ngx-time-picker-header-bg: #6200ee;--ngx-time-picker-header-fg: #fff;--ngx-clock-bg: light-dark(#e8e8e8, #35363c);display:inline-block}.ngx-time-picker{width:270px;max-width:100%;border-radius:15px;overflow:hidden;direction:ltr;user-select:none;-webkit-user-select:none;border:1px rgba(191,191,191,.4) solid;box-shadow:0 0 20px #9090904f}.ngx-time-picker__header{display:flex;align-items:center;justify-content:center;height:82px;background:var(--ngx-time-picker-header-bg, );color:var(--ngx-time-picker-header-fg)}.ngx-time-picker__value{border:0;padding:0;background:transparent;color:#ffffff8c;font-size:48px;line-height:1;font-weight:400;cursor:pointer;transition:color .16s ease,opacity .16s ease;font-variant-numeric:tabular-nums}.ngx-time-picker__value:hover{color:#fffc}.ngx-time-picker__value.active{color:#fff}.ngx-time-picker__value:disabled{cursor:default}.ngx-time-picker__separator{margin-inline:4px;font-size:44px;line-height:1;color:#fff}.ngx-time-picker__clock-wrapper{display:flex;align-items:center;justify-content:center;padding:20px;background:var(--ngx-time-picker-clock-bg)}.ngx-time-picker__clock{width:250px;height:250px;touch-action:none;overflow:visible;cursor:pointer}.clock-background{fill:var(--ngx-clock-bg)}.clock-hand{stroke:#1976d2;stroke-width:2;stroke-linecap:round;pointer-events:none}.clock-center,.clock-selected{fill:#1976d2;pointer-events:none}.clock-number{cursor:pointer}.clock-number circle{fill:transparent;transition:fill .12s ease,transform .12s ease}.clock-number text{fill:currentColor;font-size:14px;font-family:Roboto,Arial,sans-serif;text-anchor:middle;dominant-baseline:central;pointer-events:none;transition:fill .12s ease}.clock-number:hover circle{fill:#1976d21f}.clock-number.selected circle{fill:#1976d2}.clock-number.selected text{fill:#fff;font-weight:500}.clock-number--inner text{font-size:12px}.ngx-time-picker--disabled{opacity:.5;pointer-events:none}.ngx-time-picker--footer{display:flex;justify-content:flex-end;gap:5px;padding:5px 10px 20px;background:var(--ngx-time-picker-clock-bg)}.ngx-time-picker--footer button{outline:none;background:none;color:inherit;border:none;border-radius:4px;padding:8px 15px;box-shadow:none;transition:all .3s}.ngx-time-picker--footer button:not([disabled]):hover{cursor:pointer;background:#816ef175}.ngx-time-picker_format{display:flex;flex-direction:column;margin:0 15px;gap:5px}.ngx-time-picker_format button{all:unset;opacity:.4;cursor:pointer}.ngx-time-picker_format button.active{opacity:1}\n"] }]
390
+ }], ctorParameters: () => [], propDecorators: { change: [{ type: i0.Output, args: ["change"] }], cancel: [{ type: i0.Output, args: ["cancel"] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], amOrPm: [{ type: i0.Input, args: [{ isSignal: true, alias: "amOrPm", required: false }] }, { type: i0.Output, args: ["amOrPmChange"] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], autoSwitchToMinute: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoSwitchToMinute", required: false }] }], clock: [{ type: i0.ViewChild, args: ['clock', { isSignal: true }] }] } });
391
+
392
+ class NgxInputTimePicker {
393
+ el;
394
+ config = inject(NGX_TIME_PICKER_CONFIG);
395
+ openOnCLick = input(true, /* @ts-ignore */
396
+ ...(ngDevMode ? [{ debugName: "openOnCLick" }] : /* istanbul ignore next */ []));
397
+ change = output();
398
+ value = signal('', /* @ts-ignore */
399
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
400
+ format = input(this.config.format, /* @ts-ignore */
401
+ ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
402
+ amOrPm = model(/* @ts-ignore */
403
+ ...(ngDevMode ? [undefined, { debugName: "amOrPm" }] : /* istanbul ignore next */ []));
404
+ pickerRef;
405
+ _onChange = (value) => { };
406
+ _onTouched = () => { };
407
+ _validatorOnChange = () => { };
408
+ isDisabled = false;
409
+ overlayService = inject(OverlayService);
410
+ viewContainerRef = inject(ViewContainerRef);
411
+ renderer = inject(Renderer2);
412
+ constructor(el) {
413
+ this.el = el;
414
+ }
415
+ ngOnDestroy() {
416
+ this.destroy();
417
+ }
418
+ onClick(ev) {
419
+ if (this.openOnCLick() && !this.isDisabled) {
420
+ ev.stopPropagation();
421
+ ev.preventDefault();
422
+ this.toggle();
423
+ }
424
+ }
425
+ onInput(event) {
426
+ const input = event.target;
427
+ this.value.set(input.value ?? '');
428
+ this._formatValue();
429
+ this._onChange(this.value());
430
+ }
431
+ onBlur() {
432
+ this._onTouched();
433
+ }
434
+ writeValue(value) {
435
+ this.value.set(value);
436
+ this._formatValue();
437
+ }
438
+ registerOnChange(fn) {
439
+ this._onChange = fn;
440
+ }
441
+ registerOnTouched(fn) {
442
+ this._onTouched = fn;
443
+ }
444
+ registerOnValidatorChange(fn) {
445
+ this._validatorOnChange = fn;
446
+ }
447
+ setDisabledState(disabled) {
448
+ this.isDisabled = disabled;
449
+ if (disabled) {
450
+ this.renderer.setProperty(this.el.nativeElement, 'disabled', disabled);
451
+ }
452
+ else {
453
+ this.renderer.removeAttribute(this.el.nativeElement, 'disabled');
454
+ }
455
+ }
456
+ toggle() {
457
+ if (this.pickerRef || this.isDisabled) {
458
+ this.destroy();
459
+ return;
460
+ }
461
+ this.pickerRef = this.overlayService.open({
462
+ anchor: this.el.nativeElement,
463
+ component: NgxInputTimePickerComponent,
464
+ viewContainerRef: this.viewContainerRef,
465
+ alignment: 'center',
466
+ placement: 'bottom',
467
+ margin: 2,
468
+ configure: (instance, ref) => {
469
+ instance.writeValue(this.value());
470
+ instance.amOrPm.set(this.amOrPm());
471
+ instance.change.subscribe((c) => {
472
+ this.value.set(c ?? '');
473
+ this.emitChange();
474
+ this.destroy();
475
+ });
476
+ instance.cancel.subscribe(() => ref.close());
477
+ },
478
+ onClosed: () => {
479
+ this.pickerRef = undefined;
480
+ },
481
+ });
482
+ }
483
+ destroy() {
484
+ this.pickerRef?.close();
485
+ this.pickerRef = undefined;
486
+ }
487
+ async emitChange() {
488
+ this._onChange(this.value());
489
+ this._formatValue();
490
+ this.change.emit(this.value());
491
+ this._onTouched();
492
+ }
493
+ validate(control) {
494
+ return null;
495
+ }
496
+ _formatValue() {
497
+ const s = this.value().split(':');
498
+ if (this.format() == '12') {
499
+ if (+s[0] > 12) {
500
+ s[0] = (+s[0] - 12).toString().padStart(2, '0');
501
+ this.amOrPm.set('PM');
502
+ }
503
+ else {
504
+ this.amOrPm.set('AM');
505
+ }
506
+ }
507
+ this.value.set(s.join(':') + ' ' + this.amOrPm());
508
+ this.renderer.setProperty(this.el.nativeElement, 'value', this.value());
509
+ }
510
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxInputTimePicker, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
511
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.4", type: NgxInputTimePicker, isStandalone: true, selector: "[ngxInputTimePicker]", inputs: { openOnCLick: { classPropertyName: "openOnCLick", publicName: "openOnCLick", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, amOrPm: { classPropertyName: "amOrPm", publicName: "amOrPm", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { change: "change", amOrPm: "amOrPmChange" }, host: { listeners: { "click": "onClick($event)", "input": "onInput($event)", "blur": "onBlur()" }, properties: { "attr.readOnly": "true" }, classAttribute: "ngx-datepicker-input" }, providers: [
512
+ {
513
+ provide: NG_VALUE_ACCESSOR,
514
+ useExisting: forwardRef(() => NgxInputTimePicker),
515
+ multi: true,
516
+ },
517
+ {
518
+ provide: NG_VALIDATORS,
519
+ useExisting: forwardRef(() => NgxInputTimePicker),
520
+ multi: true,
521
+ },
522
+ ], exportAs: ["ngxInputTimePicker"], ngImport: i0 });
523
+ }
524
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxInputTimePicker, decorators: [{
525
+ type: Directive,
526
+ args: [{
527
+ selector: '[ngxInputTimePicker]',
528
+ exportAs: 'ngxInputTimePicker',
529
+ host: {
530
+ class: 'ngx-datepicker-input',
531
+ '[attr.readOnly]': 'true',
532
+ },
533
+ providers: [
534
+ {
535
+ provide: NG_VALUE_ACCESSOR,
536
+ useExisting: forwardRef(() => NgxInputTimePicker),
537
+ multi: true,
538
+ },
539
+ {
540
+ provide: NG_VALIDATORS,
541
+ useExisting: forwardRef(() => NgxInputTimePicker),
542
+ multi: true,
543
+ },
544
+ ],
545
+ }]
546
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { openOnCLick: [{ type: i0.Input, args: [{ isSignal: true, alias: "openOnCLick", required: false }] }], change: [{ type: i0.Output, args: ["change"] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], amOrPm: [{ type: i0.Input, args: [{ isSignal: true, alias: "amOrPm", required: false }] }, { type: i0.Output, args: ["amOrPmChange"] }], onClick: [{
547
+ type: HostListener,
548
+ args: ['click', ['$event']]
549
+ }], onInput: [{
550
+ type: HostListener,
551
+ args: ['input', ['$event']]
552
+ }], onBlur: [{
553
+ type: HostListener,
554
+ args: ['blur']
555
+ }] } });
556
+
557
+ /**
558
+ * Generated bundle index. Do not edit.
559
+ */
560
+
561
+ export { NgxInputTimePicker, NgxInputTimePickerComponent };
562
+ //# sourceMappingURL=ngx-kit-time-picker.mjs.map