@klippa/ngx-enhancy-forms 4.0.0 → 5.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 (39) hide show
  1. package/bundles/klippa-ngx-enhancy-forms.umd.js +547 -90
  2. package/bundles/klippa-ngx-enhancy-forms.umd.js.map +1 -1
  3. package/bundles/klippa-ngx-enhancy-forms.umd.min.js +2 -2
  4. package/bundles/klippa-ngx-enhancy-forms.umd.min.js.map +1 -1
  5. package/esm2015/lib/elements/date-picker/date-picker.component.js +92 -0
  6. package/esm2015/lib/elements/date-time-picker/date-time-picker.component.js +311 -0
  7. package/esm2015/lib/elements/email/email-input.component.js +2 -2
  8. package/esm2015/lib/elements/password-field/password-field.component.js +6 -4
  9. package/esm2015/lib/elements/select/select-footer/select-footer.component.js +15 -0
  10. package/esm2015/lib/elements/select/select.component.js +30 -9
  11. package/esm2015/lib/elements/sortable-items/sortable-items.component.js +46 -4
  12. package/esm2015/lib/elements/text-input/text-input.component.js +7 -4
  13. package/esm2015/lib/elements/value-accessor-base/multiple-value-accessor-base.component.js +63 -0
  14. package/esm2015/lib/elements/value-accessor-base/value-accessor-base.component.js +3 -3
  15. package/esm2015/lib/form/form-element/form-element.component.js +13 -15
  16. package/esm2015/lib/form/form.component.js +21 -5
  17. package/esm2015/lib/ngx-enhancy-forms.module.js +13 -4
  18. package/esm2015/lib/util/values.js +8 -17
  19. package/esm2015/public-api.js +5 -2
  20. package/fesm2015/klippa-ngx-enhancy-forms.js +512 -78
  21. package/fesm2015/klippa-ngx-enhancy-forms.js.map +1 -1
  22. package/klippa-ngx-enhancy-forms.metadata.json +1 -1
  23. package/lib/elements/date-picker/date-picker.component.d.ts +23 -0
  24. package/lib/elements/date-time-picker/date-time-picker.component.d.ts +59 -0
  25. package/lib/elements/email/email-input.component.d.ts +1 -1
  26. package/lib/elements/password-field/password-field.component.d.ts +2 -1
  27. package/lib/elements/select/select-footer/select-footer.component.d.ts +4 -0
  28. package/lib/elements/select/select.component.d.ts +12 -4
  29. package/lib/elements/sortable-items/sortable-items.component.d.ts +12 -2
  30. package/lib/elements/text-input/text-input.component.d.ts +2 -0
  31. package/lib/elements/value-accessor-base/multiple-value-accessor-base.component.d.ts +11 -0
  32. package/lib/elements/value-accessor-base/value-accessor-base.component.d.ts +2 -1
  33. package/lib/form/form-element/form-element.component.d.ts +5 -5
  34. package/lib/form/form.component.d.ts +2 -0
  35. package/lib/util/values.d.ts +2 -4
  36. package/package.json +1 -1
  37. package/public-api.d.ts +4 -1
  38. package/esm2015/lib/elements/datepicker/datepicker.component.js +0 -111
  39. package/lib/elements/datepicker/datepicker.component.d.ts +0 -26
