ngx-kit 5.0.0 → 6.0.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 (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 +602 -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 +149 -0
@@ -0,0 +1,602 @@
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
+ function normalizeTime(value) {
22
+ const match = value.match(/^(\d{1,2}):(\d{2})$/);
23
+ if (!match) {
24
+ return null;
25
+ }
26
+ const hour = Number(match[1]);
27
+ const minute = Number(match[2]);
28
+ if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
29
+ return null;
30
+ }
31
+ return [hour.toString().padStart(2, '0'), minute.toString().padStart(2, '0')].join(':');
32
+ }
33
+
34
+ class NgxInputTimePickerComponent {
35
+ browserService = inject(BrowserService);
36
+ change = output();
37
+ cancel = output();
38
+ config = inject(NGX_TIME_PICKER_CONFIG);
39
+ isDisabled = false;
40
+ /**
41
+ * Time value.
42
+ *
43
+ * Example:
44
+ * 14:35
45
+ */
46
+ value = model('12:00', /* @ts-ignore */
47
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
48
+ /**
49
+ * 12h or 24h.
50
+ */
51
+ format = input(this.config.format, /* @ts-ignore */
52
+ ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
53
+ /**
54
+ * Minute step.
55
+ */
56
+ minuteStep = input(this.config.minuteStep, /* @ts-ignore */
57
+ ...(ngDevMode ? [{ debugName: "minuteStep" }] : /* istanbul ignore next */ []));
58
+ /**
59
+ * Whether the clock is disabled.
60
+ */
61
+ disabled = input(false, /* @ts-ignore */
62
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
63
+ /**
64
+ * Whether to automatically switch from hour to minute.
65
+ */
66
+ autoSwitchToMinute = input(this.config.autoSwitchToMinute, /* @ts-ignore */
67
+ ...(ngDevMode ? [{ debugName: "autoSwitchToMinute" }] : /* istanbul ignore next */ []));
68
+ clock = viewChild('clock', /* @ts-ignore */
69
+ ...(ngDevMode ? [{ debugName: "clock" }] : /* istanbul ignore next */ []));
70
+ mode = signal('hour', /* @ts-ignore */
71
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
72
+ dragging = false;
73
+ parsedTime = computed(() => {
74
+ const value = this.value();
75
+ const [hour, minute] = value.split(':').map(Number);
76
+ return {
77
+ hour: Number.isFinite(hour) ? hour : 12,
78
+ minute: Number.isFinite(minute) ? minute : 0,
79
+ };
80
+ }, /* @ts-ignore */
81
+ ...(ngDevMode ? [{ debugName: "parsedTime" }] : /* istanbul ignore next */ []));
82
+ displayHour = computed(() => {
83
+ const { hour } = this.parsedTime();
84
+ if (this.format() === '12') {
85
+ const h = hour % 12;
86
+ return h === 0 ? 12 : h;
87
+ }
88
+ return hour;
89
+ }, /* @ts-ignore */
90
+ ...(ngDevMode ? [{ debugName: "displayHour" }] : /* istanbul ignore next */ []));
91
+ isPm = computed(() => {
92
+ const hour = Number(this.value().split(':')[0]);
93
+ return hour >= 12;
94
+ }, /* @ts-ignore */
95
+ ...(ngDevMode ? [{ debugName: "isPm" }] : /* istanbul ignore next */ []));
96
+ displayMinute = computed(() => {
97
+ return this.parsedTime().minute;
98
+ }, /* @ts-ignore */
99
+ ...(ngDevMode ? [{ debugName: "displayMinute" }] : /* istanbul ignore next */ []));
100
+ hourNumbers = computed(() => {
101
+ if (this.format() === '24') {
102
+ return Array.from({ length: 24 }, (_, i) => i);
103
+ }
104
+ return Array.from({ length: 12 }, (_, i) => i + 1);
105
+ }, /* @ts-ignore */
106
+ ...(ngDevMode ? [{ debugName: "hourNumbers" }] : /* istanbul ignore next */ []));
107
+ minuteNumbers = computed(() => {
108
+ const step = Math.max(1, 5);
109
+ const values = [];
110
+ for (let i = 0; i < 60; i += step) {
111
+ values.push(i);
112
+ }
113
+ return values;
114
+ }, /* @ts-ignore */
115
+ ...(ngDevMode ? [{ debugName: "minuteNumbers" }] : /* istanbul ignore next */ []));
116
+ hourAngle = computed(() => {
117
+ const { hour } = this.parsedTime();
118
+ if (this.format() === '24') {
119
+ /*
120
+ * MUI-like 24 hour clock.
121
+ *
122
+ * 0 -> 0°
123
+ * 6 -> 90°
124
+ * 12 -> 180°
125
+ * 18 -> 270°
126
+ */
127
+ return (hour % 12) * 30;
128
+ }
129
+ const h = hour % 12;
130
+ return h * 30;
131
+ }, /* @ts-ignore */
132
+ ...(ngDevMode ? [{ debugName: "hourAngle" }] : /* istanbul ignore next */ []));
133
+ minuteAngle = computed(() => {
134
+ return this.parsedTime().minute * 6;
135
+ }, /* @ts-ignore */
136
+ ...(ngDevMode ? [{ debugName: "minuteAngle" }] : /* istanbul ignore next */ []));
137
+ currentAngle = computed(() => {
138
+ return this.mode() === 'hour' ? this.hourAngle() : this.minuteAngle();
139
+ }, /* @ts-ignore */
140
+ ...(ngDevMode ? [{ debugName: "currentAngle" }] : /* istanbul ignore next */ []));
141
+ handLength = computed(() => {
142
+ if (this.mode() === 'hour' && this.format() === '24') {
143
+ const hour = this.parsedTime().hour;
144
+ if (hour >= 13 && hour <= 23) {
145
+ return 58;
146
+ }
147
+ }
148
+ return 86;
149
+ }, /* @ts-ignore */
150
+ ...(ngDevMode ? [{ debugName: "handLength" }] : /* istanbul ignore next */ []));
151
+ hourRadius = computed(() => {
152
+ if (this.mode() !== 'hour') {
153
+ return 94;
154
+ }
155
+ if (this.format() !== '24') {
156
+ return 94;
157
+ }
158
+ const hour = this.parsedTime().hour;
159
+ // 00, 13..23 → inner ring
160
+ if (hour === 0 || hour >= 13) {
161
+ return 58;
162
+ }
163
+ // 01..12 → outer ring
164
+ return 94;
165
+ }, /* @ts-ignore */
166
+ ...(ngDevMode ? [{ debugName: "hourRadius" }] : /* istanbul ignore next */ []));
167
+ selectedPosition = computed(() => {
168
+ const angle = this.currentAngle();
169
+ const radians = ((angle - 90) * Math.PI) / 180;
170
+ const radius = this.mode() === 'hour' ? this.hourRadius() : 94;
171
+ return {
172
+ x: 120 + Math.cos(radians) * radius,
173
+ y: 120 + Math.sin(radians) * radius,
174
+ };
175
+ }, /* @ts-ignore */
176
+ ...(ngDevMode ? [{ debugName: "selectedPosition" }] : /* istanbul ignore next */ []));
177
+ handEnd = computed(() => {
178
+ const angle = this.currentAngle();
179
+ const radians = ((angle - 90) * Math.PI) / 180;
180
+ const radius = this.mode() === 'hour' ? this.hourRadius() : 94;
181
+ return {
182
+ x: 120 + Math.cos(radians) * radius,
183
+ y: 120 + Math.sin(radians) * radius,
184
+ };
185
+ }, /* @ts-ignore */
186
+ ...(ngDevMode ? [{ debugName: "handEnd" }] : /* istanbul ignore next */ []));
187
+ _onChange = (value) => { };
188
+ _onTouched = () => { };
189
+ _validatorOnChange = () => { };
190
+ constructor() { }
191
+ ngOnInit() { }
192
+ writeValue(value) {
193
+ if (!value) {
194
+ this.value.set('12:00');
195
+ return;
196
+ }
197
+ const normalized = normalizeTime(value);
198
+ if (normalized === null) {
199
+ // invalid value
200
+ return;
201
+ }
202
+ this.value.set(normalized);
203
+ }
204
+ validate(control) {
205
+ return null;
206
+ }
207
+ registerOnChange(fn) {
208
+ this._onChange = fn;
209
+ }
210
+ registerOnTouched(fn) {
211
+ this._onTouched = fn;
212
+ }
213
+ registerOnValidatorChange(fn) {
214
+ this._validatorOnChange = fn;
215
+ }
216
+ setDisabledState(disabled) {
217
+ this.isDisabled = disabled;
218
+ }
219
+ startPointer(event) {
220
+ if (this.disabled()) {
221
+ return;
222
+ }
223
+ event.preventDefault();
224
+ this.dragging = true;
225
+ const target = event.currentTarget;
226
+ target.setPointerCapture?.(event.pointerId);
227
+ this.updateFromPointer(event);
228
+ }
229
+ movePointer(event) {
230
+ if (!this.dragging || this.disabled()) {
231
+ return;
232
+ }
233
+ event.preventDefault();
234
+ this.updateFromPointer(event);
235
+ }
236
+ endPointer(event) {
237
+ if (!this.dragging) {
238
+ return;
239
+ }
240
+ this.dragging = false;
241
+ const target = event.currentTarget;
242
+ target.releasePointerCapture?.(event.pointerId);
243
+ if (this.mode() === 'hour' && this.autoSwitchToMinute()) {
244
+ this.mode.set('minute');
245
+ }
246
+ }
247
+ selectHour(hour) {
248
+ if (this.disabled()) {
249
+ return;
250
+ }
251
+ let normalizedHour = hour;
252
+ if (this.format() === '12') {
253
+ const currentHour = this.parsedTime().hour;
254
+ const isPm = currentHour >= 12;
255
+ normalizedHour = hour === 12 ? (isPm ? 12 : 0) : isPm ? hour + 12 : hour;
256
+ }
257
+ this.setTime(normalizedHour, this.parsedTime().minute);
258
+ if (this.autoSwitchToMinute()) {
259
+ this.mode.set('minute');
260
+ }
261
+ }
262
+ selectMinute(minute) {
263
+ if (this.disabled()) {
264
+ return;
265
+ }
266
+ this.setTime(this.parsedTime().hour, minute);
267
+ }
268
+ setMode(mode) {
269
+ if (!this.disabled()) {
270
+ this.mode.set(mode);
271
+ }
272
+ }
273
+ updateFromPointer(event) {
274
+ const svg = this.clock()?.nativeElement;
275
+ if (!svg) {
276
+ return;
277
+ }
278
+ const rect = svg.getBoundingClientRect();
279
+ const x = ((event.clientX - rect.left) / rect.width) * 240;
280
+ const y = ((event.clientY - rect.top) / rect.height) * 240;
281
+ if (this.mode() === 'hour') {
282
+ this.updateHourFromPointer(x, y);
283
+ return;
284
+ }
285
+ this.updateMinuteFromPointer(x, y);
286
+ }
287
+ updateHourFromPointer(x, y) {
288
+ const dx = x - 120;
289
+ const dy = y - 120;
290
+ const distance = Math.sqrt(dx * dx + dy * dy);
291
+ let angle = (Math.atan2(dy, dx) * 180) / Math.PI + 90;
292
+ if (angle < 0) {
293
+ angle += 360;
294
+ }
295
+ let hour = Math.round(angle / 30) % 12;
296
+ if (this.format() === '12') {
297
+ hour = hour === 0 ? 12 : hour;
298
+ this.setTime(hour, this.parsedTime().minute);
299
+ return;
300
+ }
301
+ /*
302
+ * 24 hour mode
303
+ *
304
+ * Outer ring:
305
+ * 1 ... 12
306
+ *
307
+ * Inner ring:
308
+ * 13 ... 23, 00
309
+ */
310
+ const INNER_RING_THRESHOLD = 76;
311
+ const isInnerRing = distance < INNER_RING_THRESHOLD;
312
+ if (isInnerRing) {
313
+ /*
314
+ * Inner ring:
315
+ *
316
+ * 12 position -> 00
317
+ * 1 position -> 13
318
+ * 2 position -> 14
319
+ * ...
320
+ * 11 position -> 23
321
+ */
322
+ hour = hour === 0 ? 0 : hour + 12;
323
+ }
324
+ else {
325
+ /*
326
+ * Outer ring:
327
+ *
328
+ * 12 position -> 12
329
+ * 1 ... 11 -> 1 ... 11
330
+ */
331
+ hour = hour === 0 ? 12 : hour;
332
+ }
333
+ this.setTime(hour, this.parsedTime().minute);
334
+ }
335
+ updateMinuteFromPointer(x, y) {
336
+ const dx = x - 120;
337
+ const dy = y - 120;
338
+ let angle = (Math.atan2(dy, dx) * 180) / Math.PI + 90;
339
+ if (angle < 0) {
340
+ angle += 360;
341
+ }
342
+ let minute = Math.round(angle / 6);
343
+ minute %= 60;
344
+ const step = Math.max(1, this.minuteStep());
345
+ minute = Math.round(minute / step) * step;
346
+ if (minute >= 60) {
347
+ minute = 0;
348
+ }
349
+ this.setTime(this.parsedTime().hour, minute);
350
+ }
351
+ setTime(hour, minute) {
352
+ const h = String(hour).padStart(2, '0');
353
+ const m = String(minute).padStart(2, '0');
354
+ this.value.set(`${h}:${m}`);
355
+ }
356
+ formatHour(hour) {
357
+ if (this.format() === '24') {
358
+ return String(hour).padStart(2, '0');
359
+ }
360
+ return String(hour);
361
+ }
362
+ formatMinute(minute) {
363
+ return String(minute).padStart(2, '0');
364
+ }
365
+ numberPosition(index, total, radius = 94) {
366
+ const angle = (index / total) * 360 - 90;
367
+ const radians = (angle * Math.PI) / 180;
368
+ return {
369
+ x: 120 + Math.cos(radians) * radius,
370
+ y: 120 + Math.sin(radians) * radius,
371
+ };
372
+ }
373
+ hourPosition(hour, inner = false) {
374
+ const normalized = hour % 12;
375
+ const angle = normalized * 30 - 90;
376
+ const radians = (angle * Math.PI) / 180;
377
+ const radius = inner ? 58 : 94;
378
+ return {
379
+ x: 120 + Math.cos(radians) * radius,
380
+ y: 120 + Math.sin(radians) * radius,
381
+ };
382
+ }
383
+ minutePosition(minute) {
384
+ const angle = minute * 6 - 90;
385
+ const radians = (angle * Math.PI) / 180;
386
+ return {
387
+ x: 120 + Math.cos(radians) * 94,
388
+ y: 120 + Math.sin(radians) * 94,
389
+ };
390
+ }
391
+ togglePmAm(val) {
392
+ const [hour, minute] = this.value().split(':').map(Number);
393
+ let newHour = hour;
394
+ if (val === 'AM') {
395
+ // 12:xx PM → 00:xx
396
+ if (hour >= 12) {
397
+ newHour = hour - 12;
398
+ }
399
+ }
400
+ else {
401
+ // 00:xx AM → 12:xx PM
402
+ if (hour < 12) {
403
+ newHour = hour + 12;
404
+ }
405
+ }
406
+ const value = `${String(newHour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
407
+ this.value.set(value);
408
+ }
409
+ ok() {
410
+ this.change.emit(this.value());
411
+ this._onChange(this.value());
412
+ }
413
+ close() {
414
+ this.cancel.emit();
415
+ }
416
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxInputTimePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
417
+ 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 }, 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" }, providers: [
418
+ {
419
+ provide: NG_VALUE_ACCESSOR,
420
+ useExisting: forwardRef(() => NgxInputTimePickerComponent),
421
+ multi: true,
422
+ },
423
+ {
424
+ provide: NG_VALIDATORS,
425
+ useExisting: forwardRef(() => NgxInputTimePickerComponent),
426
+ multi: true,
427
+ },
428
+ ], 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]=\"!isPm()\" (click)=\"togglePmAm('AM')\">\n {{ config.amText }}\n </button>\n <button [class.active]=\"isPm()\" (click)=\"togglePmAm('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 || hour == 0)) {\n <g class=\"clock-number clock-number--inner\" (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 {{ hour == 0 ? '00' : hour }}\n </text>\n </g>\n } @else {\n <g\n class=\"clock-number\"\n [class.selected]=\"displayHour() == 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 {{ 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]=\"displayMinute() == 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:300px;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}.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 text{fill:#000;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 px;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 }] });
429
+ }
430
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxInputTimePickerComponent, decorators: [{
431
+ type: Component,
432
+ args: [{ selector: 'ngx-time-picker', imports: [CommonModule], providers: [
433
+ {
434
+ provide: NG_VALUE_ACCESSOR,
435
+ useExisting: forwardRef(() => NgxInputTimePickerComponent),
436
+ multi: true,
437
+ },
438
+ {
439
+ provide: NG_VALIDATORS,
440
+ useExisting: forwardRef(() => NgxInputTimePickerComponent),
441
+ multi: true,
442
+ },
443
+ ], 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]=\"!isPm()\" (click)=\"togglePmAm('AM')\">\n {{ config.amText }}\n </button>\n <button [class.active]=\"isPm()\" (click)=\"togglePmAm('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 || hour == 0)) {\n <g class=\"clock-number clock-number--inner\" (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 {{ hour == 0 ? '00' : hour }}\n </text>\n </g>\n } @else {\n <g\n class=\"clock-number\"\n [class.selected]=\"displayHour() == 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 {{ 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]=\"displayMinute() == 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:300px;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}.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 text{fill:#000;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 px;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"] }]
444
+ }], 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 }] }], 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 }] }] } });
445
+
446
+ class NgxInputTimePicker {
447
+ el;
448
+ config = inject(NGX_TIME_PICKER_CONFIG);
449
+ openOnCLick = input(true, /* @ts-ignore */
450
+ ...(ngDevMode ? [{ debugName: "openOnCLick" }] : /* istanbul ignore next */ []));
451
+ change = output();
452
+ value = signal('', /* @ts-ignore */
453
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
454
+ format = input(this.config.format, /* @ts-ignore */
455
+ ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
456
+ pickerRef;
457
+ _onChange = (value) => { };
458
+ _onTouched = () => { };
459
+ _validatorOnChange = () => { };
460
+ isDisabled = false;
461
+ overlayService = inject(OverlayService);
462
+ viewContainerRef = inject(ViewContainerRef);
463
+ renderer = inject(Renderer2);
464
+ constructor(el) {
465
+ this.el = el;
466
+ }
467
+ ngOnDestroy() {
468
+ this.destroy();
469
+ }
470
+ onClick(ev) {
471
+ if (this.openOnCLick() && !this.isDisabled) {
472
+ ev.stopPropagation();
473
+ ev.preventDefault();
474
+ this.toggle();
475
+ }
476
+ }
477
+ onInput(event) {
478
+ const input = event.target;
479
+ this.value.set(input.value ?? '');
480
+ this._formatValue();
481
+ this._onChange(this.value());
482
+ }
483
+ onBlur() {
484
+ this._onTouched();
485
+ }
486
+ writeValue(value) {
487
+ this.value.set(value);
488
+ this._formatValue();
489
+ }
490
+ registerOnChange(fn) {
491
+ this._onChange = fn;
492
+ }
493
+ registerOnTouched(fn) {
494
+ this._onTouched = fn;
495
+ }
496
+ registerOnValidatorChange(fn) {
497
+ this._validatorOnChange = fn;
498
+ }
499
+ setDisabledState(disabled) {
500
+ this.isDisabled = disabled;
501
+ if (disabled) {
502
+ this.renderer.setProperty(this.el.nativeElement, 'disabled', disabled);
503
+ }
504
+ else {
505
+ this.renderer.removeAttribute(this.el.nativeElement, 'disabled');
506
+ }
507
+ }
508
+ toggle() {
509
+ if (this.pickerRef || this.isDisabled) {
510
+ this.destroy();
511
+ return;
512
+ }
513
+ this.pickerRef = this.overlayService.open({
514
+ anchor: this.el.nativeElement,
515
+ component: NgxInputTimePickerComponent,
516
+ viewContainerRef: this.viewContainerRef,
517
+ alignment: 'center',
518
+ placement: 'bottom',
519
+ margin: 2,
520
+ configure: (instance, ref) => {
521
+ instance.writeValue(this.value());
522
+ instance.change.subscribe((c) => {
523
+ this.value.set(c ?? '');
524
+ this.emitChange();
525
+ this.destroy();
526
+ });
527
+ instance.cancel.subscribe(() => ref.close());
528
+ },
529
+ onClosed: () => {
530
+ this.pickerRef = undefined;
531
+ },
532
+ });
533
+ }
534
+ destroy() {
535
+ this.pickerRef?.close();
536
+ this.pickerRef = undefined;
537
+ }
538
+ async emitChange() {
539
+ this._onChange(this.value());
540
+ this._formatValue();
541
+ this.change.emit(this.value());
542
+ this._onTouched();
543
+ }
544
+ validate(control) {
545
+ return null;
546
+ }
547
+ _formatValue() {
548
+ this.renderer.setProperty(this.el.nativeElement, 'value', this.value());
549
+ }
550
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxInputTimePicker, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
551
+ 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 } }, outputs: { change: "change" }, host: { listeners: { "click": "onClick($event)", "input": "onInput($event)", "blur": "onBlur()" }, properties: { "attr.readOnly": "true" }, classAttribute: "ngx-datepicker-input" }, providers: [
552
+ {
553
+ provide: NG_VALUE_ACCESSOR,
554
+ useExisting: forwardRef(() => NgxInputTimePicker),
555
+ multi: true,
556
+ },
557
+ {
558
+ provide: NG_VALIDATORS,
559
+ useExisting: forwardRef(() => NgxInputTimePicker),
560
+ multi: true,
561
+ },
562
+ ], exportAs: ["ngxInputTimePicker"], ngImport: i0 });
563
+ }
564
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxInputTimePicker, decorators: [{
565
+ type: Directive,
566
+ args: [{
567
+ selector: '[ngxInputTimePicker]',
568
+ exportAs: 'ngxInputTimePicker',
569
+ host: {
570
+ class: 'ngx-datepicker-input',
571
+ '[attr.readOnly]': 'true',
572
+ },
573
+ providers: [
574
+ {
575
+ provide: NG_VALUE_ACCESSOR,
576
+ useExisting: forwardRef(() => NgxInputTimePicker),
577
+ multi: true,
578
+ },
579
+ {
580
+ provide: NG_VALIDATORS,
581
+ useExisting: forwardRef(() => NgxInputTimePicker),
582
+ multi: true,
583
+ },
584
+ ],
585
+ }]
586
+ }], 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 }] }], onClick: [{
587
+ type: HostListener,
588
+ args: ['click', ['$event']]
589
+ }], onInput: [{
590
+ type: HostListener,
591
+ args: ['input', ['$event']]
592
+ }], onBlur: [{
593
+ type: HostListener,
594
+ args: ['blur']
595
+ }] } });
596
+
597
+ /**
598
+ * Generated bundle index. Do not edit.
599
+ */
600
+
601
+ export { NgxInputTimePicker, NgxInputTimePickerComponent };
602
+ //# sourceMappingURL=ngx-kit-time-picker.mjs.map