@@ -1,10 +1,10 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('@angular/forms'), require('lodash'), require('ngx-sortablejs'), require('@ng-select/ng-select'), require('@angular/material/core'), require('@angular/material/datepicker'), require('@angular/material/form-field'), require('@angular/material/input'), require('@angular/material/button')) :
3
- typeof define === 'function' && define.amd ? define('@klippa/ngx-enhancy-forms', ['exports', '@angular/core', '@angular/common', '@angular/forms', 'lodash', 'ngx-sortablejs', '@ng-select/ng-select', '@angular/material/core', '@angular/material/datepicker', '@angular/material/form-field', '@angular/material/input', '@angular/material/button'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.klippa = global.klippa || {}, global.klippa["ngx-enhancy-forms"] = {}), global.ng.core, global.ng.common, global.ng.forms, global.lodash, global.ngxSortablejs, global.ngSelect, global.ng.material.core, global.ng.material.datepicker, global.ng.material.formField, global.ng.material.input, global.ng.material.button));
5
- })(this, (function (exports, core, common, forms, lodash, ngxSortablejs, ngSelect, core$1, datepicker, formField, input, button) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('@angular/forms'), require('lodash'), require('ngx-sortablejs'), require('@ng-select/ng-select'), require('date-fns'), require('@angular/material/core'), require('@angular/material/datepicker'), require('@angular/material/form-field'), require('@angular/material/input'), require('@angular/material/button')) :
3
+ typeof define === 'function' && define.amd ? define('@klippa/ngx-enhancy-forms', ['exports', '@angular/core', '@angular/common', '@angular/forms', 'lodash', 'ngx-sortablejs', '@ng-select/ng-select', 'date-fns', '@angular/material/core', '@angular/material/datepicker', '@angular/material/form-field', '@angular/material/input', '@angular/material/button'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.klippa = global.klippa || {}, global.klippa["ngx-enhancy-forms"] = {}), global.ng.core, global.ng.common, global.ng.forms, global.lodash, global.ngxSortablejs, global.ngSelect, global.dateFns, global.ng.material.core, global.ng.material.datepicker, global.ng.material.formField, global.ng.material.input, global.ng.material.button));
5
+ })(this, (function (exports, core, common, forms, lodash, ngxSortablejs, ngSelect, dateFns, core$1, datepicker, formField, input, button) { 'use strict';
6
6
 
7
- function stringIsSetAndNotEmpty(s) {
7
+ function stringIsSetAndFilled(s) {
8
8
  return lodash.isString(s) && s.length > 0;
9
9
  }
10
10
  function isNullOrUndefined(value) {
@@ -16,24 +16,15 @@
16
16
  function isValueSet(value) {
17
17
  return value !== null && value !== undefined;
18
18
  }
19
+ function removeDuplicatesFromArray(array) {
20
+ return array.filter(function (c, i) {
21
+ var firstOccurrenceIndex = array.findIndex(function (c2) { return c2 === c; });
22
+ return i === firstOccurrenceIndex;
23
+ });
24
+ }
19
25
  function stringOrArrayIsSetAndEmpty(value) {
20
26
  return value !== null && value !== undefined && value.length === 0;
21
27
  }
22
- function useIfStringIsSet(s) {
23
- if (stringIsSetAndNotEmpty(s)) {
24
- return s;
25
- }
26
- return undefined;
27
- }
28
- function useIfArrayIsSetWithOneItem(a) {
29
- if (!isNullOrUndefined(a) && a.length === 1) {
30
- return a[0];
31
- }
32
- return undefined;
33
- }
34
- function convertParentToChild(originalClass, newClass) {
35
- return Object.assign(newClass, originalClass);
36
- }
37
28
  function truncateString(s, length) {
38
29
  if (s.length < length) {
39
30
  return s;
@@ -69,18 +60,21 @@
69
60
  var injectInto = this.subFormPlaceholder.injectInto;
70
61
  var injectAt = this.subFormPlaceholder.at;
71
62
  if (injectInto instanceof forms.FormArray) {
72
- if (typeof injectAt !== "number") {
63
+ if (typeof injectAt !== 'number') {
73
64
  throw new Error("cannot index FormArray with " + typeof injectAt);
74
65
  }
75
66
  injectInto.setControl(injectAt, this.formGroup);
76
67
  }
77
68
  else if (injectInto instanceof forms.FormGroup) {
78
- if (typeof injectAt !== "string") {
69
+ if (typeof injectAt !== 'string') {
79
70
  throw new Error("cannot index FormGroup with " + typeof injectAt);
80
71
  }
81
72
  injectInto.setControl(injectAt, this.formGroup);
82
73
  }
83
74
  }
75
+ if (isValueSet(this.patchValueInterceptor)) {
76
+ this.addSupportForPatchValueInterceptor();
77
+ }
84
78
  };
85
79
  FormComponent.prototype.ngOnDestroy = function () {
86
80
  var _this = this;
@@ -92,13 +86,25 @@
92
86
  injectInto.removeAt(idx);
93
87
  }
94
88
  else if (injectInto instanceof forms.FormGroup) {
95
- if (typeof injectAt !== "string") {
89
+ if (typeof injectAt !== 'string') {
96
90
  throw new Error("cannot index FormGroup with " + typeof injectAt);
97
91
  }
98
92
  injectInto.removeControl(injectAt);
99
93
  }
100
94
  }
101
95
  };
96
+ FormComponent.prototype.addSupportForPatchValueInterceptor = function () {
97
+ var _this = this;
98
+ var fn = this.formGroup.patchValue;
99
+ var newFn = function (value, options) {
100
+ _this.patchValueInterceptor(value).then(function (val) {
101
+ setTimeout(function () {
102
+ fn.call(_this.formGroup, val, options);
103
+ });
104
+ });
105
+ };
106
+ this.formGroup.patchValue = newFn;
107
+ };
102
108
  FormComponent.prototype.registerControl = function (formControl, formElement) {
103
109
  this.activeControls.push({ formControl: formControl, formElement: formElement });
104
110
  if (this.parent) {
@@ -155,6 +161,7 @@
155
161
  FormComponent.prototype.trySubmit = function () {
156
162
  var _this = this;
157
163
  var _a, _b;
164
+ this.formGroup.updateValueAndValidity();
158
165
  this.formGroup.markAllAsTouched();
159
166
  var allControls = this.getAllFormControls();
160
167
  var originalDisabledStates = allControls.map(function (e) {
@@ -196,20 +203,21 @@
196
203
  { type: SubFormDirective, decorators: [{ type: core.Optional }] }
197
204
  ]; };
198
205
  FormComponent.propDecorators = {
199
- formGroup: [{ type: core.Input }]
206
+ formGroup: [{ type: core.Input }],
207
+ patchValueInterceptor: [{ type: core.Input }]
200
208
  };
201
209
 
202
210
  var FORM_ERROR_MESSAGES = new core.InjectionToken('form.error.messages');
203
211
  var DEFAULT_ERROR_MESSAGES = {
204
- min: "Use a number larger than %min%",
205
- max: "Use a number smaller than %max%",
206
- required: "This field is required",
207
- email: "Use a valid email address",
208
- minLength: "Has to be longer than %minLength% character(s)",
209
- maxLength: "Has to be shorter than %maxLength% character(s)",
210
- pattern: "This input is not valid",
211
- matchPassword: "Passwords must match",
212
- date: "Enter a valid date",
212
+ min: 'Use a number larger than %min%',
213
+ max: 'Use a number smaller than %max%',
214
+ required: 'This field is required',
215
+ email: 'Use a valid email address',
216
+ minLength: 'Has to be longer than %minLength% character(s)',
217
+ maxLength: 'Has to be shorter than %maxLength% character(s)',
218
+ pattern: 'This input is not valid',
219
+ matchPassword: 'Passwords must match',
220
+ date: 'Enter a valid date',
213
221
  };
214
222
  var FormElementComponent = /** @class */ (function () {
215
223
  function FormElementComponent(parent, customMessages) {
@@ -227,8 +235,6 @@
227
235
  }, message);
228
236
  };
229
237
  FormElementComponent.prototype.registerControl = function (formControl) {
230
- // console.log('register');
231
- // console.log(this.caption);
232
238
  this.attachedControl = formControl;
233
239
  this.parent.registerControl(formControl, this);
234
240
  };
@@ -275,7 +281,7 @@
275
281
  // to give some breathing room, we scroll 100px more to the top
276
282
  (_a = this.getScrollableParent(this.internalComponentRef.nativeElement)) === null || _a === void 0 ? void 0 : _a.scrollBy(0, -100);
277
283
  };
278
- FormElementComponent.prototype.getErrorMessages = function (key) {
284
+ FormElementComponent.prototype.getErrorMessage = function (key) {
279
285
  var _a, _b, _c;
280
286
  return (_c = (_b = (_a = this.customMessages) === null || _a === void 0 ? void 0 : _a[key]) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : this.errorMessages[key];
281
287
  };
@@ -284,7 +290,7 @@
284
290
  FormElementComponent.decorators = [
285
291
  { type: core.Component, args: [{
286
292
  selector: 'klp-form-element',
287
- template: "<ng-template #errorRef>\n\t<div *ngIf=\"getErrorToShow()\" class=\"errorContainer\">\n\t\t<div *ngIf=\"showDefaultError('min')\">{{substituteParameters(getErrorMessages(\"min\"), {min: attachedControl.errors.min.min})}}</div>\n\t\t<div *ngIf=\"showDefaultError('max')\">{{substituteParameters(getErrorMessages(\"max\"), {max: attachedControl.errors.max.max})}}</div>\n\t\t<div *ngIf=\"showDefaultError('required')\">{{getErrorMessages(\"required\")}}</div>\n\t\t<div *ngIf=\"showDefaultError('email')\">{{getErrorMessages(\"email\")}}</div>\n\t\t<div *ngIf=\"showDefaultError('minlength')\">{{substituteParameters(getErrorMessages(\"minLength\"), {minLength: attachedControl.errors.minlength.requiredLength})}}</div>\n\t\t<div *ngIf=\"showDefaultError('maxlength')\">{{substituteParameters(getErrorMessages(\"maxLength\"), {maxLength: attachedControl.errors.maxlength.requiredLength})}}</div>\n\t\t<div *ngIf=\"showDefaultError('pattern')\">{{getErrorMessages(\"pattern\")}}</div>\n\t\t<div *ngIf=\"showDefaultError('MatchPassword')\">{{getErrorMessages(\"matchPassword\")}}</div>\n\t\t<div *ngIf=\"showDefaultError('date')\">{{getErrorMessages(\"date\")}}</div>\n\t\t<div *ngIf=\"showDefaultError('message')\">{{attachedControl.errors.message.value}}</div>\n\t\t<div [ngTemplateOutlet]=\"getCustomErrorHandler(getErrorToShow())?.templateRef\"></div>\n\t</div>\n</ng-template>\n<ng-container *ngIf=\"direction === 'horizontal'\" [ngTemplateOutlet]=\"errorRef\"></ng-container>\n<div *ngIf=\"attachedControl\" class=\"componentContainer\" [ngClass]=\"{vertical: direction === 'vertical', reverseOrder: swapInputAndCaption}\" #internalComponentRef>\n\t<div class=\"caption\" [ngClass]=\"{ hasErrors: getErrorToShow() && attachedControl.touched, percentageSpacing: captionSpacing === 'percentages' }\">\n\t\t<div *ngIf=\"captionRef\" [ngTemplateOutlet]=\"captionRef\"></div>\n\t\t<div *ngIf=\"!captionRef\">{{caption}}</div>\n\t</div>\n\t<ng-container *ngIf=\"direction === 'vertical'\" [ngTemplateOutlet]=\"errorRef\"></ng-container>\n\t<div class=\"inputContainer\" [ngClass]=\"{ percentageSpacing: captionSpacing === 'percentages' }\">\n\t\t<ng-content></ng-content>\n\t</div>\n</div>\n",
293
+ template: "<ng-template #errorRef>\n\t<div *ngIf=\"getErrorToShow()\" class=\"errorContainer\">\n\t\t<div *ngIf=\"showDefaultError('min')\">{{substituteParameters(getErrorMessage(\"min\"), {min: attachedControl.errors.min.min})}}</div>\n\t\t<div *ngIf=\"showDefaultError('max')\">{{substituteParameters(getErrorMessage(\"max\"), {max: attachedControl.errors.max.max})}}</div>\n\t\t<div *ngIf=\"showDefaultError('required')\">{{getErrorMessage(\"required\")}}</div>\n\t\t<div *ngIf=\"showDefaultError('email')\">{{getErrorMessage(\"email\")}}</div>\n\t\t<div *ngIf=\"showDefaultError('minlength')\">{{substituteParameters(getErrorMessage(\"minLength\"), {minLength: attachedControl.errors.minlength.requiredLength})}}</div>\n\t\t<div *ngIf=\"showDefaultError('maxlength')\">{{substituteParameters(getErrorMessage(\"maxLength\"), {maxLength: attachedControl.errors.maxlength.requiredLength})}}</div>\n\t\t<div *ngIf=\"showDefaultError('pattern')\">{{getErrorMessage(\"pattern\")}}</div>\n\t\t<div *ngIf=\"showDefaultError('MatchPassword')\">{{getErrorMessage(\"matchPassword\")}}</div>\n\t\t<div *ngIf=\"showDefaultError('date')\">{{getErrorMessage(\"date\")}}</div>\n\t\t<div *ngIf=\"showDefaultError('message')\">{{attachedControl.errors.message.value}}</div>\n\t\t<div [ngTemplateOutlet]=\"getCustomErrorHandler(getErrorToShow())?.templateRef\"></div>\n\t</div>\n</ng-template>\n<ng-container *ngIf=\"direction === 'horizontal'\" [ngTemplateOutlet]=\"errorRef\"></ng-container>\n<div *ngIf=\"attachedControl\" class=\"componentContainer\" [ngClass]=\"{vertical: direction === 'vertical', reverseOrder: swapInputAndCaption}\" #internalComponentRef>\n\t<div class=\"caption\" [ngClass]=\"{ hasErrors: getErrorToShow() && attachedControl.touched, percentageSpacing: captionSpacing === 'percentages' }\">\n\t\t<div *ngIf=\"captionRef\" [ngTemplateOutlet]=\"captionRef\"></div>\n\t\t<div *ngIf=\"!captionRef\">{{caption}}</div>\n\t</div>\n\t<ng-container *ngIf=\"direction === 'vertical'\" [ngTemplateOutlet]=\"errorRef\"></ng-container>\n\t<div class=\"inputContainer\" [ngClass]=\"{ percentageSpacing: captionSpacing === 'percentages' }\">\n\t\t<ng-content></ng-content>\n\t</div>\n</div>\n",
288
294
  styles: [":host{display:block;margin-top:1.25rem}.componentContainer{align-items:center;display:flex}.componentContainer.reverseOrder{flex-direction:row-reverse;justify-content:flex-end}.componentContainer.vertical{display:block;margin-bottom:1rem}.componentContainer.vertical .inputContainer{margin-top:.3125rem}.componentContainer.vertical .errorContainer{margin-left:0}.caption{color:#515365;flex:0 0 auto;font-weight:700}.caption.percentageSpacing{flex:0 0 40%}.caption.hasErrors{color:#ff8000}.inputContainer{flex:0 0 auto}.inputContainer.percentageSpacing{flex:0 0 60%}.errorContainer{color:#ff8000;margin-left:40%}"]
289
295
  },] }
290
296
  ];
@@ -326,7 +332,7 @@
326
332
  if (this.formControl) {
327
333
  this.attachedFormControl = this.formControl;
328
334
  }
329
- else if (stringIsSetAndNotEmpty(this.formControlName)) {
335
+ else if (stringIsSetAndFilled(this.formControlName)) {
330
336
  this.attachedFormControl = (_a = this.controlContainer) === null || _a === void 0 ? void 0 : _a.control.get(this.formControlName);
331
337
  if (isNullOrUndefined(this.attachedFormControl)) {
332
338
  throw new Error("Form element '" + this.formControlName + "' with caption '" + ((_b = this.parent) === null || _b === void 0 ? void 0 : _b.caption) + "' is not declared in your FormGroup.");
@@ -830,6 +836,7 @@
830
836
  function PasswordFieldComponent() {
831
837
  var _this = _super.apply(this, __spread(arguments)) || this;
832
838
  _this.placeholder = 'Password';
839
+ _this.isPasswordConfirm = false;
833
840
  return _this;
834
841
  }
835
842
  return PasswordFieldComponent;
@@ -837,74 +844,157 @@
837
844
  PasswordFieldComponent.decorators = [
838
845
  { type: core.Component, args: [{
839
846
  selector: 'klp-form-password-field',
840
- template: "<input\n\ttype=\"password\"\n\tclass=\"form-control\"\n [ngClass]=\"{showErrors: isInErrorState()}\"\n\t[(ngModel)]=\"innerValue\"\n\t(input)=\"setInnerValueAndNotify($event.target.value)\"\n\t[placeholder]=\"placeholder\"\n\t(blur)=\"touch()\"\n/>\n",
847
+ template: "<input\n\ttype=\"password\"\n\tclass=\"form-control\"\n [ngClass]=\"{showErrors: isInErrorState()}\"\n\t[(ngModel)]=\"innerValue\"\n\t(input)=\"setInnerValueAndNotify($event.target.value)\"\n\t[placeholder]=\"isPasswordConfirm ? 'Confirm password': 'Password'\"\n\t(blur)=\"touch()\"\n/>\n",
841
848
  providers: [{ provide: forms.NG_VALUE_ACCESSOR, useExisting: PasswordFieldComponent, multi: true }],
842
849
  styles: [":host,input{display:block}input{-moz-transition:all .2s ease-in;-ms-transition:all .2s ease-in;-o-transition:all .2s ease-in;-webkit-transition:all .2s ease-in;border:1px solid #e6ecf5;border-radius:2px;box-shadow:none;color:#888da8;font-size:14px;height:42px;outline:none;padding:.375rem .625rem;transition:all .2s ease-in;width:100%}input::-webkit-input-placeholder{color:#adadad}input:-moz-placeholder,input::-moz-placeholder{color:#adadad}input:-ms-input-placeholder{color:#adadad}input:focus{border-color:#3ed778;box-shadow:none;outline:0 none}input.input-sm{height:30px}input.input-lg{height:50px}input.error{background-color:#ffeff4;border-color:#ff3c7e}input.valid{background-color:#ebfaeb;border-color:#37c936;color:#278d26}.showErrors{border-color:#ff8000}"]
843
850
  },] }
844
851
  ];
845
852
  PasswordFieldComponent.propDecorators = {
846
- placeholder: [{ type: core.Input }]
853
+ placeholder: [{ type: core.Input }],
854
+ isPasswordConfirm: [{ type: core.Input }]
847
855
  };
848
856
 
857
+ var SELECT_TRANSLATIONS = new core.InjectionToken('klp.form.select.translations');
849
858
  var SelectComponent = /** @class */ (function (_super) {
850
859
  __extends(SelectComponent, _super);
851
- function SelectComponent(parent, controlContainer) {
860
+ function SelectComponent(parent, controlContainer, translations) {
852
861
  var _this = _super.call(this, parent, controlContainer) || this;
853
862
  _this.parent = parent;
854
863
  _this.controlContainer = controlContainer;
855
- _this.placeholder = 'Pick an option';
864
+ _this.translations = translations;
856
865
  _this.multiple = false;
866
+ _this.multipleDisplayedAsAmount = false;
857
867
  _this.clearable = true;
858
868
  _this.onSearch = new core.EventEmitter();
859
869
  return _this;
860
870
  }
871
+ SelectComponent.prototype.onTextInput = function (value) {
872
+ this.currentQueryString = value;
873
+ this.onSearch.emit(value);
874
+ };
875
+ SelectComponent.prototype.getDefaultTranslation = function (key) {
876
+ var _this = this;
877
+ switch (key) {
878
+ case 'placeholder':
879
+ return function () { var _a; return (_a = _this.placeholder) !== null && _a !== void 0 ? _a : 'Pick an option'; };
880
+ case 'amountSelected':
881
+ return function (amount) { return amount + " selected"; };
882
+ }
883
+ };
884
+ SelectComponent.prototype.getTranslation = function (key, params) {
885
+ if (params === void 0) { params = null; }
886
+ var _a, _b, _c;
887
+ return (_c = (_b = (_a = this.translations) === null || _a === void 0 ? void 0 : _a[key]) === null || _b === void 0 ? void 0 : _b.call(_a, params)) !== null && _c !== void 0 ? _c : this.getDefaultTranslation(key)(params);
888
+ };
861
889
  return SelectComponent;
862
890
  }(ValueAccessorBase));
863
891
  SelectComponent.decorators = [
864
892
  { type: core.Component, args: [{
865
893
  selector: 'klp-form-select',
866
- template: "<ng-select\n\t[placeholder]=\"placeholder\"\n\tbindLabel=\"name\"\n\tbindValue=\"id\"\n\t[items]=\"options\"\n\t[clearable]=\"clearable\"\n\t[(ngModel)]=\"innerValue\"\n\t[ngClass]=\"{showErrors: isInErrorState()}\"\n\t(change)=\"setInnerValueAndNotify(innerValue)\"\n\t[multiple]=\"multiple\"\n\t[disabled]=\"disabled\"\n\t(blur)=\"touch()\"\n\t(search)=\"onSearch.emit($event.term)\"\n\t[dropdownPosition]=\"dropdownPosition\"\n\t[searchFn]=\"customSearchFn\"\n>\n\t<ng-template let-item=\"item\" ng-option-tmp>\n\t\t{{ item.name }}\n\t\t<div *ngIf=\"item.description\" class=\"dropdown-item-description\">\n\t\t\t{{ item.description }}\n\t\t</div>\n\t</ng-template>\n</ng-select>\n",
894
+ template: "<ng-select\n\t[placeholder]=\"getTranslation('placeholder')\"\n\tbindLabel=\"name\"\n\tbindValue=\"id\"\n\t[items]=\"options\"\n\t[clearable]=\"clearable\"\n\t[(ngModel)]=\"innerValue\"\n\t[ngClass]=\"{showErrors: isInErrorState()}\"\n\t(change)=\"setInnerValueAndNotify(innerValue)\"\n\t[multiple]=\"multiple\"\n\t[disabled]=\"disabled\"\n\t(blur)=\"touch()\"\n\t(search)=\"onSearch.emit($event.term)\"\n\t[dropdownPosition]=\"dropdownPosition\"\n\t[searchFn]=\"customSearchFn\"\n\t(input)=\"onTextInput($event.target.value)\"\n>\n\t<ng-template let-item=\"item\" ng-option-tmp>\n\t\t{{ item.name }}\n\t\t<div *ngIf=\"item.description\" class=\"dropdown-item-description\">\n\t\t\t{{ item.description }}\n\t\t</div>\n\t</ng-template>\n\t<ng-container *ngIf=\"multiple && multipleDisplayedAsAmount && innerValue?.length > 1\">\n\t\t<ng-template ng-multi-label-tmp>\n\t\t\t<div class=\"ng-value\">\n\t\t\t\t<span class=\"ng-value-label\">{{getTranslation('amountSelected', innerValue?.length)}}</span>\n\t\t\t</div>\n\t\t</ng-template>\n\t</ng-container>\n\t<ng-template ng-footer-tmp *ngIf=\"footerElement\">\n\t\t<ng-container [ngTemplateOutlet]=\"footerElement\"></ng-container>\n\t</ng-template>\n</ng-select>\n",
867
895
  providers: [{ provide: forms.NG_VALUE_ACCESSOR, useExisting: SelectComponent, multi: true }],
868
- styles: [":host{display:block}.showErrors ::ng-deep .ng-select-container,:host.showErrors ::ng-deep .ng-select-container{border-color:#ff8000}:host ::ng-deep ng-select.ng-select .ng-select-container{color:#888da8}:host ::ng-deep .ng-select.ng-select-opened>.ng-select-container{background:#fff;border-color:#3ed778}:host ::ng-deep .ng-select.ng-select-opened>.ng-select-container:hover{box-shadow:none}:host ::ng-deep .ng-select.ng-select-opened>.ng-select-container .ng-arrow{border-color:transparent transparent #999;border-width:0 5px 5px;top:-2px}:host ::ng-deep .ng-select.ng-select-opened>.ng-select-container .ng-arrow:hover{border-color:transparent transparent #666}:host ::ng-deep .ng-select.ng-select-opened.ng-select-bottom>.ng-select-container{border-bottom-left-radius:0;border-bottom-right-radius:0}:host ::ng-deep .ng-select.ng-select-opened.ng-select-top>.ng-select-container{border-top-left-radius:0;border-top-right-radius:0}:host ::ng-deep .ng-select.ng-select-disabled>.ng-select-container{background-color:#f9f9f9}:host ::ng-deep .ng-select .ng-has-value .ng-placeholder{display:none}:host ::ng-deep .ng-select .ng-select-container{align-items:center;background-clip:padding-box;background-color:#fff;border:1px solid #e6ecf5;border-radius:4px;border-radius:2px;box-shadow:none;box-sizing:border-box;color:#888da8;display:flex;flex-direction:row;font-size:1rem;font-size:14px;line-height:1.5;margin:0;min-height:42px;outline:none;overflow:visible;padding:.375rem .75rem;transition-delay:0s;transition-duration:.2s;transition-property:all;transition-timing-function:ease-in;width:100%}:host ::ng-deep .ng-select .ng-select-container:hover{box-shadow:0 1px 0 rgba(0,0,0,.06)}:host ::ng-deep .ng-select .ng-select-container .ng-value-container{align-items:center;overflow:hidden;padding-left:10px}:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-placeholder{color:#aaa}:host ::ng-deep .ng-select.ng-select-single .ng-select-container{height:42px}:host ::ng-deep .ng-select.ng-select-single .ng-select-container .ng-value-container .ng-input{left:0;padding-left:10px;padding-right:50px;top:5px}:host ::ng-deep .ng-select.ng-select-multiple.ng-select-disabled>.ng-select-container .ng-value-container .ng-value{background-color:#f9f9f9;border:1px solid #e3e3e3}:host ::ng-deep .ng-select.ng-select-multiple.ng-select-disabled>.ng-select-container .ng-value-container .ng-value .ng-value-label{padding:0 5px}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding-left:7px;padding-right:10px;padding-top:2px}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background-color:#e7faee;border:1px solid #93e8b3;border-radius:2px;display:flex;font-size:.9em;margin-bottom:5px;margin-right:5px;overflow:hidden}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled{background-color:#f9f9f9;border:1px solid #e3e3e3}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled .ng-value-label{padding-left:5px}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-label{display:inline-block;overflow:hidden;padding:0 5px;text-overflow:ellipsis}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon{display:inline-block;padding:0 5px}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon:hover{background-color:#93e8b3}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.left{border-right:1px solid #93e8b3}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.right{border-left:1px solid #c2e0ff}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-input{padding-bottom:3px;padding-left:3px}:host ::ng-deep ng-select.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-bottom:3px;padding-left:3px;position:static;top:5px}:host ::ng-deep .ng-select .ng-clear-wrapper{color:#999}:host ::ng-deep .ng-select .ng-clear-wrapper .ng-clear:hover{color:#ff3c7e}:host ::ng-deep .ng-select .ng-spinner-zone{padding-right:5px;padding-top:5px}:host ::ng-deep .ng-select .ng-arrow-wrapper{padding-right:5px;width:25px}:host ::ng-deep .ng-select .ng-arrow-wrapper:hover .ng-arrow{border-top-color:#666}:host ::ng-deep .ng-select .ng-arrow-wrapper .ng-arrow{border-color:#999 transparent transparent;border-style:solid;border-width:5px 5px 2.5px}:host ::ng-deep .ng-dropdown-panel{background-color:#fff;border:1px solid #3ed778;box-shadow:0 1px 0 rgba(0,0,0,.06)}:host ::ng-deep .ng-dropdown-panel.ng-select-bottom{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-top-color:#e6e6e6;margin-top:-1px;top:100%}:host ::ng-deep .ng-dropdown-panel.ng-select-bottom .ng-dropdown-panel-items .ng-option:last-child{border-bottom-left-radius:4px;border-bottom-right-radius:4px}:host ::ng-deep .ng-dropdown-panel.ng-select-top{border-bottom-color:#e6e6e6;border-top-left-radius:4px;border-top-right-radius:4px;bottom:100%;margin-bottom:-1px}:host ::ng-deep .ng-dropdown-panel.ng-select-top .ng-dropdown-panel-items .ng-option:first-child{border-top-left-radius:4px;border-top-right-radius:4px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border-bottom:1px solid #ccc;padding:5px 7px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-footer{border-top:1px solid #ccc;padding:5px 7px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{margin-bottom:1px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;color:rgba(0,0,0,.54);cursor:default;cursor:pointer;font-weight:500;padding:8px 10px;user-select:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-disabled{cursor:default}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-marked{background-color:#ebf5ff}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-selected{background-color:#f5faff;font-weight:600}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option{background-color:#fff;color:rgba(0,0,0,.87);padding:8px 10px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected{background-color:#e7faee;color:#333}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected .ng-option-label{font-weight:600}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked{background-color:#e7faee;color:#333}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-disabled{color:#ccc}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-child{padding-left:22px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option .ng-tag-label{font-size:80%;font-weight:400;padding-right:5px}:host ::ng-deep ng-select.ng-select .ng-select-container .ng-value-container{padding-left:0}:host ::ng-deep ng-select.ng-select.ng-select-single .ng-select-container .ng-value-container .ng-input{color:#888da8;top:9px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option,:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input{color:#888da8}:host ::ng-deep .ng-select.ng-select-auto-grow{max-width:inherit}:host ::ng-deep .ng-select.ng-select-auto-grow .ng-dropdown-panel{width:auto}"]
896
+ styles: [":host{display:block}.showErrors ::ng-deep .ng-select-container,:host.showErrors ::ng-deep .ng-select-container{border-color:#ff8000}:host ::ng-deep ng-select.ng-select .ng-select-container{color:#888da8}:host ::ng-deep .ng-select.ng-select-opened>.ng-select-container{background:#fff;border-color:#3ed778}:host ::ng-deep .ng-select.ng-select-opened>.ng-select-container:hover{box-shadow:none}:host ::ng-deep .ng-select.ng-select-opened>.ng-select-container .ng-arrow{border-color:transparent transparent #999;border-width:0 5px 5px;top:-2px}:host ::ng-deep .ng-select.ng-select-opened>.ng-select-container .ng-arrow:hover{border-color:transparent transparent #666}:host ::ng-deep .ng-select.ng-select-opened.ng-select-bottom>.ng-select-container{border-bottom-left-radius:0;border-bottom-right-radius:0}:host ::ng-deep .ng-select.ng-select-opened.ng-select-top>.ng-select-container{border-top-left-radius:0;border-top-right-radius:0}:host ::ng-deep .ng-select.ng-select-disabled>.ng-select-container{background-color:#f9f9f9}:host ::ng-deep .ng-select .ng-has-value .ng-placeholder{display:none}:host ::ng-deep .ng-select .ng-select-container{align-items:center;background-clip:padding-box;background-color:#fff;border:1px solid #e6ecf5;border-radius:4px;border-radius:2px;box-shadow:none;box-sizing:border-box;color:#888da8;display:flex;flex-direction:row;font-size:1rem;font-size:14px;line-height:1.5;margin:0;min-height:42px;outline:none;overflow:visible;padding:.375rem .75rem;transition-delay:0s;transition-duration:.2s;transition-property:all;transition-timing-function:ease-in;width:100%}:host ::ng-deep .ng-select .ng-select-container:hover{box-shadow:0 1px 0 rgba(0,0,0,.06)}:host ::ng-deep .ng-select .ng-select-container .ng-value-container{align-items:center;overflow:hidden;padding-left:10px}:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-placeholder{color:#aaa}:host ::ng-deep .ng-select.ng-select-single .ng-select-container{height:42px}:host ::ng-deep .ng-select.ng-select-single .ng-select-container .ng-value-container .ng-input{left:0;padding-left:10px;padding-right:50px;top:5px}:host ::ng-deep .ng-select.ng-select-multiple.ng-select-disabled>.ng-select-container .ng-value-container .ng-value{background-color:#f9f9f9;border:1px solid #e3e3e3}:host ::ng-deep .ng-select.ng-select-multiple.ng-select-disabled>.ng-select-container .ng-value-container .ng-value .ng-value-label{padding:0 5px}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background-color:#e7faee;border:1px solid #93e8b3;border-radius:2px;display:flex;font-size:.9em;margin-bottom:3px;margin-right:5px;margin-top:3px;overflow:hidden}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled{background-color:#f9f9f9;border:1px solid #e3e3e3}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value.ng-value-disabled .ng-value-label{padding-left:5px}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-label{display:inline-block;overflow:hidden;padding:0 5px;text-overflow:ellipsis}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon{display:inline-block;padding:0 5px}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon:hover{background-color:#93e8b3}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.left{border-right:1px solid #93e8b3}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value .ng-value-icon.right{border-left:1px solid #c2e0ff}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-input{padding-bottom:3px;padding-left:3px}:host ::ng-deep ng-select.ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-bottom:3px;padding-left:3px;position:static;top:5px}:host ::ng-deep .ng-select .ng-clear-wrapper{color:#999}:host ::ng-deep .ng-select .ng-clear-wrapper .ng-clear:hover{color:#ff3c7e}:host ::ng-deep .ng-select .ng-spinner-zone{padding-right:5px;padding-top:5px}:host ::ng-deep .ng-select .ng-arrow-wrapper{padding-right:5px;width:25px}:host ::ng-deep .ng-select .ng-arrow-wrapper:hover .ng-arrow{border-top-color:#666}:host ::ng-deep .ng-select .ng-arrow-wrapper .ng-arrow{border-color:#999 transparent transparent;border-style:solid;border-width:5px 5px 2.5px}:host ::ng-deep .ng-dropdown-panel{background-color:#fff;border:1px solid #3ed778;box-shadow:0 1px 0 rgba(0,0,0,.06)}:host ::ng-deep .ng-dropdown-panel.ng-select-bottom{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-top-color:#e6e6e6;margin-top:-1px;top:100%}:host ::ng-deep .ng-dropdown-panel.ng-select-bottom .ng-dropdown-panel-items .ng-option:last-child{border-bottom-left-radius:4px;border-bottom-right-radius:4px}:host ::ng-deep .ng-dropdown-panel.ng-select-top{border-bottom-color:#e6e6e6;border-top-left-radius:4px;border-top-right-radius:4px;bottom:100%;margin-bottom:-1px}:host ::ng-deep .ng-dropdown-panel.ng-select-top .ng-dropdown-panel-items .ng-option:first-child{border-top-left-radius:4px;border-top-right-radius:4px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border-bottom:1px solid #ccc;padding:5px 7px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-footer{border-top:1px solid #ccc;padding:5px 7px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{margin-bottom:1px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;color:rgba(0,0,0,.54);cursor:default;cursor:pointer;font-weight:500;padding:8px 10px;user-select:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-disabled{cursor:default}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-marked{background-color:#ebf5ff}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-optgroup.ng-option-selected{background-color:#f5faff;font-weight:600}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option{background-color:#fff;color:rgba(0,0,0,.87);padding:8px 10px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected{background-color:#e7faee;color:#333}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-selected .ng-option-label{font-weight:600}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-marked{background-color:#e7faee;color:#333}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-disabled{color:#ccc}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option.ng-option-child{padding-left:22px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option .ng-tag-label{font-size:80%;font-weight:400;padding-right:5px}:host ::ng-deep ng-select.ng-select .ng-select-container .ng-value-container{padding-left:0}:host ::ng-deep ng-select.ng-select.ng-select-single .ng-select-container .ng-value-container .ng-input{color:#888da8;top:9px}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items .ng-option,:host ::ng-deep .ng-select .ng-select-container .ng-value-container .ng-input>input{color:#888da8}:host ::ng-deep .ng-select.ng-select-auto-grow{max-width:inherit}:host ::ng-deep .ng-select.ng-select-auto-grow .ng-dropdown-panel{width:auto}"]
869
897
  },] }
870
898
  ];
871
899
  SelectComponent.ctorParameters = function () { return [
872
900
  { type: FormElementComponent, decorators: [{ type: core.Optional }, { type: core.Host }] },
873
- { type: forms.ControlContainer, decorators: [{ type: core.Optional }, { type: core.Host }] }
901
+ { type: forms.ControlContainer, decorators: [{ type: core.Optional }, { type: core.Host }] },
902
+ { type: undefined, decorators: [{ type: core.Inject, args: [SELECT_TRANSLATIONS,] }, { type: core.Optional }] }
874
903
  ]; };
875
904
  SelectComponent.propDecorators = {
876
905
  placeholder: [{ type: core.Input }],
877
906
  options: [{ type: core.Input }],
878
907
  multiple: [{ type: core.Input }],
908
+ multipleDisplayedAsAmount: [{ type: core.Input }],
879
909
  clearable: [{ type: core.Input }],
880
910
  dropdownPosition: [{ type: core.Input }],
881
911
  customSearchFn: [{ type: core.Input }],
912
+ footerElement: [{ type: core.Input }],
882
913
  onSearch: [{ type: core.Output }]
883
914
  };
884
915
 
916
+ var SelectFooterComponent = /** @class */ (function () {
917
+ function SelectFooterComponent() {
918
+ }
919
+ return SelectFooterComponent;
920
+ }());
921
+ SelectFooterComponent.decorators = [
922
+ { type: core.Component, args: [{
923
+ selector: 'klp-select-footer',
924
+ template: "<div class=\"componentContainer\">\n\t<span class=\"prefix\">{{prefix}}</span>\n\t<span class=\"text\">{{text}}</span>\n</div>\n",
925
+ styles: [":host{display:block}.componentContainer{cursor:pointer;padding:6px 10px}.componentContainer:hover{background:#e7faee}.prefix{font-size:80%;padding-right:.625rem}"]
926
+ },] }
927
+ ];
928
+ SelectFooterComponent.propDecorators = {
929
+ prefix: [{ type: core.Input }],
930
+ text: [{ type: core.Input }]
931
+ };
932
+
885
933
  var SortableItemsComponent = /** @class */ (function (_super) {
886
934
  __extends(SortableItemsComponent, _super);
887
935
  function SortableItemsComponent() {
888
936
  var _this = _super.apply(this, __spread(arguments)) || this;
889
937
  _this.sortableItemSize = 'lg';
938
+ _this.useCustomScroll = false;
939
+ _this.scrollInterval = null;
890
940
  _this.itemsOrderChanged = function () {
891
941
  _this.setInnerValueAndNotify(_this.innerValue);
892
942
  };
943
+ _this.onItemDrag = function (data) {
944
+ // if the item you're dragging is reaching the top, start scrolling.
945
+ if (data.relatedRect.top < 100) {
946
+ _this.scrollPage(100);
947
+ }
948
+ else {
949
+ _this.stopScrolling();
950
+ }
951
+ };
952
+ _this.onEnd = function () {
953
+ _this.stopScrolling();
954
+ };
893
955
  return _this;
894
956
  }
957
+ SortableItemsComponent.prototype.ngOnInit = function () {
958
+ _super.prototype.ngOnInit.call(this);
959
+ if (this.useCustomScroll) {
960
+ this.sortablejsOptions = { onUpdate: this.itemsOrderChanged, onMove: this.onItemDrag, onEnd: this.onEnd };
961
+ }
962
+ else {
963
+ this.sortablejsOptions = { onUpdate: this.itemsOrderChanged };
964
+ }
965
+ };
966
+ SortableItemsComponent.prototype.scrollPage = function (scrollAmount) {
967
+ var _this = this;
968
+ if (!isValueSet(this.scrollInterval)) {
969
+ this.scrollInterval = setInterval(function () {
970
+ window.scroll({
971
+ top: document.scrollingElement.scrollTop - scrollAmount,
972
+ behavior: 'smooth',
973
+ });
974
+ if (document.scrollingElement.scrollTop <= 100) {
975
+ _this.stopScrolling();
976
+ }
977
+ }, 100);
978
+ }
979
+ };
980
+ SortableItemsComponent.prototype.stopScrolling = function () {
981
+ clearInterval(this.scrollInterval);
982
+ this.scrollInterval = null;
983
+ };
895
984
  return SortableItemsComponent;
896
985
  }(ValueAccessorBase));
897
986
  SortableItemsComponent.decorators = [
898
987
  { type: core.Component, args: [{
899
988
  selector: 'klp-form-sortable-items',
900
- template: "<ng-template #listItem>\n\t<li *ngFor=\"let item of innerValue; index as index\"\n\t class=\"sortableItem\"\n\t [ngClass]=\"{\n\t\t\tlargeSortableItem: sortableItemSize === 'lg',\n\t\t \tsmallSortableItem: sortableItemSize === 'sm'\n\t\t }\"\n\t>\n\t\t<ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"{ item: item, index:index }\" ></ng-container>\n\t</li>\n</ng-template>\n\n<ol *ngIf='!disabled'\n [sortablejs]=\"innerValue\"\n [sortablejsOptions]=\"{ onUpdate: itemsOrderChanged }\"\n class=\"itemsContainer\"\n>\n\t<ng-container *ngTemplateOutlet=\"listItem\"></ng-container>\n</ol>\n\n<ol *ngIf='disabled' class=\"itemsContainer disabled-mouse-cursor\">\n\t<ng-container *ngTemplateOutlet=\"listItem\"></ng-container>\n</ol>\n",
989
+ template: "<ng-template #listItem>\n\t<li *ngFor=\"let item of innerValue; index as index\"\n\t\t\tclass=\"sortableItem\"\n\t\t\t[ngClass]=\"{\n\t\t\tlargeSortableItem: sortableItemSize === 'lg',\n\t\t \tsmallSortableItem: sortableItemSize === 'sm'\n\t\t }\"\n\t>\n\t\t<ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"{ item: item, index:index }\"></ng-container>\n\t</li>\n</ng-template>\n\n<ol *ngIf='!disabled'\n\t\t[sortablejs]=\"innerValue\"\n\t\t[sortablejsOptions]=\"sortablejsOptions\"\n\t\tclass=\"itemsContainer\"\n>\n\t<ng-container *ngTemplateOutlet=\"listItem\"></ng-container>\n</ol>\n\n<ol *ngIf='disabled' class=\"itemsContainer disabled-mouse-cursor\">\n\t<ng-container *ngTemplateOutlet=\"listItem\"></ng-container>\n</ol>\n",
901
990
  providers: [{ provide: forms.NG_VALUE_ACCESSOR, useExisting: SortableItemsComponent, multi: true }],
902
991
  styles: [":host{display:block}.itemsContainer{border:1px solid #e6ecf5;border-radius:5px;margin-bottom:0;padding:0}.sortableItem{border-top:1px solid #e6ecf5;cursor:-webkit-grab;cursor:grab;list-style:none}.sortableItem:hover{background:#f8f9fa}.sortableItem:first-child{border-top:none}.largeSortableItem{padding:15px}.smallSortableItem{padding:0 10px}.disabled-mouse-cursor li{cursor:no-drop}"]
903
992
  },] }
904
993
  ];
905
994
  SortableItemsComponent.propDecorators = {
906
995
  template: [{ type: core.ContentChild, args: [core.TemplateRef,] }],
907
- sortableItemSize: [{ type: core.Input }]
996
+ sortableItemSize: [{ type: core.Input }],
997
+ useCustomScroll: [{ type: core.Input }]
908
998
  };
909
999
 
910
1000
  var TextInputComponent = /** @class */ (function (_super) {
@@ -912,6 +1002,7 @@
912
1002
  function TextInputComponent() {
913
1003
  var _this = _super.apply(this, __spread(arguments)) || this;
914
1004
  _this.type = 'text';
1005
+ _this.clearable = false;
915
1006
  return _this;
916
1007
  }
917
1008
  return TextInputComponent;
@@ -919,14 +1010,16 @@
919
1010
  TextInputComponent.decorators = [
920
1011
  { type: core.Component, args: [{
921
1012
  selector: 'klp-form-text-input',
922
- template: "<input\n\t[type]=\"type\"\n\tclass=\"form-control\"\n\t[ngClass]=\"{showErrors: isInErrorState()}\"\n\t[(ngModel)]=\"innerValue\"\n\t(input)=\"setInnerValueAndNotify($event.target.value)\"\n\t[placeholder]=\"placeholder ? placeholder : ''\"\n\t(blur)=\"touch()\"\n\t[disabled]='disabled'\n/>\n",
1013
+ template: "<div class=\"componentContainer\">\n\t<ng-container *ngIf=\"icon?.length > 0\">\n\t\t<i class=\"ti-search\" *ngIf=\"icon === 'search'\"></i>\n\t</ng-container>\n\t<input\n\t\t[type]=\"type\"\n\t\t[ngClass]=\"{showErrors: isInErrorState(), hasIcon: icon?.length > 0, hasClearButton: clearable}\"\n\t\t[(ngModel)]=\"innerValue\"\n\t\t(input)=\"setInnerValueAndNotify($event.target.value)\"\n\t\t[placeholder]=\"placeholder ? placeholder : ''\"\n\t\t(blur)=\"touch()\"\n\t\t[disabled]='disabled'\n\t/>\n\t<div class=\"clearIcon\" *ngIf=\"clearable && innerValue?.length > 0\" (click)=\"resetToNull()\">\u00D7</div>\n</div>\n",
923
1014
  providers: [{ provide: forms.NG_VALUE_ACCESSOR, useExisting: TextInputComponent, multi: true }],
924
- styles: [":host,input{display:block}input{-moz-transition:all .2s ease-in;-ms-transition:all .2s ease-in;-o-transition:all .2s ease-in;-webkit-transition:all .2s ease-in;border:1px solid #e6ecf5;border-radius:2px;box-shadow:none;color:#888da8;font-size:14px;height:42px;outline:none;padding:.375rem .625rem;transition:all .2s ease-in;width:100%}input::-webkit-input-placeholder{color:#adadad}input:-moz-placeholder,input::-moz-placeholder{color:#adadad}input:-ms-input-placeholder{color:#adadad}input:focus{border-color:#3ed778;box-shadow:none;outline:0 none}input.input-sm{height:30px}input.input-lg{height:50px}input.error{background-color:#ffeff4;border-color:#ff3c7e}input.valid{background-color:#ebfaeb;border-color:#37c936;color:#278d26}.showErrors{border-color:#ff8000}"]
1015
+ styles: [":host{display:block}:host input:disabled{cursor:not-allowed}.componentContainer{position:relative}i{left:.625rem;position:absolute;top:14px}input{-moz-transition:all .2s ease-in;-ms-transition:all .2s ease-in;-o-transition:all .2s ease-in;-webkit-transition:all .2s ease-in;border:1px solid #e6ecf5;border-radius:2px;box-shadow:none;color:#888da8;display:block;font-size:14px;height:42px;outline:none;padding:.375rem .625rem;transition:all .2s ease-in;width:100%}input::-webkit-input-placeholder{color:#adadad}input:-moz-placeholder,input::-moz-placeholder{color:#adadad}input:-ms-input-placeholder{color:#adadad}input:focus{border-color:#3ed778;box-shadow:none;outline:0 none}input.input-sm{height:30px}input.input-lg{height:50px}input.error{background-color:#ffeff4;border-color:#ff3c7e}input.valid{background-color:#ebfaeb;border-color:#37c936;color:#278d26}input.hasIcon{padding-left:1.875rem}input.hasClearButton{padding-right:1.875rem}.clearIcon{cursor:pointer;font-size:18px;position:absolute;right:.625rem;top:7px}.showErrors{border-color:#ff8000}"]
925
1016
  },] }
926
1017
  ];
927
1018
  TextInputComponent.propDecorators = {
928
1019
  placeholder: [{ type: core.Input }],
929
- type: [{ type: core.Input }]
1020
+ type: [{ type: core.Input }],
1021
+ clearable: [{ type: core.Input }],
1022
+ icon: [{ type: core.Input }]
930
1023
  };
931
1024
 
932
1025
  var ToggleComponent = /** @class */ (function (_super) {
@@ -1071,38 +1164,226 @@
1071
1164
  _: [{ type: core.HostBinding, args: ['class._fullWidth',] }]
1072
1165
  };
1073
1166
 
1167
+ var MultipleValueAccessorBase = /** @class */ (function (_super) {
1168
+ __extends(MultipleValueAccessorBase, _super);
1169
+ function MultipleValueAccessorBase(parent, controlContainer) {
1170
+ var _this = _super.call(this, parent, controlContainer) || this;
1171
+ _this.parent = parent;
1172
+ _this.controlContainer = controlContainer;
1173
+ _this.multiple = false;
1174
+ return _this;
1175
+ }
1176
+ MultipleValueAccessorBase.prototype.writeValue = function (value) {
1177
+ if (this.multiple) {
1178
+ if (Array.isArray(value)) {
1179
+ _super.prototype.writeValue.call(this, value.filter(isValueSet));
1180
+ }
1181
+ else {
1182
+ _super.prototype.writeValue.call(this, [value].filter(isValueSet));
1183
+ }
1184
+ }
1185
+ else {
1186
+ if (Array.isArray(value)) {
1187
+ _super.prototype.writeValue.call(this, value[0]);
1188
+ }
1189
+ else {
1190
+ _super.prototype.writeValue.call(this, value);
1191
+ }
1192
+ }
1193
+ };
1194
+ MultipleValueAccessorBase.prototype.setInnerValueAndNotify = function (value) {
1195
+ if (this.multiple) {
1196
+ if (Array.isArray(value)) {
1197
+ _super.prototype.setInnerValueAndNotify.call(this, value.filter(isValueSet));
1198
+ }
1199
+ else {
1200
+ _super.prototype.setInnerValueAndNotify.call(this, [value].filter(isValueSet));
1201
+ }
1202
+ }
1203
+ else {
1204
+ if (Array.isArray(value)) {
1205
+ _super.prototype.setInnerValueAndNotify.call(this, value[0]);
1206
+ }
1207
+ else {
1208
+ _super.prototype.setInnerValueAndNotify.call(this, value);
1209
+ }
1210
+ }
1211
+ };
1212
+ return MultipleValueAccessorBase;
1213
+ }(ValueAccessorBase));
1214
+ MultipleValueAccessorBase.decorators = [
1215
+ { type: core.Component, args: [{
1216
+ selector: '',
1217
+ template: ''
1218
+ },] }
1219
+ ];
1220
+ MultipleValueAccessorBase.ctorParameters = function () { return [
1221
+ { type: FormElementComponent, decorators: [{ type: core.Host }, { type: core.Optional }] },
1222
+ { type: forms.ControlContainer, decorators: [{ type: core.Host }, { type: core.Optional }] }
1223
+ ]; };
1224
+ MultipleValueAccessorBase.propDecorators = {
1225
+ multiple: [{ type: core.Input }]
1226
+ };
1227
+
1074
1228
  var invalidDateKey = '--invalid_date--';
1075
1229
  function dateValidator(control) {
1076
1230
  var invalid = control.value === invalidDateKey;
1077
1231
  return invalid ? { date: control.value } : null;
1078
1232
  }
1079
1233
 
1234
+ var DATE_PICKER_TRANSLATIONS = new core.InjectionToken('klp.form.date.translations');
1235
+ var DatePickerComponent = /** @class */ (function (_super) {
1236
+ __extends(DatePickerComponent, _super);
1237
+ function DatePickerComponent(parent, controlContainer, translations) {
1238
+ var _this = _super.call(this, parent, controlContainer) || this;
1239
+ _this.parent = parent;
1240
+ _this.controlContainer = controlContainer;
1241
+ _this.translations = translations;
1242
+ _this.minDate = undefined;
1243
+ _this.maxDate = undefined;
1244
+ _this.sameMonthOnly = false;
1245
+ _this.format = 'dd-MM-yyyy';
1246
+ _this.clearable = false;
1247
+ return _this;
1248
+ }
1249
+ DatePickerComponent.prototype.writeValue = function (value) {
1250
+ if (value === invalidDateKey) {
1251
+ _super.prototype.writeValue.call(this, invalidDateKey);
1252
+ }
1253
+ else if (isNullOrUndefined(value)) {
1254
+ this.dateValue = null;
1255
+ _super.prototype.writeValue.call(this, null);
1256
+ }
1257
+ else {
1258
+ if (Array.isArray(value)) {
1259
+ this.dateValue = value.map(function (e) { return dateFns.parse(e, 'yyyy-MM-dd', new Date()); });
1260
+ }
1261
+ else {
1262
+ this.dateValue = dateFns.parse(value, 'yyyy-MM-dd', new Date());
1263
+ }
1264
+ _super.prototype.writeValue.call(this, value);
1265
+ }
1266
+ };
1267
+ DatePickerComponent.prototype.dateChanged = function (value) {
1268
+ if (value === invalidDateKey) {
1269
+ this.setInnerValueAndNotify(invalidDateKey);
1270
+ }
1271
+ else if (isNullOrUndefined(value)) {
1272
+ this.dateValue = null;
1273
+ this.setInnerValueAndNotify(null);
1274
+ }
1275
+ else {
1276
+ this.dateValue = value;
1277
+ if (Array.isArray(value)) {
1278
+ this.setInnerValueAndNotify(value.map(function (e) { return dateFns.format(e, 'yyyy-MM-dd'); }));
1279
+ }
1280
+ else {
1281
+ this.setInnerValueAndNotify(dateFns.format(value, 'yyyy-MM-dd'));
1282
+ }
1283
+ }
1284
+ };
1285
+ DatePickerComponent.prototype.getDefaultTranslation = function (key) {
1286
+ var _this = this;
1287
+ switch (key) {
1288
+ case 'placeholder':
1289
+ return function () { var _a; return (_a = _this.placeholder) !== null && _a !== void 0 ? _a : 'Select date'; };
1290
+ }
1291
+ };
1292
+ DatePickerComponent.prototype.getTranslation = function (key, params) {
1293
+ if (params === void 0) { params = null; }
1294
+ var _a, _b, _c;
1295
+ if (key === 'placeholder' && this.multiple) {
1296
+ return '';
1297
+ }
1298
+ return (_c = (_b = (_a = this.translations) === null || _a === void 0 ? void 0 : _a[key]) === null || _b === void 0 ? void 0 : _b.call(_a, params)) !== null && _c !== void 0 ? _c : this.getDefaultTranslation(key)(params);
1299
+ };
1300
+ return DatePickerComponent;
1301
+ }(MultipleValueAccessorBase));
1302
+ DatePickerComponent.decorators = [
1303
+ { type: core.Component, args: [{
1304
+ selector: 'klp-form-date-picker',
1305
+ template: "<div class=\"componentContainer\" [ngClass]=\"{showErrors: isInErrorState()}\">\n\t<klp-form-date-time-picker\n\t\t[multiple]=\"multiple\"\n\t\t[disabled]=\"disabled\"\n\t\t[(ngModel)]=\"dateValue\"\n\t\t(ngModelChange)=\"dateChanged($event)\"\n\t\t[minDate]=\"minDate\"\n\t\t[maxDate]=\"maxDate\"\n\t\t[sameMonthOnly]=\"sameMonthOnly\"\n\t\t[format]=\"format\"\n\t\t[placeholder]=\"getTranslation('placeholder')\"\n\t\t[clearable]=\"clearable\"\n\t\t[showTimeInput]=\"false\"\n\t\t(onTouch)=\"touch()\"\n\t></klp-form-date-time-picker>\n</div>\n",
1306
+ providers: [{ provide: forms.NG_VALUE_ACCESSOR, useExisting: DatePickerComponent, multi: true }],
1307
+ styles: [":host{display:block}.componentContainer.showErrors ::ng-deep klp-form-date-time-picker .clearButton,.componentContainer.showErrors ::ng-deep klp-form-date-time-picker .dateContainer{border-color:#ff8000}"]
1308
+ },] }
1309
+ ];
1310
+ DatePickerComponent.ctorParameters = function () { return [
1311
+ { type: FormElementComponent, decorators: [{ type: core.Host }, { type: core.Optional }] },
1312
+ { type: forms.ControlContainer, decorators: [{ type: core.Host }, { type: core.Optional }] },
1313
+ { type: undefined, decorators: [{ type: core.Inject, args: [DATE_PICKER_TRANSLATIONS,] }, { type: core.Optional }] }
1314
+ ]; };
1315
+ DatePickerComponent.propDecorators = {
1316
+ minDate: [{ type: core.Input }],
1317
+ maxDate: [{ type: core.Input }],
1318
+ sameMonthOnly: [{ type: core.Input }],
1319
+ format: [{ type: core.Input }],
1320
+ placeholder: [{ type: core.Input }],
1321
+ clearable: [{ type: core.Input }]
1322
+ };
1323
+
1080
1324
  var KLP_DATE_FORMATS = new core.InjectionToken('klp.form.date.formats');
1325
+ var DATE_TIME_PICKER_TRANSLATIONS = new core.InjectionToken('klp.form.dateTime.translations');
1081
1326
  function matDateFormatsFactory(component, dateFormats) {
1082
1327
  var _a;
1083
1328
  return (_a = dateFormats === null || dateFormats === void 0 ? void 0 : dateFormats(component.format)) !== null && _a !== void 0 ? _a : core$1.MAT_NATIVE_DATE_FORMATS;
1084
1329
  }
1085
- var DatepickerComponent = /** @class */ (function (_super) {
1086
- __extends(DatepickerComponent, _super);
1087
- function DatepickerComponent() {
1088
- var _this = _super.apply(this, __spread(arguments)) || this;
1330
+ var DateTimePickerComponent = /** @class */ (function (_super) {
1331
+ __extends(DateTimePickerComponent, _super);
1332
+ function DateTimePickerComponent(parent, controlContainer, translations, cdr) {
1333
+ var _this = _super.call(this, parent, controlContainer) || this;
1334
+ _this.parent = parent;
1335
+ _this.controlContainer = controlContainer;
1336
+ _this.translations = translations;
1337
+ _this.cdr = cdr;
1089
1338
  _this.minDate = undefined;
1090
1339
  _this.maxDate = undefined;
1091
- _this.placeholder = 'Select date';
1340
+ _this.sameMonthOnly = false;
1341
+ _this.format = 'dd-MM-yyyy';
1092
1342
  _this.clearable = false;
1343
+ _this.showTimeInput = true;
1344
+ _this.invalidTimeAsMidnight = false; // if the time is not valid, use 00:00 as the time
1093
1345
  _this.minDateStartOfDay = undefined;
1094
1346
  _this.maxDateEndOfDay = undefined;
1347
+ _this.selectedDates = [];
1348
+ _this.dateTouched = false;
1349
+ _this.hoursTouched = false;
1350
+ _this.minutesTouched = false;
1351
+ _this.isSelected = function (d) {
1352
+ if (_this.multiple) {
1353
+ return _this.selectedDates.some(function (e) { return e.getTime() === d.getTime(); }) ? 'selected' : '';
1354
+ }
1355
+ return '';
1356
+ };
1357
+ _this.filterDates = function (e) {
1358
+ if (_this.disabled) {
1359
+ return false;
1360
+ }
1361
+ return true;
1362
+ };
1095
1363
  return _this;
1096
1364
  }
1097
- DatepickerComponent.prototype.ngOnChanges = function (changes) {
1365
+ DateTimePickerComponent.prototype.ngOnInit = function () {
1366
+ _super.prototype.ngOnInit.call(this);
1367
+ if (this.multiple) {
1368
+ this.placeholder = '';
1369
+ this.showTimeInput = false;
1370
+ }
1371
+ };
1372
+ DateTimePickerComponent.prototype.ngAfterViewInit = function () {
1373
+ if (this.multiple) {
1374
+ // we are going to overwrite the datepicker closing fn later, so we are saving it here to restore it when needed
1375
+ this.datePickingClosingFn = this.datePickerRef.close;
1376
+ }
1377
+ };
1378
+ DateTimePickerComponent.prototype.ngOnChanges = function (changes) {
1098
1379
  if (changes.minDate) {
1099
- this.setMinDate(changes.minDate.currentValue);
1380
+ this.determineMinAndMaxDates();
1100
1381
  }
1101
1382
  if (changes.maxDate) {
1102
- this.setMaxDate(changes.maxDate.currentValue);
1383
+ this.determineMinAndMaxDates();
1103
1384
  }
1104
1385
  };
1105
- DatepickerComponent.prototype.setMinDate = function (minDate) {
1386
+ DateTimePickerComponent.prototype.setMinDate = function (minDate) {
1106
1387
  if (minDate) {
1107
1388
  this.minDateStartOfDay = new Date(minDate);
1108
1389
  this.minDateStartOfDay.setHours(0, 0, 0, 0);
@@ -1111,7 +1392,7 @@
1111
1392
  this.minDateStartOfDay = undefined;
1112
1393
  }
1113
1394
  };
1114
- DatepickerComponent.prototype.setMaxDate = function (maxDate) {
1395
+ DateTimePickerComponent.prototype.setMaxDate = function (maxDate) {
1115
1396
  if (maxDate) {
1116
1397
  this.maxDateEndOfDay = new Date(maxDate);
1117
1398
  this.maxDateEndOfDay.setHours(23, 59, 59, 999);
@@ -1120,67 +1401,231 @@
1120
1401
  this.maxDateEndOfDay = undefined;
1121
1402
  }
1122
1403
  };
1404
+ DateTimePickerComponent.prototype.getSelectedMonths = function () {
1405
+ return removeDuplicatesFromArray(this.selectedDates.map(function (e) { return dateFns.format(e, 'MMMM'); })).length;
1406
+ };
1123
1407
  // dateChanged is called when the output of the datepicker is changed and
1124
1408
  // parsed correctly. If the date is invalid, it will be called the first time
1125
1409
  // with null but never again until a valid input is provided.
1126
- DatepickerComponent.prototype.dateChanged = function (event) {
1127
- var nativeInputValue = this.nativeInputRef.nativeElement.value;
1410
+ DateTimePickerComponent.prototype.dateChanged = function (event) {
1411
+ var _this = this;
1128
1412
  var date = event.value;
1129
- if (isNullOrUndefined(date) && stringIsSetAndNotEmpty(nativeInputValue)) {
1130
- this.setInnerValueAndNotify(invalidDateKey);
1413
+ if (this.multiple) {
1414
+ this.datePickerRef.close = function () {
1415
+ };
1416
+ if (this.selectedDates.some(function (e) { return e.getTime() === date.getTime(); })) {
1417
+ this.selectedDates = this.selectedDates.filter(function (e) { return e.getTime() !== date.getTime(); });
1418
+ }
1419
+ else {
1420
+ this.selectedDates = __spread(this.selectedDates, [date]);
1421
+ }
1422
+ // START HACK
1423
+ // the date picker does not provide any rerender calls. Therefore, we are going to change the minDate in order to force the render
1424
+ // This is needed to show all selected days in our date picker
1425
+ // We also set the innerValue to null (with this.valueForMaterialDatePicker = null;), otherwise you can not
1426
+ // deselect your last picked date
1427
+ this.cdr.detectChanges();
1428
+ this.valueForMaterialDatePicker = null;
1429
+ var oldMinDate = this.minDateStartOfDay;
1430
+ this.minDateStartOfDay = new Date(0);
1431
+ this.cdr.detectChanges();
1432
+ this.minDateStartOfDay = oldMinDate;
1433
+ // END HACK
1434
+ if (this.sameMonthOnly) {
1435
+ if (this.selectedDates.length >= 2) {
1436
+ if (date < dateFns.startOfMonth(this.selectedDates[0]) || date > dateFns.endOfMonth(this.selectedDates[0])) {
1437
+ this.selectedDates = [date];
1438
+ }
1439
+ }
1440
+ this.determineMinAndMaxDates();
1441
+ }
1442
+ this.setInnerValueAndNotify(this.selectedDates);
1443
+ setTimeout(function () {
1444
+ _this.datePickerRef.close = _this.datePickingClosingFn;
1445
+ });
1446
+ }
1447
+ else {
1448
+ this.notifyNewDate();
1449
+ }
1450
+ };
1451
+ DateTimePickerComponent.prototype.determineMinAndMaxDates = function () {
1452
+ if (this.sameMonthOnly) {
1453
+ if (this.selectedDates.length >= 2) {
1454
+ this.setMinDate(dateFns.startOfMonth(this.selectedDates[0]));
1455
+ this.setMaxDate(dateFns.endOfMonth(this.selectedDates[0]));
1456
+ }
1457
+ else {
1458
+ this.setMinDate(this.minDate);
1459
+ this.setMaxDate(this.maxDate);
1460
+ }
1131
1461
  }
1132
1462
  else {
1133
- this.setInnerValueAndNotify(date);
1463
+ this.setMinDate(this.minDate);
1464
+ this.setMinDate(this.maxDate);
1465
+ }
1466
+ };
1467
+ DateTimePickerComponent.prototype.notifyNewDate = function () {
1468
+ var nativeInputValue = this.nativeInputRef.nativeElement.value;
1469
+ var parsedHours = Number(this.hours);
1470
+ var parsedMinutes = Number(this.minutes);
1471
+ // if we dont have the time element
1472
+ if (!this.showTimeInput) {
1473
+ if (!stringIsSetAndFilled(nativeInputValue)) {
1474
+ this.setInnerValueAndNotify(null);
1475
+ return;
1476
+ }
1477
+ if (this.valueForMaterialDatePicker instanceof Date) {
1478
+ this.setInnerValueAndNotify(this.valueForMaterialDatePicker);
1479
+ return;
1480
+ }
1481
+ }
1482
+ // when all inputs are empty
1483
+ if (!stringIsSetAndFilled(nativeInputValue) && !stringIsSetAndFilled(this.hours) && !stringIsSetAndFilled(this.minutes)) {
1484
+ this.setInnerValueAndNotify(null);
1485
+ return;
1486
+ }
1487
+ // if we have date and time
1488
+ if (stringIsSetAndFilled(this.hours) &&
1489
+ Number.isFinite(parsedHours) &&
1490
+ parsedHours >= 0 &&
1491
+ parsedHours <= 23 &&
1492
+ stringIsSetAndFilled(this.minutes) &&
1493
+ Number.isFinite(parsedMinutes) &&
1494
+ parsedMinutes >= 0 &&
1495
+ parsedMinutes <= 59 &&
1496
+ this.valueForMaterialDatePicker instanceof Date) {
1497
+ var newDateWithHours = new Date(this.valueForMaterialDatePicker.setHours(parsedHours));
1498
+ var newDateWithMinutes = new Date(newDateWithHours.setMinutes(parsedMinutes));
1499
+ this.setInnerValueAndNotify(newDateWithMinutes);
1500
+ return;
1134
1501
  }
1502
+ if (this.invalidTimeAsMidnight) {
1503
+ if (this.valueForMaterialDatePicker instanceof Date) {
1504
+ this.setInnerValueAndNotify(this.valueForMaterialDatePicker);
1505
+ return;
1506
+ }
1507
+ }
1508
+ // all other cases, we are not in a valid state
1509
+ this.setInnerValueAndNotify(invalidDateKey);
1135
1510
  };
1136
- DatepickerComponent.prototype.writeValue = function (value) {
1511
+ DateTimePickerComponent.prototype.writeValue = function (value) {
1137
1512
  _super.prototype.writeValue.call(this, value);
1138
- this.valueForMaterialDatePicker = value === invalidDateKey ? null : value;
1513
+ if (Array.isArray(value)) {
1514
+ this.selectedDates = value;
1515
+ this.determineMinAndMaxDates();
1516
+ this.valueForMaterialDatePicker = null;
1517
+ }
1518
+ else {
1519
+ this.valueForMaterialDatePicker = value === invalidDateKey ? null : value;
1520
+ if (value instanceof Date) {
1521
+ this.hours = String(value.getHours());
1522
+ this.minutes = String(value.getMinutes());
1523
+ this.formatTime();
1524
+ }
1525
+ else {
1526
+ this.hours = '';
1527
+ this.minutes = '';
1528
+ }
1529
+ }
1139
1530
  };
1140
1531
  // nativeValueChanged is called when the internal text value changes, but not
1141
1532
  // when the date is changed via the date picker. We need this so that we can
1142
1533
  // determine if the datepicker is empty or invalid.
1143
- DatepickerComponent.prototype.nativeValueChanged = function (event) {
1144
- var nativeInputValue = event.target.value;
1145
- var date = this.valueForMaterialDatePicker;
1534
+ DateTimePickerComponent.prototype.nativeValueChanged = function () {
1146
1535
  if (this.datePickerRef.opened) {
1147
1536
  // if the user is typing instead of using the picker, close it.
1148
1537
  this.datePickerRef.close();
1149
1538
  }
1150
- if (isNullOrUndefined(date) && stringIsSetAndNotEmpty(nativeInputValue)) {
1151
- this.setInnerValueAndNotify(invalidDateKey);
1152
- }
1153
- else {
1154
- this.setInnerValueAndNotify(date);
1155
- }
1539
+ this.notifyNewDate();
1156
1540
  };
1157
- DatepickerComponent.prototype.resetToNull = function () {
1541
+ DateTimePickerComponent.prototype.resetToNull = function () {
1158
1542
  this.setInnerValueAndNotify(null);
1159
1543
  this.valueForMaterialDatePicker = null;
1160
1544
  this.nativeInputRef.nativeElement.value = null;
1545
+ this.hours = '';
1546
+ this.minutes = '';
1547
+ this.selectedDates = [];
1161
1548
  };
1162
- return DatepickerComponent;
1163
- }(ValueAccessorBase));
1164
- DatepickerComponent.decorators = [
1549
+ DateTimePickerComponent.prototype.formatTime = function () {
1550
+ if (Number.isFinite(Number(this.hours)) && this.hours.length === 1) {
1551
+ this.hours = '0' + this.hours;
1552
+ }
1553
+ if (Number.isFinite(Number(this.minutes)) && this.minutes.length === 1) {
1554
+ this.minutes = '0' + this.minutes;
1555
+ }
1556
+ };
1557
+ DateTimePickerComponent.prototype.touchDate = function () {
1558
+ this.dateTouched = true;
1559
+ this.determineAllTouched();
1560
+ };
1561
+ DateTimePickerComponent.prototype.touchHours = function () {
1562
+ this.hoursTouched = true;
1563
+ this.determineAllTouched();
1564
+ };
1565
+ DateTimePickerComponent.prototype.touchMinutes = function () {
1566
+ this.minutesTouched = true;
1567
+ this.determineAllTouched();
1568
+ };
1569
+ DateTimePickerComponent.prototype.determineAllTouched = function () {
1570
+ if ((this.dateTouched && this.hoursTouched && this.minutesTouched) || (this.dateTouched && !this.showTimeInput)) {
1571
+ this.touch();
1572
+ }
1573
+ };
1574
+ DateTimePickerComponent.prototype.getDefaultTranslation = function (key) {
1575
+ var _this = this;
1576
+ switch (key) {
1577
+ case 'placeholder':
1578
+ return function () { var _a; return (_a = _this.placeholder) !== null && _a !== void 0 ? _a : 'Select date'; };
1579
+ case 'selectDays':
1580
+ return function () { return 'Select day(s)'; };
1581
+ case 'selectedDate':
1582
+ return function (d) { return d.toLocaleDateString(); };
1583
+ case 'daysSelected':
1584
+ return function (amount) { return amount + " days selected"; };
1585
+ case 'selectedInMonth':
1586
+ return function (d) { return " in " + dateFns.format(d, 'MMMM'); };
1587
+ }
1588
+ };
1589
+ DateTimePickerComponent.prototype.getTranslation = function (key, params) {
1590
+ if (params === void 0) { params = null; }
1591
+ var _a, _b, _c;
1592
+ if (key === 'placeholder' && this.multiple) {
1593
+ return '';
1594
+ }
1595
+ return (_c = (_b = (_a = this.translations) === null || _a === void 0 ? void 0 : _a[key]) === null || _b === void 0 ? void 0 : _b.call(_a, params)) !== null && _c !== void 0 ? _c : this.getDefaultTranslation(key)(params);
1596
+ };
1597
+ return DateTimePickerComponent;
1598
+ }(MultipleValueAccessorBase));
1599
+ DateTimePickerComponent.decorators = [
1165
1600
  { type: core.Component, args: [{
1166
- selector: 'klp-form-datepicker',
1167
- template: "<div class=\"componentContainer\" [ngClass]=\"{showErrors: isInErrorState()}\">\n\t<mat-form-field [floatLabel]=\"'never'\">\n\t\t<input\n\t\t\t#nativeInput\n\t\t\tmatInput\n\t\t\t[matDatepicker]=\"picker\"\n\t\t\t[(ngModel)]=\"valueForMaterialDatePicker\"\n\t\t\t(dateInput)=\"dateChanged($event)\"\n\t\t\t(input)=\"nativeValueChanged($event)\"\n\t\t\t[min]=\"minDateStartOfDay\"\n\t\t\t[max]=\"maxDateEndOfDay\"\n\t\t\t[placeholder]=\"placeholder\"\n\t\t\t(click)=\"picker.open()\"\n\t\t\t(blur)=\"touch()\"\n\t\t>\n\t\t<mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n\t\t<mat-datepicker #picker\n\t\t></mat-datepicker>\n\t</mat-form-field>\n\t<button *ngIf=\"clearable\" class=\"clearButton\" (click)=\"resetToNull()\">\u00D7</button>\n</div>\n",
1601
+ selector: 'klp-form-date-time-picker',
1602
+ template: "<div class=\"componentContainer\" [ngClass]=\"{showErrors: isInErrorState()}\">\n\t<div class=\"dateContainer\" [ngClass]=\"{noRightBorder: !showTimeInput && clearable && !disabled, disabled: disabled}\">\n\t\t<mat-form-field floatLabel=\"never\">\n\t\t\t<div *ngIf=\"multiple\" class=\"daysSelectedCaption\" (click)=\"picker.open()\" [ngClass]=\"{disabled: disabled}\">\n\t\t\t\t<ng-container *ngIf=\"selectedDates.length >= 2\">\n\t\t\t\t\t<span>{{getTranslation('daysSelected', selectedDates.length)}}</span>\n\t\t\t\t\t<span *ngIf=\"getSelectedMonths() === 1\">{{getTranslation('selectedInMonth', selectedDates[0])}}</span>\n\t\t\t\t</ng-container>\n\t\t\t\t<span *ngIf=\"selectedDates.length === 1\">{{getTranslation('selectedDate', selectedDates[0])}}</span>\n\t\t\t\t<span *ngIf=\"selectedDates.length === 0\" class=\"placeholderForMultipleSelection\">{{getTranslation('selectDays')}}</span>\n\t\t\t</div>\n\t\t\t<input\n\t\t\t\t#nativeInput\n\t\t\t\tmatInput\n\t\t\t\t[matDatepicker]=\"picker\"\n\t\t\t\t[matDatepickerFilter]=\"filterDates\"\n\t\t\t\t[(ngModel)]=\"valueForMaterialDatePicker\"\n\t\t\t\t(dateInput)=\"dateChanged($event)\"\n\t\t\t\t(input)=\"nativeValueChanged()\"\n\t\t\t\t[min]=\"minDateStartOfDay\"\n\t\t\t\t[max]=\"maxDateEndOfDay\"\n\t\t\t\t[placeholder]=\"getTranslation('placeholder')\"\n\t\t\t\t(click)=\"picker.open()\"\n\t\t\t\t(blur)=\"touchDate()\"\n\t\t\t\t[ngClass]=\"{inputForMultipleDays: multiple}\"\n\t\t\t>\n\t\t\t<mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n\t\t\t<mat-datepicker\n\t\t\t\t#picker\n\t\t\t\t[dateClass]=\"isSelected\"\n\t\t\t></mat-datepicker>\n\t\t</mat-form-field>\n\t</div>\n\t<div class=\"timeContainer\" *ngIf=\"showTimeInput\" [ngClass]=\"{disabled: disabled}\">\n\t\t<input maxlength=\"2\" placeholder=\"__\" [disabled]=\"disabled\" [(ngModel)]=\"hours\" (ngModelChange)=\"notifyNewDate()\" (blur)=\"formatTime(); touchHours()\">\n\t\t<div class=\"divider\">:</div>\n\t\t<input maxlength=\"2\" placeholder=\"__\" [disabled]=\"disabled\" [(ngModel)]=\"minutes\" (ngModelChange)=\"notifyNewDate()\" (blur)=\"formatTime(); touchMinutes()\">\n\t</div>\n\t<button *ngIf=\"clearable && !disabled\" class=\"clearButton\" (click)=\"resetToNull()\" [ngClass]=\"{withoutSpacing: !showTimeInput}\">\u00D7</button>\n</div>\n",
1168
1603
  providers: [
1169
- { provide: forms.NG_VALUE_ACCESSOR, useExisting: DatepickerComponent, multi: true },
1170
- { provide: core$1.MAT_DATE_FORMATS,
1171
- deps: [DatepickerComponent, [new core.Optional(), KLP_DATE_FORMATS]],
1604
+ { provide: forms.NG_VALUE_ACCESSOR, useExisting: DateTimePickerComponent, multi: true },
1605
+ {
1606
+ provide: core$1.MAT_DATE_FORMATS,
1607
+ deps: [DateTimePickerComponent, [new core.Optional(), KLP_DATE_FORMATS]],
1172
1608
  useFactory: matDateFormatsFactory,
1173
1609
  }
1174
1610
  ],
1175
- styles: [":host{display:block}:host ::ng-deep mat-form-field{display:block;height:100%}:host ::ng-deep mat-form-field.mat-focused .mat-form-field-label,:host ::ng-deep mat-form-field .mat-form-field-label{color:#adadad}:host ::ng-deep .mat-datepicker-toggle-active{color:#666}:host ::ng-deep .mat-form-field-wrapper{padding-bottom:none}:host ::ng-deep .mat-form-field-flex{flex-direction:row-reverse}:host ::ng-deep .mat-form-field-infix{border-top:none}:host ::ng-deep .mat-form-field-suffix{margin-right:.625rem}:host ::ng-deep .mat-form-field-suffix:hover .mat-button-focus-overlay{opacity:.1}:host ::ng-deep .mat-form-field-underline{display:none}.componentContainer{-moz-transition:all .2s ease-in;-ms-transition:all .2s ease-in;-o-transition:all .2s ease-in;-webkit-transition:all .2s ease-in;border:1px solid #e6ecf5;border-radius:2px;box-shadow:none;color:#888da8;display:block;font-size:14px;height:42px;padding:.375rem .625rem;position:relative;transition:all .2s ease-in;width:100%}.componentContainer::-webkit-input-placeholder{color:#adadad}.componentContainer:-moz-placeholder,.componentContainer::-moz-placeholder{color:#adadad}.componentContainer:-ms-input-placeholder{color:#adadad}.componentContainer:focus{border-color:#3ed778;box-shadow:none;outline:0 none}.componentContainer.input-sm{height:30px}.componentContainer.input-lg{height:50px}.componentContainer.error{background-color:#ffeff4;border-color:#ff3c7e}.componentContainer.valid{background-color:#ebfaeb;border-color:#37c936;color:#278d26}.componentContainer.showErrors{border-color:#ff8000}.componentContainer .clearButton{align-items:center;background:none;border:none;bottom:0;color:#7b7b7b;display:flex;font-size:18px;position:absolute;right:1.25rem;top:0}"]
1611
+ styles: [":host{display:block}:host ::ng-deep mat-form-field{display:block;height:100%}:host ::ng-deep mat-form-field.mat-focused .mat-form-field-label,:host ::ng-deep mat-form-field .mat-form-field-label{color:#adadad}:host ::ng-deep .mat-datepicker-toggle-active{color:#666}:host ::ng-deep .mat-form-field-wrapper{padding-bottom:0}:host ::ng-deep .mat-form-field-flex{flex-direction:row-reverse}:host ::ng-deep .mat-form-field-infix{border-top:none;width:auto}:host ::ng-deep .mat-form-field-suffix{margin-right:.625rem}:host ::ng-deep .mat-form-field-suffix:hover .mat-button-focus-overlay{opacity:.1}:host ::ng-deep .mat-form-field-underline{display:none}:host ::ng-deep .daysSelectedCaption{cursor:pointer}:host ::ng-deep .daysSelectedCaption.disabled{cursor:zoom-in}:host ::ng-deep .inputForMultipleDays{display:none}.componentContainer{border-radius:2px;color:#888da8;display:flex;position:relative}.componentContainer .placeholderForMultipleSelection{color:#adadad}.componentContainer.showErrors .clearButton.withoutSpacing,.componentContainer.showErrors .dateContainer,.componentContainer.showErrors .timeContainer{border-color:#ff8000}.componentContainer .clearButton{align-items:center;background:#fff;border:1px solid #e6ecf5;color:#7b7b7b;display:flex;flex:0 0 auto;font-size:18px;margin-left:1.25rem;padding:6px 14px}.componentContainer .clearButton.withoutSpacing{border-left:none;margin-left:0}.componentContainer .clearButton:disabled{background:#f9f9f9;border:1px solid #e6ecf5}.componentContainer .dateContainer{background:#fff;border:1px solid #e6ecf5;flex:1 1 auto;padding:6px}.componentContainer .dateContainer.noRightBorder{border-right:none}.componentContainer .dateContainer.disabled{background:#f9f9f9}.componentContainer .timeContainer{align-items:center;background:#fff;border:1px solid #e6ecf5;display:flex;flex:0 0 auto;margin-left:1.25rem;padding:6px .625rem}.componentContainer .timeContainer.disabled{background:#f9f9f9}.componentContainer .timeContainer input{border:none;color:#888da8;padding:0;text-align:center;width:20px}.componentContainer .timeContainer input::-moz-placeholder{color:#adadad}.componentContainer .timeContainer input:-ms-input-placeholder{color:#adadad}.componentContainer .timeContainer input::placeholder{color:#adadad}.componentContainer .timeContainer .divider{margin:0 .3125rem}"]
1176
1612
  },] }
1177
1613
  ];
1178
- DatepickerComponent.propDecorators = {
1614
+ DateTimePickerComponent.ctorParameters = function () { return [
1615
+ { type: FormElementComponent, decorators: [{ type: core.Host }, { type: core.Optional }] },
1616
+ { type: forms.ControlContainer, decorators: [{ type: core.Host }, { type: core.Optional }] },
1617
+ { type: undefined, decorators: [{ type: core.Inject, args: [DATE_TIME_PICKER_TRANSLATIONS,] }, { type: core.Optional }] },
1618
+ { type: core.ChangeDetectorRef }
1619
+ ]; };
1620
+ DateTimePickerComponent.propDecorators = {
1179
1621
  minDate: [{ type: core.Input }],
1180
1622
  maxDate: [{ type: core.Input }],
1623
+ sameMonthOnly: [{ type: core.Input }],
1181
1624
  format: [{ type: core.Input }],
1182
1625
  placeholder: [{ type: core.Input }],
1183
1626
  clearable: [{ type: core.Input }],
1627
+ showTimeInput: [{ type: core.Input }],
1628
+ invalidTimeAsMidnight: [{ type: core.Input }],
1184
1629
  nativeInputRef: [{ type: core.ViewChild, args: ['nativeInput',] }],
1185
1630
  datePickerRef: [{ type: core.ViewChild, args: ['picker',] }]
1186
1631
  };
@@ -1215,14 +1660,17 @@
1215
1660
  ],
1216
1661
  declarations: [
1217
1662
  ValueAccessorBase,
1663
+ MultipleValueAccessorBase,
1218
1664
  ButtonComponent,
1219
1665
  CheckboxComponent,
1220
- DatepickerComponent,
1666
+ DatePickerComponent,
1667
+ DateTimePickerComponent,
1221
1668
  EmailInputComponent,
1222
1669
  LoadingIndicatorComponent,
1223
1670
  NumberInputComponent,
1224
1671
  PasswordFieldComponent,
1225
1672
  SelectComponent,
1673
+ SelectFooterComponent,
1226
1674
  SortableItemsComponent,
1227
1675
  TextInputComponent,
1228
1676
  ToggleComponent,
@@ -1235,14 +1683,17 @@
1235
1683
  ],
1236
1684
  exports: [
1237
1685
  ValueAccessorBase,
1686
+ MultipleValueAccessorBase,
1238
1687
  ButtonComponent,
1239
- DatepickerComponent,
1688
+ DatePickerComponent,
1689
+ DateTimePickerComponent,
1240
1690
  CheckboxComponent,
1241
1691
  EmailInputComponent,
1242
1692
  LoadingIndicatorComponent,
1243
1693
  NumberInputComponent,
1244
1694
  PasswordFieldComponent,
1245
1695
  SelectComponent,
1696
+ SelectFooterComponent,
1246
1697
  SortableItemsComponent,
1247
1698
  TextInputComponent,
1248
1699
  ToggleComponent,
@@ -1266,8 +1717,11 @@
1266
1717
 
1267
1718
  exports.ButtonComponent = ButtonComponent;
1268
1719
  exports.CheckboxComponent = CheckboxComponent;
1720
+ exports.DATE_PICKER_TRANSLATIONS = DATE_PICKER_TRANSLATIONS;
1721
+ exports.DATE_TIME_PICKER_TRANSLATIONS = DATE_TIME_PICKER_TRANSLATIONS;
1269
1722
  exports.DEFAULT_ERROR_MESSAGES = DEFAULT_ERROR_MESSAGES;
1270
- exports.DatepickerComponent = DatepickerComponent;
1723
+ exports.DatePickerComponent = DatePickerComponent;
1724
+ exports.DateTimePickerComponent = DateTimePickerComponent;
1271
1725
  exports.EmailInputComponent = EmailInputComponent;
1272
1726
  exports.FORM_ERROR_MESSAGES = FORM_ERROR_MESSAGES;
1273
1727
  exports.FormCaptionComponent = FormCaptionComponent;
@@ -1277,10 +1731,13 @@
1277
1731
  exports.FormSubmitButtonComponent = FormSubmitButtonComponent;
1278
1732
  exports.KLP_DATE_FORMATS = KLP_DATE_FORMATS;
1279
1733
  exports.LoadingIndicatorComponent = LoadingIndicatorComponent;
1734
+ exports.MultipleValueAccessorBase = MultipleValueAccessorBase;
1280
1735
  exports.NgxEnhancyFormsModule = NgxEnhancyFormsModule;
1281
1736
  exports.NumberInputComponent = NumberInputComponent;
1282
1737
  exports.PasswordFieldComponent = PasswordFieldComponent;
1738
+ exports.SELECT_TRANSLATIONS = SELECT_TRANSLATIONS;
1283
1739
  exports.SelectComponent = SelectComponent;
1740
+ exports.SelectFooterComponent = SelectFooterComponent;
1284
1741
  exports.SortableItemsComponent = SortableItemsComponent;
1285
1742
  exports.SubFormDirective = SubFormDirective;
1286
1743
  exports.TextInputComponent = TextInputComponent;