@balinasoftware/balinaui-components 3.3.8 → 3.3.10

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, EventEmitter, HostListener, Output, Input } from '@angular/core';
2
+ import { Component, EventEmitter, HostListener, Output, Input, HostBinding } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as i2 from '@angular/router';
@@ -110,29 +110,52 @@ class Button {
110
110
  type = 'button';
111
111
  disabled = false;
112
112
  loading = false;
113
+ /**
114
+ * Controls whether the button is clickable.
115
+ */
116
+ clickable = true;
117
+ /**
118
+ * Developer custom CSS class.
119
+ */
113
120
  customClass = '';
114
121
  // =========================================
122
+ // HOST CLASSES
123
+ // =========================================
124
+ get buttonClickable() {
125
+ return (this.clickable &&
126
+ !this.disabled &&
127
+ !this.loading);
128
+ }
129
+ get buttonDisabled() {
130
+ return (this.disabled ||
131
+ this.loading);
132
+ }
133
+ // =========================================
115
134
  // OUTPUTS
116
135
  // =========================================
136
+ /**
137
+ * Developer click event.
138
+ */
117
139
  clicked = new EventEmitter();
118
140
  // =========================================
119
- // CLICK
141
+ // CLICK HANDLER
120
142
  // =========================================
121
143
  onClick(event) {
122
144
  if (this.disabled ||
123
- this.loading) {
145
+ this.loading ||
146
+ !this.clickable) {
124
147
  event.preventDefault();
148
+ event.stopPropagation();
125
149
  return;
126
150
  }
127
- // Developer event
128
151
  this.clicked.emit(event);
129
152
  }
130
153
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: Button, deps: [], target: i0.ɵɵFactoryTarget.Component });
131
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: Button, isStandalone: true, selector: "lib-button", inputs: { label: "label", type: "type", disabled: "disabled", loading: "loading", customClass: "customClass" }, outputs: { clicked: "clicked" }, ngImport: i0, template: "<button\n class=\"balina-button\"\n [class]=\"customClass\"\n [type]=\"type\"\n [disabled]=\"disabled || loading\"\n [attr.aria-busy]=\"loading\"\n (click)=\"onClick($event)\"\n>\n\n @if (loading) {\n\n <span\n class=\"button-spinner\"\n aria-hidden=\"true\"\n ></span>\n\n <span>\n Loading...\n </span>\n\n } @else {\n\n <span class=\"button-label\">\n {{ label }}\n </span>\n\n }\n\n</button>", styles: [".balina-button{--button-width: auto;--button-height: 44px;--button-padding: 0 22px;--button-background: #68479b;--button-background-hover: #593b84;--button-background-active: #4b326f;--button-text-color: #ffffff;--button-border: 1px solid #68479b;--button-radius: 6px;--button-font-family: Arial, Helvetica, sans-serif;--button-font-size: 14px;--button-font-weight: 600;--button-gap: 8px;--button-shadow: 0 2px 5px rgba(0, 0, 0, .08);--button-disabled-background: #dddddd;--button-disabled-text: #999999;--button-disabled-border: #dddddd;width:var(--button-width);min-height:var(--button-height);padding:var(--button-padding);display:inline-flex;align-items:center;justify-content:center;gap:var(--button-gap);box-sizing:border-box;border:var(--button-border);border-radius:var(--button-radius);background:var(--button-background);color:var(--button-text-color);font-family:var(--button-font-family);font-size:var(--button-font-size);font-weight:var(--button-font-weight);box-shadow:var(--button-shadow);outline:none;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color .2s ease,border-color .2s ease,box-shadow .2s ease,transform .1s ease}.balina-button:hover:not(:disabled){background:var(--button-background-hover)}.balina-button:active:not(:disabled){background:var(--button-background-active);transform:translateY(1px)}.balina-button:focus-visible{box-shadow:0 0 0 3px #68479b33}.balina-button:disabled{background:var(--button-disabled-background);color:var(--button-disabled-text);border-color:var(--button-disabled-border);cursor:not-allowed;box-shadow:none;transform:none}.balina-button[aria-busy=true]{cursor:wait}.button-spinner{width:16px;height:16px;box-sizing:border-box;border:2px solid rgba(255,255,255,.4);border-top-color:var(--button-text-color);border-radius:50%;animation:button-spin .7s linear infinite}@keyframes button-spin{to{transform:rotate(360deg)}}.button-label{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap}@media(max-width:768px){.balina-button{min-height:var(--button-height);font-size:var(--button-font-size)}}\n"] });
154
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: Button, isStandalone: true, selector: "lib-button", inputs: { label: "label", type: "type", disabled: "disabled", loading: "loading", clickable: "clickable", customClass: "customClass" }, outputs: { clicked: "clicked" }, host: { properties: { "class": "this.customClass", "class.button-clickable": "this.buttonClickable", "class.button-disabled": "this.buttonDisabled" } }, ngImport: i0, template: "<button\n class=\"balina-button\"\n\n [type]=\"type\"\n\n [disabled]=\"\n disabled ||\n loading ||\n !clickable\n \"\n\n [attr.aria-disabled]=\"\n disabled ||\n loading ||\n !clickable\n \"\n\n [attr.aria-busy]=\"loading\"\n\n (click)=\"onClick($event)\"\n>\n\n <!-- =====================================\n LOADING\n ===================================== -->\n\n @if (loading) {\n\n <span\n class=\"button-spinner\"\n aria-hidden=\"true\"\n ></span>\n\n <span class=\"button-loading-text\">\n Loading...\n </span>\n\n }\n\n <!-- =====================================\n NORMAL\n ===================================== -->\n\n @else {\n\n <span class=\"button-label\">\n {{ label }}\n </span>\n\n }\n\n</button>", styles: [":host{--button-width: auto;--button-height: 44px;--button-padding: 0 22px;--button-background: #68479b;--button-background-hover: #593b84;--button-background-active: #4b326f;--button-text-color: #ffffff;--button-border: 1px solid #68479b;--button-radius: 6px;--button-font-family: Arial, Helvetica, sans-serif;--button-font-size: 14px;--button-font-weight: 600;--button-gap: 8px;--button-shadow: 0 2px 5px rgba(0, 0, 0, .08);--button-disabled-background: #dddddd;--button-disabled-text: #999999;--button-disabled-border: #dddddd;--button-focus-ring: rgba(104, 71, 155, .2);--button-spinner-size: 16px;--button-spinner-border: 2px;display:inline-block;width:var(--button-width);box-sizing:border-box;font-family:var(--button-font-family)}.balina-button{width:100%;min-height:var(--button-height);padding:var(--button-padding);display:inline-flex;align-items:center;justify-content:center;gap:var(--button-gap);box-sizing:border-box;border:var(--button-border);border-radius:var(--button-radius);background:var(--button-background);color:var(--button-text-color);font-family:var(--button-font-family);font-size:var(--button-font-size);font-weight:var(--button-font-weight);line-height:1;box-shadow:var(--button-shadow);outline:none;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;transition:background-color .2s ease,border-color .2s ease,box-shadow .2s ease,transform .1s ease,color .2s ease}:host(.button-clickable) .balina-button{cursor:pointer}:host(:not(.button-clickable)) .balina-button{cursor:default}:host(.button-clickable) .balina-button:hover{background:var(--button-background-hover)}:host(.button-clickable) .balina-button:active{background:var(--button-background-active);transform:translateY(1px)}.balina-button:focus-visible{box-shadow:0 0 0 3px var(--button-focus-ring)}:host(.button-disabled) .balina-button{background:var(--button-disabled-background);color:var(--button-disabled-text);border-color:var(--button-disabled-border);cursor:not-allowed;box-shadow:none;transform:none}.balina-button[aria-busy=true]{cursor:wait}.button-label{display:inline-flex;align-items:center;justify-content:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.button-loading-text{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap}.button-spinner{width:var(--button-spinner-size);height:var(--button-spinner-size);flex:0 0 auto;box-sizing:border-box;border:var(--button-spinner-border) solid rgba(255,255,255,.4);border-top-color:var(--button-text-color);border-radius:50%;animation:button-spin .7s linear infinite}@keyframes button-spin{to{transform:rotate(360deg)}}@media(max-width:768px){:host{width:var(--button-width)}.balina-button{min-height:var(--button-height);font-size:var(--button-font-size)}}\n"] });
132
155
  }
133
156
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: Button, decorators: [{
134
157
  type: Component,
135
- args: [{ selector: 'lib-button', standalone: true, imports: [], template: "<button\n class=\"balina-button\"\n [class]=\"customClass\"\n [type]=\"type\"\n [disabled]=\"disabled || loading\"\n [attr.aria-busy]=\"loading\"\n (click)=\"onClick($event)\"\n>\n\n @if (loading) {\n\n <span\n class=\"button-spinner\"\n aria-hidden=\"true\"\n ></span>\n\n <span>\n Loading...\n </span>\n\n } @else {\n\n <span class=\"button-label\">\n {{ label }}\n </span>\n\n }\n\n</button>", styles: [".balina-button{--button-width: auto;--button-height: 44px;--button-padding: 0 22px;--button-background: #68479b;--button-background-hover: #593b84;--button-background-active: #4b326f;--button-text-color: #ffffff;--button-border: 1px solid #68479b;--button-radius: 6px;--button-font-family: Arial, Helvetica, sans-serif;--button-font-size: 14px;--button-font-weight: 600;--button-gap: 8px;--button-shadow: 0 2px 5px rgba(0, 0, 0, .08);--button-disabled-background: #dddddd;--button-disabled-text: #999999;--button-disabled-border: #dddddd;width:var(--button-width);min-height:var(--button-height);padding:var(--button-padding);display:inline-flex;align-items:center;justify-content:center;gap:var(--button-gap);box-sizing:border-box;border:var(--button-border);border-radius:var(--button-radius);background:var(--button-background);color:var(--button-text-color);font-family:var(--button-font-family);font-size:var(--button-font-size);font-weight:var(--button-font-weight);box-shadow:var(--button-shadow);outline:none;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color .2s ease,border-color .2s ease,box-shadow .2s ease,transform .1s ease}.balina-button:hover:not(:disabled){background:var(--button-background-hover)}.balina-button:active:not(:disabled){background:var(--button-background-active);transform:translateY(1px)}.balina-button:focus-visible{box-shadow:0 0 0 3px #68479b33}.balina-button:disabled{background:var(--button-disabled-background);color:var(--button-disabled-text);border-color:var(--button-disabled-border);cursor:not-allowed;box-shadow:none;transform:none}.balina-button[aria-busy=true]{cursor:wait}.button-spinner{width:16px;height:16px;box-sizing:border-box;border:2px solid rgba(255,255,255,.4);border-top-color:var(--button-text-color);border-radius:50%;animation:button-spin .7s linear infinite}@keyframes button-spin{to{transform:rotate(360deg)}}.button-label{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap}@media(max-width:768px){.balina-button{min-height:var(--button-height);font-size:var(--button-font-size)}}\n"] }]
158
+ args: [{ selector: 'lib-button', standalone: true, imports: [], template: "<button\n class=\"balina-button\"\n\n [type]=\"type\"\n\n [disabled]=\"\n disabled ||\n loading ||\n !clickable\n \"\n\n [attr.aria-disabled]=\"\n disabled ||\n loading ||\n !clickable\n \"\n\n [attr.aria-busy]=\"loading\"\n\n (click)=\"onClick($event)\"\n>\n\n <!-- =====================================\n LOADING\n ===================================== -->\n\n @if (loading) {\n\n <span\n class=\"button-spinner\"\n aria-hidden=\"true\"\n ></span>\n\n <span class=\"button-loading-text\">\n Loading...\n </span>\n\n }\n\n <!-- =====================================\n NORMAL\n ===================================== -->\n\n @else {\n\n <span class=\"button-label\">\n {{ label }}\n </span>\n\n }\n\n</button>", styles: [":host{--button-width: auto;--button-height: 44px;--button-padding: 0 22px;--button-background: #68479b;--button-background-hover: #593b84;--button-background-active: #4b326f;--button-text-color: #ffffff;--button-border: 1px solid #68479b;--button-radius: 6px;--button-font-family: Arial, Helvetica, sans-serif;--button-font-size: 14px;--button-font-weight: 600;--button-gap: 8px;--button-shadow: 0 2px 5px rgba(0, 0, 0, .08);--button-disabled-background: #dddddd;--button-disabled-text: #999999;--button-disabled-border: #dddddd;--button-focus-ring: rgba(104, 71, 155, .2);--button-spinner-size: 16px;--button-spinner-border: 2px;display:inline-block;width:var(--button-width);box-sizing:border-box;font-family:var(--button-font-family)}.balina-button{width:100%;min-height:var(--button-height);padding:var(--button-padding);display:inline-flex;align-items:center;justify-content:center;gap:var(--button-gap);box-sizing:border-box;border:var(--button-border);border-radius:var(--button-radius);background:var(--button-background);color:var(--button-text-color);font-family:var(--button-font-family);font-size:var(--button-font-size);font-weight:var(--button-font-weight);line-height:1;box-shadow:var(--button-shadow);outline:none;cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;transition:background-color .2s ease,border-color .2s ease,box-shadow .2s ease,transform .1s ease,color .2s ease}:host(.button-clickable) .balina-button{cursor:pointer}:host(:not(.button-clickable)) .balina-button{cursor:default}:host(.button-clickable) .balina-button:hover{background:var(--button-background-hover)}:host(.button-clickable) .balina-button:active{background:var(--button-background-active);transform:translateY(1px)}.balina-button:focus-visible{box-shadow:0 0 0 3px var(--button-focus-ring)}:host(.button-disabled) .balina-button{background:var(--button-disabled-background);color:var(--button-disabled-text);border-color:var(--button-disabled-border);cursor:not-allowed;box-shadow:none;transform:none}.balina-button[aria-busy=true]{cursor:wait}.button-label{display:inline-flex;align-items:center;justify-content:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.button-loading-text{display:inline-flex;align-items:center;justify-content:center;white-space:nowrap}.button-spinner{width:var(--button-spinner-size);height:var(--button-spinner-size);flex:0 0 auto;box-sizing:border-box;border:var(--button-spinner-border) solid rgba(255,255,255,.4);border-top-color:var(--button-text-color);border-radius:50%;animation:button-spin .7s linear infinite}@keyframes button-spin{to{transform:rotate(360deg)}}@media(max-width:768px){:host{width:var(--button-width)}.balina-button{min-height:var(--button-height);font-size:var(--button-font-size)}}\n"] }]
136
159
  }], propDecorators: { label: [{
137
160
  type: Input
138
161
  }], type: [{
@@ -141,35 +164,75 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
141
164
  type: Input
142
165
  }], loading: [{
143
166
  type: Input
167
+ }], clickable: [{
168
+ type: Input
144
169
  }], customClass: [{
145
170
  type: Input
171
+ }, {
172
+ type: HostBinding,
173
+ args: ['class']
174
+ }], buttonClickable: [{
175
+ type: HostBinding,
176
+ args: ['class.button-clickable']
177
+ }], buttonDisabled: [{
178
+ type: HostBinding,
179
+ args: ['class.button-disabled']
146
180
  }], clicked: [{
147
181
  type: Output
148
182
  }] } });
149
183
 
150
184
  class Card {
185
+ // =========================================
186
+ // INPUTS
187
+ // =========================================
151
188
  title = 'Last 24 hours';
152
189
  month = 'Jul';
153
190
  day = 9;
154
191
  description = '156 flights were monitored with 96.8% on-time performance. Minor delays occurred due to weather and air traffic.';
155
- cardClick = new EventEmitter();
192
+ /**
193
+ * Developer custom CSS class.
194
+ */
156
195
  customClass = '';
157
- clickable = false;
196
+ /**
197
+ * Controls whether the card is clickable.
198
+ */
199
+ clickable = true;
200
+ /**
201
+ * Disables card interaction.
202
+ */
158
203
  disabled = false;
204
+ // =========================================
205
+ // OUTPUTS
206
+ // =========================================
207
+ /**
208
+ * Legacy / specific card click event.
209
+ */
210
+ cardClick = new EventEmitter();
211
+ /**
212
+ * Standard Balina UI developer click event.
213
+ */
159
214
  clicked = new EventEmitter();
215
+ // =========================================
216
+ // CLICK HANDLER
217
+ // =========================================
160
218
  onClick(event) {
161
219
  if (!this.clickable ||
162
220
  this.disabled) {
221
+ event.preventDefault();
222
+ event.stopPropagation();
163
223
  return;
164
224
  }
225
+ // Standard developer event
165
226
  this.clicked.emit(event);
227
+ // Card-specific event
228
+ this.cardClick.emit();
166
229
  }
167
230
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: Card, deps: [], target: i0.ɵɵFactoryTarget.Component });
168
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.2", type: Card, isStandalone: true, selector: "lib-card", inputs: { title: "title", month: "month", day: "day", description: "description", customClass: "customClass", clickable: "clickable", disabled: "disabled" }, outputs: { cardClick: "cardClick", clicked: "clicked" }, ngImport: i0, template: "<div\n class=\"balina-card\"\n [class]=\"customClass\"\n [class.card-clickable]=\"clickable\"\n [class.card-disabled]=\"disabled\"\n (click)=\"onClick($event)\"\n>\n\n <!-- Title -->\n <h2 class=\"card-title\">\n {{ title }}\n </h2>\n\n <!-- Card Content -->\n <div class=\"card-content\">\n\n <!-- Date -->\n <div class=\"card-date\">\n\n <div class=\"card-month\">\n {{ month }}\n </div>\n\n <div class=\"card-line\"></div>\n\n <div class=\"card-day\">\n {{ day }}\n </div>\n\n </div>\n\n <!-- Description -->\n <div class=\"card-description\">\n {{ description }}\n </div>\n\n </div>\n\n</div>", styles: [".balina-card{--card-width: 100%;--card-height: 280px;--card-padding: 28px;--card-background: #ffffff;--card-border: 3px solid #dddddd;--card-radius: 12px;--card-title-color: #000000;--card-description-color: #222222;--card-date-background: #eef5ff;--card-month-color: #2962ff;--card-line-color: #b7b7b7;--card-title-size: 38px;--card-description-size: 20px;--card-month-size: 24px;--card-day-size: 24px;--card-font-family: Arial, Helvetica, sans-serif;width:var(--card-width);min-height:var(--card-height);box-sizing:border-box;padding:var(--card-padding);background:var(--card-background);border:var(--card-border);border-radius:var(--card-radius);font-family:var(--card-font-family);cursor:pointer;transition:box-shadow .2s ease,transform .2s ease}.balina-card:hover{box-shadow:0 4px 12px #00000014;transform:translateY(-1px)}.card-title{margin:0;color:var(--card-title-color);font-size:var(--card-title-size);font-weight:700;line-height:1.2}.card-content{display:flex;align-items:center;gap:28px;margin-top:36px}.card-date{width:92px;height:96px;flex-shrink:0;display:flex;flex-direction:column;align-items:center;justify-content:center;box-sizing:border-box;padding:8px;background:var(--card-date-background);border-radius:10px}.card-month{color:var(--card-month-color);font-size:var(--card-month-size);font-weight:700;line-height:1}.card-line{width:80%;height:2px;margin:7px 0;background:var(--card-line-color)}.card-day{color:#000;font-size:var(--card-day-size);font-weight:600;line-height:1}.card-description{flex:1;color:var(--card-description-color);font-size:var(--card-description-size);font-weight:600;line-height:1.4}@media(max-width:768px){.balina-card{--card-title-size: 30px;--card-description-size: 17px;--card-height: auto;padding:22px}.card-content{gap:18px;margin-top:28px}.card-date{width:80px;height:88px}}@media(max-width:480px){.balina-card{--card-title-size: 26px;--card-description-size: 15px;padding:18px}.card-content{align-items:flex-start;gap:14px}.card-date{width:70px;height:80px}.card-month,.card-day{font-size:20px}}\n"] });
231
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.2", type: Card, isStandalone: true, selector: "lib-card", inputs: { title: "title", month: "month", day: "day", description: "description", customClass: "customClass", clickable: "clickable", disabled: "disabled" }, outputs: { cardClick: "cardClick", clicked: "clicked" }, ngImport: i0, template: "<div\n class=\"balina-card\"\n\n [class]=\"customClass\"\n\n [class.card-clickable]=\"clickable\"\n\n [class.card-disabled]=\"disabled\"\n\n (click)=\"onClick($event)\"\n>\n\n <!-- =====================================\n TITLE\n ===================================== -->\n\n <h2 class=\"card-title\">\n {{ title }}\n </h2>\n\n\n <!-- =====================================\n CONTENT\n ===================================== -->\n\n <div class=\"card-content\">\n\n <!-- ===================================\n DATE\n =================================== -->\n\n <div class=\"card-date\">\n\n <div class=\"card-month\">\n {{ month }}\n </div>\n\n <div class=\"card-line\"></div>\n\n <div class=\"card-day\">\n {{ day }}\n </div>\n\n </div>\n\n\n <!-- ===================================\n DESCRIPTION\n =================================== -->\n\n <div class=\"card-description\">\n\n {{ description }}\n\n </div>\n\n </div>\n\n</div>", styles: [".balina-card{--card-width: 100%;--card-height: 280px;--card-padding: 28px;--card-background: #ffffff;--card-border: 3px solid #dddddd;--card-radius: 12px;--card-title-color: #000000;--card-description-color: #222222;--card-date-background: #eef5ff;--card-month-color: #2962ff;--card-day-color: #000000;--card-line-color: #b7b7b7;--card-title-size: 38px;--card-description-size: 20px;--card-month-size: 24px;--card-day-size: 24px;--card-font-family: Arial, Helvetica, sans-serif;--card-font-weight: 600;--card-hover-shadow: 0 4px 12px rgba(0, 0, 0, .08);--card-hover-transform: translateY(-1px);--card-disabled-background: #f5f5f5;--card-disabled-border: #d0d0d0;--card-disabled-text: #999999;width:var(--card-width);min-height:var(--card-height);padding:var(--card-padding);background:var(--card-background);border:var(--card-border);border-radius:var(--card-radius);font-family:var(--card-font-family);font-weight:var(--card-font-weight);transition:box-shadow .2s ease,transform .2s ease,background-color .2s ease,border-color .2s ease;box-sizing:border-box}.balina-card.card-clickable{cursor:pointer}.balina-card:not(.card-clickable){cursor:default}.balina-card.card-clickable:hover{box-shadow:var(--card-hover-shadow);transform:var(--card-hover-transform)}.balina-card.card-clickable:active{transform:translateY(0)}.card-title{margin:0;color:var(--card-title-color);font-size:var(--card-title-size);font-weight:700;line-height:1.2}.card-content{display:flex;align-items:center;gap:28px;margin-top:36px}.card-date{width:92px;height:96px;flex-shrink:0;display:flex;flex-direction:column;align-items:center;justify-content:center;box-sizing:border-box;padding:8px;background:var(--card-date-background);border-radius:10px}.card-month{color:var(--card-month-color);font-size:var(--card-month-size);font-weight:700;line-height:1}.card-line{width:80%;height:2px;margin:7px 0;background:var(--card-line-color)}.card-day{color:var(--card-day-color);font-size:var(--card-day-size);font-weight:600;line-height:1}.card-description{flex:1;color:var(--card-description-color);font-size:var(--card-description-size);font-weight:600;line-height:1.4}.balina-card.card-disabled{background:var(--card-disabled-background);border-color:var(--card-disabled-border);color:var(--card-disabled-text);cursor:not-allowed;box-shadow:none;transform:none}.balina-card.card-disabled:hover{box-shadow:none;transform:none}.balina-card.card-disabled .card-title,.balina-card.card-disabled .card-description{color:var(--card-disabled-text)}@media(max-width:768px){.balina-card{--card-title-size: 30px;--card-description-size: 17px;--card-height: auto;padding:22px}.card-content{gap:18px;margin-top:28px}.card-date{width:80px;height:88px}}@media(max-width:480px){.balina-card{--card-title-size: 26px;--card-description-size: 15px;padding:18px}.card-content{align-items:flex-start;gap:14px}.card-date{width:70px;height:80px}.card-month,.card-day{font-size:20px}}\n"] });
169
232
  }
170
233
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: Card, decorators: [{
171
234
  type: Component,
172
- args: [{ selector: 'lib-card', standalone: true, imports: [], template: "<div\n class=\"balina-card\"\n [class]=\"customClass\"\n [class.card-clickable]=\"clickable\"\n [class.card-disabled]=\"disabled\"\n (click)=\"onClick($event)\"\n>\n\n <!-- Title -->\n <h2 class=\"card-title\">\n {{ title }}\n </h2>\n\n <!-- Card Content -->\n <div class=\"card-content\">\n\n <!-- Date -->\n <div class=\"card-date\">\n\n <div class=\"card-month\">\n {{ month }}\n </div>\n\n <div class=\"card-line\"></div>\n\n <div class=\"card-day\">\n {{ day }}\n </div>\n\n </div>\n\n <!-- Description -->\n <div class=\"card-description\">\n {{ description }}\n </div>\n\n </div>\n\n</div>", styles: [".balina-card{--card-width: 100%;--card-height: 280px;--card-padding: 28px;--card-background: #ffffff;--card-border: 3px solid #dddddd;--card-radius: 12px;--card-title-color: #000000;--card-description-color: #222222;--card-date-background: #eef5ff;--card-month-color: #2962ff;--card-line-color: #b7b7b7;--card-title-size: 38px;--card-description-size: 20px;--card-month-size: 24px;--card-day-size: 24px;--card-font-family: Arial, Helvetica, sans-serif;width:var(--card-width);min-height:var(--card-height);box-sizing:border-box;padding:var(--card-padding);background:var(--card-background);border:var(--card-border);border-radius:var(--card-radius);font-family:var(--card-font-family);cursor:pointer;transition:box-shadow .2s ease,transform .2s ease}.balina-card:hover{box-shadow:0 4px 12px #00000014;transform:translateY(-1px)}.card-title{margin:0;color:var(--card-title-color);font-size:var(--card-title-size);font-weight:700;line-height:1.2}.card-content{display:flex;align-items:center;gap:28px;margin-top:36px}.card-date{width:92px;height:96px;flex-shrink:0;display:flex;flex-direction:column;align-items:center;justify-content:center;box-sizing:border-box;padding:8px;background:var(--card-date-background);border-radius:10px}.card-month{color:var(--card-month-color);font-size:var(--card-month-size);font-weight:700;line-height:1}.card-line{width:80%;height:2px;margin:7px 0;background:var(--card-line-color)}.card-day{color:#000;font-size:var(--card-day-size);font-weight:600;line-height:1}.card-description{flex:1;color:var(--card-description-color);font-size:var(--card-description-size);font-weight:600;line-height:1.4}@media(max-width:768px){.balina-card{--card-title-size: 30px;--card-description-size: 17px;--card-height: auto;padding:22px}.card-content{gap:18px;margin-top:28px}.card-date{width:80px;height:88px}}@media(max-width:480px){.balina-card{--card-title-size: 26px;--card-description-size: 15px;padding:18px}.card-content{align-items:flex-start;gap:14px}.card-date{width:70px;height:80px}.card-month,.card-day{font-size:20px}}\n"] }]
235
+ args: [{ selector: 'lib-card', standalone: true, imports: [], template: "<div\n class=\"balina-card\"\n\n [class]=\"customClass\"\n\n [class.card-clickable]=\"clickable\"\n\n [class.card-disabled]=\"disabled\"\n\n (click)=\"onClick($event)\"\n>\n\n <!-- =====================================\n TITLE\n ===================================== -->\n\n <h2 class=\"card-title\">\n {{ title }}\n </h2>\n\n\n <!-- =====================================\n CONTENT\n ===================================== -->\n\n <div class=\"card-content\">\n\n <!-- ===================================\n DATE\n =================================== -->\n\n <div class=\"card-date\">\n\n <div class=\"card-month\">\n {{ month }}\n </div>\n\n <div class=\"card-line\"></div>\n\n <div class=\"card-day\">\n {{ day }}\n </div>\n\n </div>\n\n\n <!-- ===================================\n DESCRIPTION\n =================================== -->\n\n <div class=\"card-description\">\n\n {{ description }}\n\n </div>\n\n </div>\n\n</div>", styles: [".balina-card{--card-width: 100%;--card-height: 280px;--card-padding: 28px;--card-background: #ffffff;--card-border: 3px solid #dddddd;--card-radius: 12px;--card-title-color: #000000;--card-description-color: #222222;--card-date-background: #eef5ff;--card-month-color: #2962ff;--card-day-color: #000000;--card-line-color: #b7b7b7;--card-title-size: 38px;--card-description-size: 20px;--card-month-size: 24px;--card-day-size: 24px;--card-font-family: Arial, Helvetica, sans-serif;--card-font-weight: 600;--card-hover-shadow: 0 4px 12px rgba(0, 0, 0, .08);--card-hover-transform: translateY(-1px);--card-disabled-background: #f5f5f5;--card-disabled-border: #d0d0d0;--card-disabled-text: #999999;width:var(--card-width);min-height:var(--card-height);padding:var(--card-padding);background:var(--card-background);border:var(--card-border);border-radius:var(--card-radius);font-family:var(--card-font-family);font-weight:var(--card-font-weight);transition:box-shadow .2s ease,transform .2s ease,background-color .2s ease,border-color .2s ease;box-sizing:border-box}.balina-card.card-clickable{cursor:pointer}.balina-card:not(.card-clickable){cursor:default}.balina-card.card-clickable:hover{box-shadow:var(--card-hover-shadow);transform:var(--card-hover-transform)}.balina-card.card-clickable:active{transform:translateY(0)}.card-title{margin:0;color:var(--card-title-color);font-size:var(--card-title-size);font-weight:700;line-height:1.2}.card-content{display:flex;align-items:center;gap:28px;margin-top:36px}.card-date{width:92px;height:96px;flex-shrink:0;display:flex;flex-direction:column;align-items:center;justify-content:center;box-sizing:border-box;padding:8px;background:var(--card-date-background);border-radius:10px}.card-month{color:var(--card-month-color);font-size:var(--card-month-size);font-weight:700;line-height:1}.card-line{width:80%;height:2px;margin:7px 0;background:var(--card-line-color)}.card-day{color:var(--card-day-color);font-size:var(--card-day-size);font-weight:600;line-height:1}.card-description{flex:1;color:var(--card-description-color);font-size:var(--card-description-size);font-weight:600;line-height:1.4}.balina-card.card-disabled{background:var(--card-disabled-background);border-color:var(--card-disabled-border);color:var(--card-disabled-text);cursor:not-allowed;box-shadow:none;transform:none}.balina-card.card-disabled:hover{box-shadow:none;transform:none}.balina-card.card-disabled .card-title,.balina-card.card-disabled .card-description{color:var(--card-disabled-text)}@media(max-width:768px){.balina-card{--card-title-size: 30px;--card-description-size: 17px;--card-height: auto;padding:22px}.card-content{gap:18px;margin-top:28px}.card-date{width:80px;height:88px}}@media(max-width:480px){.balina-card{--card-title-size: 26px;--card-description-size: 15px;padding:18px}.card-content{align-items:flex-start;gap:14px}.card-date{width:70px;height:80px}.card-month,.card-day{font-size:20px}}\n"] }]
173
236
  }], propDecorators: { title: [{
174
237
  type: Input
175
238
  }], month: [{
@@ -178,51 +241,137 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
178
241
  type: Input
179
242
  }], description: [{
180
243
  type: Input
181
- }], cardClick: [{
182
- type: Output
183
244
  }], customClass: [{
184
245
  type: Input
185
246
  }], clickable: [{
186
247
  type: Input
187
248
  }], disabled: [{
188
249
  type: Input
250
+ }], cardClick: [{
251
+ type: Output
189
252
  }], clicked: [{
190
253
  type: Output
191
254
  }] } });
192
255
 
193
256
  class TimeFilter {
257
+ // =========================================
258
+ // INPUTS
259
+ // =========================================
194
260
  label = '';
195
- value;
196
- selectedValue = '';
261
+ /**
262
+ * Unique value of this time filter.
263
+ */
264
+ value = '';
265
+ /**
266
+ * Optional external selected value.
267
+ *
268
+ * If the developer connects this input,
269
+ * multiple TimeFilters can work as a group.
270
+ *
271
+ * If it is not provided, the component
272
+ * works independently.
273
+ */
274
+ selectedValue = null;
275
+ /**
276
+ * Developer custom CSS class.
277
+ */
278
+ customClass = '';
279
+ /**
280
+ * Allows the developer to enable/disable
281
+ * click interaction.
282
+ */
283
+ clickable = true;
284
+ /**
285
+ * Disables the component.
286
+ */
287
+ disabled = false;
288
+ // =========================================
289
+ // OUTPUTS
290
+ // =========================================
291
+ /**
292
+ * Emits selected value when the component
293
+ * is used as a connected/group component.
294
+ */
197
295
  selectedValueChange = new EventEmitter();
296
+ /**
297
+ * Developer click event.
298
+ */
198
299
  clicked = new EventEmitter();
300
+ // =========================================
301
+ // INTERNAL STATE
302
+ // =========================================
303
+ /**
304
+ * Used when the component is working
305
+ * independently.
306
+ */
307
+ internalSelected = false;
308
+ // =========================================
309
+ // SELECTED STATE
310
+ // =========================================
199
311
  get selected() {
200
- return this.value === this.selectedValue;
312
+ /*
313
+ * If selectedValue is provided,
314
+ * use the external value.
315
+ */
316
+ if (this.selectedValue !== null &&
317
+ this.selectedValue !== undefined) {
318
+ return this.value === this.selectedValue;
319
+ }
320
+ /*
321
+ * Otherwise use internal state.
322
+ */
323
+ return this.internalSelected;
201
324
  }
325
+ // =========================================
326
+ // CLICK
327
+ // =========================================
202
328
  onClick(event) {
203
- // If already selected → unselect
329
+ if (this.disabled ||
330
+ !this.clickable) {
331
+ return;
332
+ }
333
+ // =====================================
334
+ // INDEPENDENT MODE
335
+ // =====================================
336
+ if (this.selectedValue === null ||
337
+ this.selectedValue === undefined) {
338
+ this.internalSelected =
339
+ !this.internalSelected;
340
+ this.clicked.emit(event);
341
+ return;
342
+ }
343
+ // =====================================
344
+ // CONNECTED / GROUP MODE
345
+ // =====================================
204
346
  if (this.selected) {
205
347
  this.selectedValueChange.emit('');
206
348
  }
207
- // If not selected → select
208
349
  else {
209
350
  this.selectedValueChange.emit(this.value);
210
351
  }
211
- // Developer custom event
352
+ // =====================================
353
+ // DEVELOPER CLICK EVENT
354
+ // =====================================
212
355
  this.clicked.emit(event);
213
356
  }
214
357
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: TimeFilter, deps: [], target: i0.ɵɵFactoryTarget.Component });
215
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.2", type: TimeFilter, isStandalone: true, selector: "lib-time-filter", inputs: { label: "label", value: "value", selectedValue: "selectedValue" }, outputs: { selectedValueChange: "selectedValueChange", clicked: "clicked" }, ngImport: i0, template: "<div class=\"time-filter\" (click)=\"onClick($event)\" role=\"button\" tabindex=\"0\">\n <div class=\"radio-circle\" [class.selected]=\"selected\">\n <div class=\"radio-dot\"></div>\n </div>\n\n <span class=\"label\">\n {{ label }}\n </span>\n</div>", styles: [".time-filter{display:flex;align-items:center;gap:16px;width:fit-content;cursor:pointer;-webkit-user-select:none;user-select:none}.radio-circle{width:24px;height:24px;border:2px solid #a6a6a6;border-radius:50%;display:flex;align-items:center;justify-content:center;box-sizing:border-box;transition:border-color .2s ease}.radio-dot{width:12px;height:12px;border-radius:50%;background:transparent;transition:background .2s ease}.radio-circle.selected{border-color:#1976d2}.radio-circle.selected .radio-dot{background:#1976d2}.label{font-size:20px;font-weight:400;color:#000;line-height:1}.label:hover{color:#333}\n"] });
358
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.2", type: TimeFilter, isStandalone: true, selector: "lib-time-filter", inputs: { label: "label", value: "value", selectedValue: "selectedValue", customClass: "customClass", clickable: "clickable", disabled: "disabled" }, outputs: { selectedValueChange: "selectedValueChange", clicked: "clicked" }, ngImport: i0, template: "<div\n class=\"time-filter\"\n [class]=\"customClass\"\n\n [class.time-filter-clickable]=\"clickable\"\n\n [class.time-filter-disabled]=\"disabled\"\n\n [class.time-filter-selected]=\"selected\"\n\n (click)=\"onClick($event)\"\n\n role=\"button\"\n\n tabindex=\"0\"\n>\n\n <!-- =====================================\n RADIO\n ===================================== -->\n\n <div\n class=\"radio-circle\"\n [class.selected]=\"selected\"\n >\n\n <div class=\"radio-dot\"></div>\n\n </div>\n\n\n <!-- =====================================\n LABEL\n ===================================== -->\n\n <span class=\"label\">\n {{ label }}\n </span>\n\n</div>", styles: [".time-filter{--time-filter-gap: 16px;--time-filter-circle-size: 24px;--time-filter-circle-border-width: 2px;--time-filter-dot-size: 12px;--time-filter-border-color: #a6a6a6;--time-filter-selected-color: #1976d2;--time-filter-text-color: #000000;--time-filter-text-hover: #333333;--time-filter-font-family: Arial, Helvetica, sans-serif;--time-filter-font-size: 20px;--time-filter-font-weight: 400;--time-filter-disabled-color: #aaaaaa;display:flex;align-items:center;gap:var(--time-filter-gap);width:fit-content;box-sizing:border-box;font-family:var(--time-filter-font-family);-webkit-user-select:none;user-select:none;transition:opacity .2s ease}.time-filter-clickable{cursor:pointer}.radio-circle{width:var(--time-filter-circle-size);height:var(--time-filter-circle-size);flex-shrink:0;display:flex;align-items:center;justify-content:center;box-sizing:border-box;border:var(--time-filter-circle-border-width) solid var(--time-filter-border-color);border-radius:50%;transition:border-color .2s ease,background-color .2s ease}.radio-dot{width:var(--time-filter-dot-size);height:var(--time-filter-dot-size);border-radius:50%;background:transparent;transition:background-color .2s ease,transform .2s ease}.radio-circle.selected{border-color:var(--time-filter-selected-color)}.radio-circle.selected .radio-dot{background:var(--time-filter-selected-color);transform:scale(1)}.label{color:var(--time-filter-text-color);font-size:var(--time-filter-font-size);font-weight:var(--time-filter-font-weight);line-height:1;transition:color .2s ease}.time-filter-clickable:hover .label{color:var(--time-filter-text-hover)}.time-filter-clickable:hover .radio-circle{border-color:var(--time-filter-selected-color)}.time-filter-disabled{opacity:.6;cursor:not-allowed}.time-filter-disabled .radio-circle{border-color:var(--time-filter-disabled-color)}.time-filter-disabled .label{color:var(--time-filter-disabled-color)}.time-filter-disabled .radio-circle.selected{border-color:var(--time-filter-disabled-color)}.time-filter-disabled .radio-circle.selected .radio-dot{background:var(--time-filter-disabled-color)}@media(max-width:768px){.time-filter{--time-filter-font-size: 18px;--time-filter-circle-size: 22px;--time-filter-dot-size: 10px;--time-filter-gap: 12px}}@media(max-width:480px){.time-filter{--time-filter-font-size: 16px;--time-filter-circle-size: 20px;--time-filter-dot-size: 9px;--time-filter-gap: 10px}}\n"] });
216
359
  }
217
360
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: TimeFilter, decorators: [{
218
361
  type: Component,
219
- args: [{ selector: 'lib-time-filter', standalone: true, imports: [], template: "<div class=\"time-filter\" (click)=\"onClick($event)\" role=\"button\" tabindex=\"0\">\n <div class=\"radio-circle\" [class.selected]=\"selected\">\n <div class=\"radio-dot\"></div>\n </div>\n\n <span class=\"label\">\n {{ label }}\n </span>\n</div>", styles: [".time-filter{display:flex;align-items:center;gap:16px;width:fit-content;cursor:pointer;-webkit-user-select:none;user-select:none}.radio-circle{width:24px;height:24px;border:2px solid #a6a6a6;border-radius:50%;display:flex;align-items:center;justify-content:center;box-sizing:border-box;transition:border-color .2s ease}.radio-dot{width:12px;height:12px;border-radius:50%;background:transparent;transition:background .2s ease}.radio-circle.selected{border-color:#1976d2}.radio-circle.selected .radio-dot{background:#1976d2}.label{font-size:20px;font-weight:400;color:#000;line-height:1}.label:hover{color:#333}\n"] }]
362
+ args: [{ selector: 'lib-time-filter', standalone: true, imports: [], template: "<div\n class=\"time-filter\"\n [class]=\"customClass\"\n\n [class.time-filter-clickable]=\"clickable\"\n\n [class.time-filter-disabled]=\"disabled\"\n\n [class.time-filter-selected]=\"selected\"\n\n (click)=\"onClick($event)\"\n\n role=\"button\"\n\n tabindex=\"0\"\n>\n\n <!-- =====================================\n RADIO\n ===================================== -->\n\n <div\n class=\"radio-circle\"\n [class.selected]=\"selected\"\n >\n\n <div class=\"radio-dot\"></div>\n\n </div>\n\n\n <!-- =====================================\n LABEL\n ===================================== -->\n\n <span class=\"label\">\n {{ label }}\n </span>\n\n</div>", styles: [".time-filter{--time-filter-gap: 16px;--time-filter-circle-size: 24px;--time-filter-circle-border-width: 2px;--time-filter-dot-size: 12px;--time-filter-border-color: #a6a6a6;--time-filter-selected-color: #1976d2;--time-filter-text-color: #000000;--time-filter-text-hover: #333333;--time-filter-font-family: Arial, Helvetica, sans-serif;--time-filter-font-size: 20px;--time-filter-font-weight: 400;--time-filter-disabled-color: #aaaaaa;display:flex;align-items:center;gap:var(--time-filter-gap);width:fit-content;box-sizing:border-box;font-family:var(--time-filter-font-family);-webkit-user-select:none;user-select:none;transition:opacity .2s ease}.time-filter-clickable{cursor:pointer}.radio-circle{width:var(--time-filter-circle-size);height:var(--time-filter-circle-size);flex-shrink:0;display:flex;align-items:center;justify-content:center;box-sizing:border-box;border:var(--time-filter-circle-border-width) solid var(--time-filter-border-color);border-radius:50%;transition:border-color .2s ease,background-color .2s ease}.radio-dot{width:var(--time-filter-dot-size);height:var(--time-filter-dot-size);border-radius:50%;background:transparent;transition:background-color .2s ease,transform .2s ease}.radio-circle.selected{border-color:var(--time-filter-selected-color)}.radio-circle.selected .radio-dot{background:var(--time-filter-selected-color);transform:scale(1)}.label{color:var(--time-filter-text-color);font-size:var(--time-filter-font-size);font-weight:var(--time-filter-font-weight);line-height:1;transition:color .2s ease}.time-filter-clickable:hover .label{color:var(--time-filter-text-hover)}.time-filter-clickable:hover .radio-circle{border-color:var(--time-filter-selected-color)}.time-filter-disabled{opacity:.6;cursor:not-allowed}.time-filter-disabled .radio-circle{border-color:var(--time-filter-disabled-color)}.time-filter-disabled .label{color:var(--time-filter-disabled-color)}.time-filter-disabled .radio-circle.selected{border-color:var(--time-filter-disabled-color)}.time-filter-disabled .radio-circle.selected .radio-dot{background:var(--time-filter-disabled-color)}@media(max-width:768px){.time-filter{--time-filter-font-size: 18px;--time-filter-circle-size: 22px;--time-filter-dot-size: 10px;--time-filter-gap: 12px}}@media(max-width:480px){.time-filter{--time-filter-font-size: 16px;--time-filter-circle-size: 20px;--time-filter-dot-size: 9px;--time-filter-gap: 10px}}\n"] }]
220
363
  }], propDecorators: { label: [{
221
364
  type: Input
222
365
  }], value: [{
223
366
  type: Input
224
367
  }], selectedValue: [{
225
368
  type: Input
369
+ }], customClass: [{
370
+ type: Input
371
+ }], clickable: [{
372
+ type: Input
373
+ }], disabled: [{
374
+ type: Input
226
375
  }], selectedValueChange: [{
227
376
  type: Output
228
377
  }], clicked: [{
@@ -239,7 +388,11 @@ class TextBox {
239
388
  disabled = false;
240
389
  readonly = false;
241
390
  /**
242
- * Developer can provide their own CSS class.
391
+ * Developer custom CSS class.
392
+ *
393
+ * Example:
394
+ *
395
+ * customClass="flight-input"
243
396
  */
244
397
  customClass = '';
245
398
  // =========================================
@@ -254,33 +407,61 @@ class TextBox {
254
407
  */
255
408
  inputChange = new EventEmitter();
256
409
  /**
257
- * Extra developer click event.
410
+ * Emits whenever the textbox is clicked.
258
411
  */
259
412
  clicked = new EventEmitter();
260
413
  // =========================================
414
+ // PASSWORD VISIBILITY
415
+ // =========================================
416
+ /**
417
+ * Controls password visibility.
418
+ */
419
+ showPassword = false;
420
+ /**
421
+ * Returns the actual input type.
422
+ *
423
+ * password + showPassword
424
+ * becomes text.
425
+ */
426
+ get inputType() {
427
+ if (this.type === 'password') {
428
+ return this.showPassword
429
+ ? 'text'
430
+ : 'password';
431
+ }
432
+ return this.type;
433
+ }
434
+ /**
435
+ * Show/hide password.
436
+ */
437
+ togglePassword(event) {
438
+ event.stopPropagation();
439
+ this.showPassword =
440
+ !this.showPassword;
441
+ }
442
+ // =========================================
261
443
  // INPUT HANDLER
262
444
  // =========================================
263
445
  onInput(event) {
264
446
  const input = event.target;
265
447
  this.value = input.value;
266
- // Two-way value event
448
+ // Emit current value
267
449
  this.valueChange.emit(this.value);
268
- // Developer input event
450
+ // Emit input event
269
451
  this.inputChange.emit(this.value);
270
452
  }
271
453
  // =========================================
272
454
  // CLICK HANDLER
273
455
  // =========================================
274
456
  onClick(event) {
275
- // Allow developer to handle the click
276
457
  this.clicked.emit(event);
277
458
  }
278
459
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: TextBox, deps: [], target: i0.ɵɵFactoryTarget.Component });
279
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.2", type: TextBox, isStandalone: true, selector: "lib-text-box", inputs: { placeholder: "placeholder", value: "value", type: "type", disabled: "disabled", readonly: "readonly", customClass: "customClass" }, outputs: { valueChange: "valueChange", inputChange: "inputChange", clicked: "clicked" }, ngImport: i0, template: "<div\n class=\"text-box-container\"\n [class]=\"customClass\"\n>\n\n <input\n class=\"text-box-input\"\n\n [type]=\"type\"\n\n [placeholder]=\"placeholder\"\n\n [value]=\"value\"\n\n [disabled]=\"disabled\"\n\n [readonly]=\"readonly\"\n\n (input)=\"onInput($event)\"\n\n (click)=\"onClick($event)\"\n />\n\n</div>", styles: [".text-box-container{--textbox-width: 300px;--textbox-height: 44px;--textbox-background: #ffffff;--textbox-border: 1px solid #a9a9a9;--textbox-border-hover: #777777;--textbox-border-focus: #68479b;--textbox-radius: 6px;--textbox-text-color: #222222;--textbox-placeholder-color: #777777;--textbox-font-family: Arial, Helvetica, sans-serif;--textbox-font-size: 14px;--textbox-font-weight: 600;--textbox-padding: 0 18px;--textbox-focus-shadow: 0 0 0 1px rgba(104, 71, 155, .15);width:var(--textbox-width);height:var(--textbox-height);display:flex;align-items:center;box-sizing:border-box}.text-box-input{width:100%;height:100%;box-sizing:border-box;padding:var(--textbox-padding);border:var(--textbox-border);border-radius:var(--textbox-radius);outline:none;background:var(--textbox-background);color:var(--textbox-text-color);font-family:var(--textbox-font-family);font-size:var(--textbox-font-size);font-weight:var(--textbox-font-weight);transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease;cursor:text}.text-box-input::placeholder{color:var(--textbox-placeholder-color);opacity:1;font-family:var(--textbox-font-family);font-size:var(--textbox-font-size);font-weight:var(--textbox-font-weight)}.text-box-input:hover:not(:disabled){border-color:var(--textbox-border-hover)}.text-box-input:focus{border-color:var(--textbox-border-focus);box-shadow:var(--textbox-focus-shadow)}.text-box-input:disabled{background:#f5f5f5;color:#999;border-color:#d0d0d0;cursor:not-allowed}.text-box-input:read-only{cursor:default}@media(max-width:768px){.text-box-container{width:100%}.text-box-input{font-size:var(--textbox-font-size)}}\n"] });
460
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: TextBox, isStandalone: true, selector: "lib-text-box", inputs: { placeholder: "placeholder", value: "value", type: "type", disabled: "disabled", readonly: "readonly", customClass: "customClass" }, outputs: { valueChange: "valueChange", inputChange: "inputChange", clicked: "clicked" }, host: { properties: { "class": "this.customClass" } }, ngImport: i0, template: "<div class=\"text-box-container\">\n\n <div class=\"text-box-input-wrapper\">\n\n <input\n class=\"text-box-input\"\n\n [type]=\"inputType\"\n\n [placeholder]=\"placeholder\"\n\n [value]=\"value\"\n\n [disabled]=\"disabled\"\n\n [readonly]=\"readonly\"\n\n (input)=\"onInput($event)\"\n\n (click)=\"onClick($event)\"\n />\n\n <!-- Password Eye Button -->\n @if (type === 'password') {\n\n <button\n type=\"button\"\n class=\"text-box-password-button\"\n\n [disabled]=\"disabled\"\n\n (click)=\"togglePassword($event)\"\n aria-label=\"Toggle password visibility\"\n >\n\n @if (showPassword) {\n\n <!-- Eye Off -->\n <svg\n class=\"text-box-password-icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path\n d=\"M3 3l18 18\"\n />\n\n <path\n d=\"M10.6 10.6a2 2 0 1 0 2.8 2.8\"\n />\n\n <path\n d=\"M9.9 4.2A10.8 10.8 0 0 1 12 4c5 0 8.7 4.2 9.8 8a10.8 10.8 0 0 1-3.1 5.1\"\n />\n\n <path\n d=\"M6.2 6.2C4.5 7.4 3.2 9.2 2.2 12c1.1 3.8 4.8 8 9.8 8 1.7 0 3.3-.5 4.7-1.2\"\n />\n </svg>\n\n } @else {\n\n <!-- Eye -->\n <svg\n class=\"text-box-password-icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path\n d=\"M2 12s3.5-7 10-7\n 10 7 10 7\n -3.5 7-10 7\n -10-7-10-7z\"\n />\n\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"3\"\n />\n </svg>\n\n }\n\n </button>\n\n }\n\n </div>\n\n</div>", styles: [":host{--textbox-width: 300px;--textbox-height: 44px;--textbox-background: #ffffff;--textbox-border: 1px solid #a9a9a9;--textbox-border-hover: #777777;--textbox-border-focus: #68479b;--textbox-radius: 6px;--textbox-text-color: #222222;--textbox-placeholder-color: #777777;--textbox-font-family: Arial, Helvetica, sans-serif;--textbox-font-size: 14px;--textbox-font-weight: 600;--textbox-padding: 0 18px;--textbox-focus-shadow: 0 0 0 1px rgba(104, 71, 155, .15);--textbox-disabled-background: #f5f5f5;--textbox-disabled-color: #999999;--textbox-disabled-border: #d0d0d0;--textbox-icon-color: #777777;--textbox-icon-hover-color: #333333;display:block;width:var(--textbox-width);height:var(--textbox-height);box-sizing:border-box}.text-box-container{width:100%;height:100%;display:flex;align-items:center;box-sizing:border-box}.text-box-input-wrapper{position:relative;width:100%;height:100%;display:flex;align-items:center;box-sizing:border-box}.text-box-input{width:100%;height:100%;box-sizing:border-box;padding:var(--textbox-padding);border:var(--textbox-border);border-radius:var(--textbox-radius);outline:none;background:var(--textbox-background);color:var(--textbox-text-color);font-family:var(--textbox-font-family);font-size:var(--textbox-font-size);font-weight:var(--textbox-font-weight);transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease;cursor:text}.text-box-input[type=password]{padding-right:48px}.text-box-input::placeholder{color:var(--textbox-placeholder-color);opacity:1;font-family:var(--textbox-font-family);font-size:var(--textbox-font-size);font-weight:var(--textbox-font-weight)}.text-box-input:hover:not(:disabled){border-color:var(--textbox-border-hover)}.text-box-input:focus{border-color:var(--textbox-border-focus);box-shadow:var(--textbox-focus-shadow)}.text-box-input:disabled{background:var(--textbox-disabled-background);color:var(--textbox-disabled-color);border-color:var(--textbox-disabled-border);cursor:not-allowed}.text-box-input:read-only{cursor:default}.text-box-password-button{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:32px;height:32px;display:flex;align-items:center;justify-content:center;padding:0;border:none;background:transparent;color:var(--textbox-icon-color);cursor:pointer;border-radius:4px;transition:color .2s ease,background-color .2s ease}.text-box-password-button:hover:not(:disabled){color:var(--textbox-icon-hover-color);background:#0000000d}.text-box-password-button:disabled{cursor:not-allowed;opacity:.5}.text-box-password-icon{width:19px;height:19px;display:block}@media(max-width:768px){:host{width:100%}.text-box-input{font-size:var(--textbox-font-size)}}\n"] });
280
461
  }
281
462
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: TextBox, decorators: [{
282
463
  type: Component,
283
- args: [{ selector: 'lib-text-box', standalone: true, imports: [], template: "<div\n class=\"text-box-container\"\n [class]=\"customClass\"\n>\n\n <input\n class=\"text-box-input\"\n\n [type]=\"type\"\n\n [placeholder]=\"placeholder\"\n\n [value]=\"value\"\n\n [disabled]=\"disabled\"\n\n [readonly]=\"readonly\"\n\n (input)=\"onInput($event)\"\n\n (click)=\"onClick($event)\"\n />\n\n</div>", styles: [".text-box-container{--textbox-width: 300px;--textbox-height: 44px;--textbox-background: #ffffff;--textbox-border: 1px solid #a9a9a9;--textbox-border-hover: #777777;--textbox-border-focus: #68479b;--textbox-radius: 6px;--textbox-text-color: #222222;--textbox-placeholder-color: #777777;--textbox-font-family: Arial, Helvetica, sans-serif;--textbox-font-size: 14px;--textbox-font-weight: 600;--textbox-padding: 0 18px;--textbox-focus-shadow: 0 0 0 1px rgba(104, 71, 155, .15);width:var(--textbox-width);height:var(--textbox-height);display:flex;align-items:center;box-sizing:border-box}.text-box-input{width:100%;height:100%;box-sizing:border-box;padding:var(--textbox-padding);border:var(--textbox-border);border-radius:var(--textbox-radius);outline:none;background:var(--textbox-background);color:var(--textbox-text-color);font-family:var(--textbox-font-family);font-size:var(--textbox-font-size);font-weight:var(--textbox-font-weight);transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease;cursor:text}.text-box-input::placeholder{color:var(--textbox-placeholder-color);opacity:1;font-family:var(--textbox-font-family);font-size:var(--textbox-font-size);font-weight:var(--textbox-font-weight)}.text-box-input:hover:not(:disabled){border-color:var(--textbox-border-hover)}.text-box-input:focus{border-color:var(--textbox-border-focus);box-shadow:var(--textbox-focus-shadow)}.text-box-input:disabled{background:#f5f5f5;color:#999;border-color:#d0d0d0;cursor:not-allowed}.text-box-input:read-only{cursor:default}@media(max-width:768px){.text-box-container{width:100%}.text-box-input{font-size:var(--textbox-font-size)}}\n"] }]
464
+ args: [{ selector: 'lib-text-box', standalone: true, imports: [], template: "<div class=\"text-box-container\">\n\n <div class=\"text-box-input-wrapper\">\n\n <input\n class=\"text-box-input\"\n\n [type]=\"inputType\"\n\n [placeholder]=\"placeholder\"\n\n [value]=\"value\"\n\n [disabled]=\"disabled\"\n\n [readonly]=\"readonly\"\n\n (input)=\"onInput($event)\"\n\n (click)=\"onClick($event)\"\n />\n\n <!-- Password Eye Button -->\n @if (type === 'password') {\n\n <button\n type=\"button\"\n class=\"text-box-password-button\"\n\n [disabled]=\"disabled\"\n\n (click)=\"togglePassword($event)\"\n aria-label=\"Toggle password visibility\"\n >\n\n @if (showPassword) {\n\n <!-- Eye Off -->\n <svg\n class=\"text-box-password-icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path\n d=\"M3 3l18 18\"\n />\n\n <path\n d=\"M10.6 10.6a2 2 0 1 0 2.8 2.8\"\n />\n\n <path\n d=\"M9.9 4.2A10.8 10.8 0 0 1 12 4c5 0 8.7 4.2 9.8 8a10.8 10.8 0 0 1-3.1 5.1\"\n />\n\n <path\n d=\"M6.2 6.2C4.5 7.4 3.2 9.2 2.2 12c1.1 3.8 4.8 8 9.8 8 1.7 0 3.3-.5 4.7-1.2\"\n />\n </svg>\n\n } @else {\n\n <!-- Eye -->\n <svg\n class=\"text-box-password-icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path\n d=\"M2 12s3.5-7 10-7\n 10 7 10 7\n -3.5 7-10 7\n -10-7-10-7z\"\n />\n\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"3\"\n />\n </svg>\n\n }\n\n </button>\n\n }\n\n </div>\n\n</div>", styles: [":host{--textbox-width: 300px;--textbox-height: 44px;--textbox-background: #ffffff;--textbox-border: 1px solid #a9a9a9;--textbox-border-hover: #777777;--textbox-border-focus: #68479b;--textbox-radius: 6px;--textbox-text-color: #222222;--textbox-placeholder-color: #777777;--textbox-font-family: Arial, Helvetica, sans-serif;--textbox-font-size: 14px;--textbox-font-weight: 600;--textbox-padding: 0 18px;--textbox-focus-shadow: 0 0 0 1px rgba(104, 71, 155, .15);--textbox-disabled-background: #f5f5f5;--textbox-disabled-color: #999999;--textbox-disabled-border: #d0d0d0;--textbox-icon-color: #777777;--textbox-icon-hover-color: #333333;display:block;width:var(--textbox-width);height:var(--textbox-height);box-sizing:border-box}.text-box-container{width:100%;height:100%;display:flex;align-items:center;box-sizing:border-box}.text-box-input-wrapper{position:relative;width:100%;height:100%;display:flex;align-items:center;box-sizing:border-box}.text-box-input{width:100%;height:100%;box-sizing:border-box;padding:var(--textbox-padding);border:var(--textbox-border);border-radius:var(--textbox-radius);outline:none;background:var(--textbox-background);color:var(--textbox-text-color);font-family:var(--textbox-font-family);font-size:var(--textbox-font-size);font-weight:var(--textbox-font-weight);transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease;cursor:text}.text-box-input[type=password]{padding-right:48px}.text-box-input::placeholder{color:var(--textbox-placeholder-color);opacity:1;font-family:var(--textbox-font-family);font-size:var(--textbox-font-size);font-weight:var(--textbox-font-weight)}.text-box-input:hover:not(:disabled){border-color:var(--textbox-border-hover)}.text-box-input:focus{border-color:var(--textbox-border-focus);box-shadow:var(--textbox-focus-shadow)}.text-box-input:disabled{background:var(--textbox-disabled-background);color:var(--textbox-disabled-color);border-color:var(--textbox-disabled-border);cursor:not-allowed}.text-box-input:read-only{cursor:default}.text-box-password-button{position:absolute;right:8px;top:50%;transform:translateY(-50%);width:32px;height:32px;display:flex;align-items:center;justify-content:center;padding:0;border:none;background:transparent;color:var(--textbox-icon-color);cursor:pointer;border-radius:4px;transition:color .2s ease,background-color .2s ease}.text-box-password-button:hover:not(:disabled){color:var(--textbox-icon-hover-color);background:#0000000d}.text-box-password-button:disabled{cursor:not-allowed;opacity:.5}.text-box-password-icon{width:19px;height:19px;display:block}@media(max-width:768px){:host{width:100%}.text-box-input{font-size:var(--textbox-font-size)}}\n"] }]
284
465
  }], propDecorators: { placeholder: [{
285
466
  type: Input
286
467
  }], value: [{
@@ -293,6 +474,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
293
474
  type: Input
294
475
  }], customClass: [{
295
476
  type: Input
477
+ }, {
478
+ type: HostBinding,
479
+ args: ['class']
296
480
  }], valueChange: [{
297
481
  type: Output
298
482
  }], inputChange: [{
@@ -302,6 +486,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
302
486
  }] } });
303
487
 
304
488
  class DateInput {
489
+ elementRef;
305
490
  // =========================================
306
491
  // INPUTS
307
492
  // =========================================
@@ -310,19 +495,55 @@ class DateInput {
310
495
  value = '';
311
496
  disabled = false;
312
497
  readonly = false;
498
+ /**
499
+ * Developer custom CSS class.
500
+ *
501
+ * Example:
502
+ *
503
+ * customClass="flight-date"
504
+ */
313
505
  customClass = '';
314
506
  // =========================================
315
507
  // OUTPUTS
316
508
  // =========================================
509
+ /**
510
+ * Emits the selected date as:
511
+ *
512
+ * YYYY-MM-DD
513
+ */
317
514
  valueChange = new EventEmitter();
515
+ /**
516
+ * Emits the selected Date object.
517
+ */
318
518
  dateChange = new EventEmitter();
519
+ /**
520
+ * Emits when the calendar opens/closes.
521
+ */
319
522
  openedChange = new EventEmitter();
523
+ /**
524
+ * Developer click event.
525
+ */
320
526
  clicked = new EventEmitter();
321
527
  // =========================================
322
528
  // INTERNAL STATE
323
529
  // =========================================
324
530
  isOpen = false;
325
531
  currentDate = new Date();
532
+ constructor(elementRef) {
533
+ this.elementRef = elementRef;
534
+ }
535
+ // =========================================
536
+ // INITIALIZE VALUE
537
+ // =========================================
538
+ ngOnInit() {
539
+ if (this.value) {
540
+ const parsedDate = this.parseDate(this.value);
541
+ if (parsedDate) {
542
+ this.currentDate =
543
+ new Date(parsedDate.getFullYear(), parsedDate.getMonth(), 1);
544
+ }
545
+ }
546
+ }
326
547
  // =========================================
327
548
  // CALENDAR DAYS
328
549
  // =========================================
@@ -332,14 +553,28 @@ class DateInput {
332
553
  const firstDay = new Date(year, month, 1);
333
554
  const lastDay = new Date(year, month + 1, 0);
334
555
  const days = [];
556
+ /*
557
+ * Sunday = 0
558
+ * Monday = 1
559
+ * ...
560
+ * Saturday = 6
561
+ */
335
562
  const startDay = firstDay.getDay();
563
+ // =====================================
564
+ // PREVIOUS MONTH DAYS
565
+ // =====================================
336
566
  for (let i = 0; i < startDay; i++) {
337
- const previousDate = new Date(year, month, i - startDay + 1);
338
- days.push(previousDate);
567
+ days.push(new Date(year, month, i - startDay + 1));
339
568
  }
569
+ // =====================================
570
+ // CURRENT MONTH DAYS
571
+ // =====================================
340
572
  for (let day = 1; day <= lastDay.getDate(); day++) {
341
573
  days.push(new Date(year, month, day));
342
574
  }
575
+ // =====================================
576
+ // NEXT MONTH DAYS
577
+ // =====================================
343
578
  const remaining = 42 - days.length;
344
579
  for (let i = 1; i <= remaining; i++) {
345
580
  days.push(new Date(year, month + 1, i));
@@ -354,11 +589,14 @@ class DateInput {
354
589
  month: 'long'
355
590
  });
356
591
  }
592
+ // =========================================
593
+ // YEAR
594
+ // =========================================
357
595
  get year() {
358
596
  return this.currentDate.getFullYear();
359
597
  }
360
598
  // =========================================
361
- // OPEN / CLOSE
599
+ // TOGGLE CALENDAR
362
600
  // =========================================
363
601
  toggleCalendar(event) {
364
602
  if (this.disabled ||
@@ -368,20 +606,23 @@ class DateInput {
368
606
  if (event) {
369
607
  this.clicked.emit(event);
370
608
  }
371
- this.isOpen = !this.isOpen;
609
+ this.isOpen =
610
+ !this.isOpen;
372
611
  this.openedChange.emit(this.isOpen);
373
612
  }
374
613
  // =========================================
375
614
  // PREVIOUS MONTH
376
615
  // =========================================
377
- previousMonth() {
616
+ previousMonth(event) {
617
+ event?.stopPropagation();
378
618
  this.currentDate =
379
619
  new Date(this.year, this.currentDate.getMonth() - 1, 1);
380
620
  }
381
621
  // =========================================
382
622
  // NEXT MONTH
383
623
  // =========================================
384
- nextMonth() {
624
+ nextMonth(event) {
625
+ event?.stopPropagation();
385
626
  this.currentDate =
386
627
  new Date(this.year, this.currentDate.getMonth() + 1, 1);
387
628
  }
@@ -389,14 +630,29 @@ class DateInput {
389
630
  // SELECT DATE
390
631
  // =========================================
391
632
  selectDate(date, event) {
392
- if (this.disabled) {
633
+ event.stopPropagation();
634
+ if (this.disabled ||
635
+ this.readonly) {
393
636
  return;
394
637
  }
638
+ /*
639
+ * Create a clean Date object.
640
+ */
641
+ const selectedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
642
+ // =====================================
643
+ // UPDATE VALUE
644
+ // =====================================
395
645
  this.value =
396
- this.formatDate(date);
646
+ this.formatDate(selectedDate);
647
+ // =====================================
648
+ // EMIT EVENTS
649
+ // =====================================
397
650
  this.valueChange.emit(this.value);
398
- this.dateChange.emit(date);
651
+ this.dateChange.emit(selectedDate);
399
652
  this.clicked.emit(event);
653
+ // =====================================
654
+ // CLOSE
655
+ // =====================================
400
656
  this.isOpen = false;
401
657
  this.openedChange.emit(false);
402
658
  }
@@ -404,15 +660,40 @@ class DateInput {
404
660
  // FORMAT DATE
405
661
  // =========================================
406
662
  formatDate(date) {
407
- const day = String(date.getDate())
408
- .padStart(2, '0');
409
- const month = String(date.getMonth() + 1)
410
- .padStart(2, '0');
663
+ const day = String(date.getDate()).padStart(2, '0');
664
+ const month = String(date.getMonth() + 1).padStart(2, '0');
411
665
  const year = date.getFullYear();
412
666
  return `${year}-${month}-${day}`;
413
667
  }
414
668
  // =========================================
415
- // CHECK CURRENT MONTH
669
+ // PARSE DATE
670
+ // =========================================
671
+ parseDate(value) {
672
+ const parts = value.split('-');
673
+ if (parts.length !== 3) {
674
+ return null;
675
+ }
676
+ const year = Number(parts[0]);
677
+ const month = Number(parts[1]);
678
+ const day = Number(parts[2]);
679
+ if (!year ||
680
+ !month ||
681
+ !day) {
682
+ return null;
683
+ }
684
+ const date = new Date(year, month - 1, day);
685
+ /*
686
+ * Validate the date.
687
+ */
688
+ if (date.getFullYear() !== year ||
689
+ date.getMonth() !== month - 1 ||
690
+ date.getDate() !== day) {
691
+ return null;
692
+ }
693
+ return date;
694
+ }
695
+ // =========================================
696
+ // CURRENT MONTH
416
697
  // =========================================
417
698
  isCurrentMonth(date) {
418
699
  return (date.getMonth() ===
@@ -421,16 +702,19 @@ class DateInput {
421
702
  this.currentDate.getFullYear());
422
703
  }
423
704
  // =========================================
424
- // CHECK TODAY
705
+ // TODAY
425
706
  // =========================================
426
707
  isToday(date) {
427
708
  const today = new Date();
428
- return (date.getDate() === today.getDate() &&
429
- date.getMonth() === today.getMonth() &&
430
- date.getFullYear() === today.getFullYear());
709
+ return (date.getDate() ===
710
+ today.getDate() &&
711
+ date.getMonth() ===
712
+ today.getMonth() &&
713
+ date.getFullYear() ===
714
+ today.getFullYear());
431
715
  }
432
716
  // =========================================
433
- // CHECK SELECTED DATE
717
+ // SELECTED DATE
434
718
  // =========================================
435
719
  isSelected(date) {
436
720
  return (this.value ===
@@ -440,21 +724,32 @@ class DateInput {
440
724
  // OUTSIDE CLICK
441
725
  // =========================================
442
726
  onDocumentClick(event) {
727
+ if (!this.isOpen) {
728
+ return;
729
+ }
443
730
  const target = event.target;
444
- const dateInput = target.closest('lib-date-input');
445
- if (!dateInput &&
446
- this.isOpen) {
447
- this.isOpen = false;
448
- this.openedChange.emit(false);
731
+ const host = this.elementRef.nativeElement;
732
+ if (!host.contains(target)) {
733
+ this.closeCalendar();
449
734
  }
450
735
  }
451
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: DateInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
452
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: DateInput, isStandalone: true, selector: "lib-date-input", inputs: { label: "label", placeholder: "placeholder", value: "value", disabled: "disabled", readonly: "readonly", customClass: "customClass" }, outputs: { valueChange: "valueChange", dateChange: "dateChange", openedChange: "openedChange", clicked: "clicked" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, ngImport: i0, template: "<div\n class=\"date-input-container\"\n [class]=\"customClass\"\n [class.date-input-disabled]=\"disabled\"\n [class.date-input-open]=\"isOpen\"\n>\n\n <!-- INPUT -->\n\n <div\n class=\"date-input-field\"\n (click)=\"toggleCalendar($event)\"\n >\n\n @if (label) {\n <label class=\"date-input-label\">\n {{ label }}\n </label>\n }\n\n <span\n class=\"date-input-value\"\n [class.date-input-placeholder]=\"!value\"\n >\n {{ value || placeholder }}\n </span>\n\n <!-- Calendar Icon -->\n\n <span class=\"calendar-icon\">\n\n <span class=\"calendar-top\"></span>\n\n <span class=\"calendar-body\"></span>\n\n </span>\n\n </div>\n\n\n <!-- DATE PICKER -->\n\n @if (isOpen) {\n\n <div\n class=\"date-picker\"\n (click)=\"$event.stopPropagation()\"\n >\n\n <!-- HEADER -->\n\n <div class=\"date-picker-header\">\n\n <button\n type=\"button\"\n class=\"month-button\"\n (click)=\"previousMonth()\"\n >\n \u2039\n </button>\n\n <span class=\"month-title\">\n {{ monthName }} {{ year }}\n </span>\n\n <button\n type=\"button\"\n class=\"month-button\"\n (click)=\"nextMonth()\"\n >\n \u203A\n </button>\n\n </div>\n\n\n <!-- WEEK DAYS -->\n\n <div class=\"week-days\">\n\n <span>Sun</span>\n <span>Mon</span>\n <span>Tue</span>\n <span>Wed</span>\n <span>Thu</span>\n <span>Fri</span>\n <span>Sat</span>\n\n </div>\n\n\n <!-- DAYS -->\n\n <div class=\"calendar-days\">\n\n @for (\n date of calendarDays;\n track date.getTime()\n ) {\n\n <button\n type=\"button\"\n\n class=\"calendar-day\"\n\n [class.other-month]=\"\n !isCurrentMonth(date)\n \"\n\n [class.today]=\"\n isToday(date)\n \"\n\n [class.selected]=\"\n isSelected(date)\n \"\n\n (click)=\"\n selectDate(date, $event)\n \"\n >\n\n {{ date.getDate() }}\n\n </button>\n\n }\n\n </div>\n\n </div>\n\n }\n\n</div>", styles: [".date-input-container{--date-width: 300px;--date-height: 44px;--date-background: #ffffff;--date-border: 1px solid #a9a9a9;--date-border-hover: #777777;--date-border-focus: #68479b;--date-radius: 6px;--date-text: #222222;--date-placeholder: #777777;--date-primary: #68479b;--date-hover: #f3f0f7;--date-selected: #68479b;--date-selected-text: #ffffff;--date-font-family: Arial, Helvetica, sans-serif;--date-font-size: 14px;--date-shadow: 0 4px 12px rgba(0, 0, 0, .12);position:relative;width:var(--date-width);font-family:var(--date-font-family);box-sizing:border-box}.date-input-field{position:relative;width:100%;height:var(--date-height);display:flex;align-items:center;box-sizing:border-box;padding:0 50px 0 18px;border:var(--date-border);border-radius:var(--date-radius);background:var(--date-background);color:var(--date-text);font-size:var(--date-font-size);font-weight:600;cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease}.date-input-field:hover{border-color:var(--date-border-hover)}.date-input-open .date-input-field{border-color:var(--date-border-focus);box-shadow:0 0 0 1px #68479b1f}.date-input-label{position:absolute;top:0;left:14px;transform:translateY(-50%);padding:0 6px;background:var(--date-background);color:var(--date-border-focus);font-size:13px;font-weight:500;line-height:1;pointer-events:none}.date-input-value{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.date-input-placeholder{color:var(--date-placeholder)}.calendar-icon{position:absolute;right:17px;width:18px;height:18px;box-sizing:border-box;border:1.8px solid #555;border-radius:3px}.calendar-top{position:absolute;left:0;top:4px;width:100%;border-top:1.8px solid #555}.calendar-icon:before,.calendar-icon:after{content:\"\";position:absolute;top:-4px;width:2px;height:6px;background:#555;border-radius:2px}.calendar-icon:before{left:4px}.calendar-icon:after{right:4px}.date-picker{position:absolute;top:calc(100% + 6px);left:0;width:100%;min-width:300px;z-index:1000;padding:14px;box-sizing:border-box;background:#fff;border:1px solid #d5d5d5;border-radius:var(--date-radius);box-shadow:var(--date-shadow)}.date-picker-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}.month-title{font-size:15px;font-weight:700;color:var(--date-text)}.month-button{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:transparent;color:#555;font-size:24px;line-height:1;cursor:pointer}.month-button:hover{background:var(--date-hover);color:var(--date-primary)}.week-days{display:grid;grid-template-columns:repeat(7,1fr);margin-bottom:6px;text-align:center;color:#777;font-size:12px;font-weight:600}.calendar-days{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}.calendar-day{width:100%;aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:transparent;color:var(--date-text);font-size:13px;cursor:pointer;transition:background-color .15s ease,color .15s ease}.calendar-day:hover{background:var(--date-hover)}.calendar-day.other-month{color:silver}.calendar-day.today{border:1px solid var(--date-primary);color:var(--date-primary)}.calendar-day.selected{background:var(--date-selected);color:var(--date-selected-text);border:none}.date-input-disabled .date-input-field{background:#f5f5f5;border-color:#d0d0d0;color:#999;cursor:not-allowed}@media(max-width:768px){.date-input-container{width:100%}.date-picker{min-width:100%}}\n"] });
736
+ // =========================================
737
+ // CLOSE CALENDAR
738
+ // =========================================
739
+ closeCalendar() {
740
+ if (!this.isOpen) {
741
+ return;
742
+ }
743
+ this.isOpen = false;
744
+ this.openedChange.emit(false);
745
+ }
746
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: DateInput, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
747
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: DateInput, isStandalone: true, selector: "lib-date-input", inputs: { label: "label", placeholder: "placeholder", value: "value", disabled: "disabled", readonly: "readonly", customClass: "customClass" }, outputs: { valueChange: "valueChange", dateChange: "dateChange", openedChange: "openedChange", clicked: "clicked" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, properties: { "class": "this.customClass" } }, ngImport: i0, template: "<div\n class=\"date-input-container\"\n [class.date-input-disabled]=\"disabled\"\n [class.date-input-open]=\"isOpen\"\n>\n\n <!-- =====================================\n INPUT FIELD\n ===================================== -->\n\n <div\n class=\"date-input-field\"\n (click)=\"toggleCalendar($event)\"\n >\n\n <!-- LABEL -->\n\n @if (label) {\n\n <label class=\"date-input-label\">\n\n {{ label }}\n\n </label>\n\n }\n\n\n <!-- VALUE -->\n\n <span\n class=\"date-input-value\"\n [class.date-input-placeholder]=\"!value\"\n >\n\n {{ value || placeholder }}\n\n </span>\n\n\n <!-- CALENDAR ICON -->\n\n <span class=\"calendar-icon\">\n\n <span class=\"calendar-top\"></span>\n\n <span class=\"calendar-body\"></span>\n\n </span>\n\n </div>\n\n\n <!-- =====================================\n DATE PICKER\n ===================================== -->\n\n @if (isOpen) {\n\n <div\n class=\"date-picker\"\n (click)=\"$event.stopPropagation()\"\n >\n\n <!-- =================================\n HEADER\n ================================= -->\n\n <div class=\"date-picker-header\">\n\n <button\n type=\"button\"\n class=\"month-button\"\n\n aria-label=\"Previous month\"\n\n (click)=\"previousMonth($event)\"\n >\n\n \u2039\n\n </button>\n\n\n <span class=\"month-title\">\n\n {{ monthName }} {{ year }}\n\n </span>\n\n\n <button\n type=\"button\"\n class=\"month-button\"\n\n aria-label=\"Next month\"\n\n (click)=\"nextMonth($event)\"\n >\n\n \u203A\n\n </button>\n\n </div>\n\n\n <!-- =================================\n WEEK DAYS\n ================================= -->\n\n <div class=\"week-days\">\n\n <span>Sun</span>\n\n <span>Mon</span>\n\n <span>Tue</span>\n\n <span>Wed</span>\n\n <span>Thu</span>\n\n <span>Fri</span>\n\n <span>Sat</span>\n\n </div>\n\n\n <!-- =================================\n CALENDAR DAYS\n ================================= -->\n\n <div class=\"calendar-days\">\n\n @for (\n date of calendarDays;\n track date.getTime()\n ) {\n\n <button\n type=\"button\"\n\n class=\"calendar-day\"\n\n [class.other-month]=\"\n !isCurrentMonth(date)\n \"\n\n [class.today]=\"\n isToday(date)\n \"\n\n [class.selected]=\"\n isSelected(date)\n \"\n\n (click)=\"\n selectDate(date, $event)\n \"\n >\n\n {{ date.getDate() }}\n\n </button>\n\n }\n\n </div>\n\n </div>\n\n }\n\n</div>", styles: [":host{--date-width: 300px;--date-height: 44px;--date-background: #ffffff;--date-border: 1px solid #a9a9a9;--date-border-hover: #777777;--date-border-focus: #68479b;--date-radius: 6px;--date-text: #222222;--date-placeholder: #777777;--date-primary: #68479b;--date-hover: #f3f0f7;--date-selected: #68479b;--date-selected-text: #ffffff;--date-font-family: Arial, Helvetica, sans-serif;--date-font-size: 14px;--date-font-weight: 600;--date-shadow: 0 4px 12px rgba(0, 0, 0, .12);--date-icon-color: #555555;--date-disabled-background: #f5f5f5;--date-disabled-border: #d0d0d0;--date-disabled-text: #999999;display:block;position:relative;width:var(--date-width);box-sizing:border-box;font-family:var(--date-font-family)}.date-input-container{position:relative;width:100%;box-sizing:border-box}.date-input-field{position:relative;width:100%;height:var(--date-height);display:flex;align-items:center;box-sizing:border-box;padding:0 50px 0 18px;border:var(--date-border);border-radius:var(--date-radius);background:var(--date-background);color:var(--date-text);font-size:var(--date-font-size);font-weight:var(--date-font-weight);cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease}.date-input-field:hover{border-color:var(--date-border-hover)}.date-input-open .date-input-field{border-color:var(--date-border-focus);box-shadow:0 0 0 1px #68479b1f}.date-input-label{position:absolute;top:0;left:14px;transform:translateY(-50%);padding:0 6px;background:var(--date-background);color:var(--date-border-focus);font-size:13px;font-weight:500;line-height:1;pointer-events:none}.date-input-value{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--date-text)}.date-input-placeholder{color:var(--date-placeholder)}.calendar-icon{position:absolute;right:17px;width:18px;height:18px;box-sizing:border-box;border:1.8px solid var(--date-icon-color);border-radius:3px}.calendar-top{position:absolute;left:0;top:4px;width:100%;border-top:1.8px solid var(--date-icon-color)}.calendar-icon:before,.calendar-icon:after{content:\"\";position:absolute;top:-4px;width:2px;height:6px;background:var(--date-icon-color);border-radius:2px}.calendar-icon:before{left:4px}.calendar-icon:after{right:4px}.date-picker{position:absolute;top:calc(100% + 6px);left:0;width:100%;min-width:300px;z-index:1000;padding:14px;box-sizing:border-box;background:#fff;border:1px solid #d5d5d5;border-radius:var(--date-radius);box-shadow:var(--date-shadow)}.date-picker-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}.month-title{font-size:15px;font-weight:700;color:var(--date-text)}.month-button{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:transparent;color:#555;font-size:24px;line-height:1;cursor:pointer;transition:background-color .15s ease,color .15s ease}.month-button:hover{background:var(--date-hover);color:var(--date-primary)}.week-days{display:grid;grid-template-columns:repeat(7,1fr);margin-bottom:6px;text-align:center;color:#777;font-size:12px;font-weight:600}.calendar-days{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}.calendar-day{width:100%;aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:transparent;color:var(--date-text);font-family:var(--date-font-family);font-size:13px;cursor:pointer;transition:background-color .15s ease,color .15s ease}.calendar-day:hover{background:var(--date-hover)}.calendar-day.other-month{color:silver}.calendar-day.today{border:1px solid var(--date-primary);color:var(--date-primary)}.calendar-day.selected{background:var(--date-selected);color:var(--date-selected-text);border:none}.calendar-day.selected.today{background:var(--date-selected);color:var(--date-selected-text)}.date-input-disabled .date-input-field{background:var(--date-disabled-background);border-color:var(--date-disabled-border);color:var(--date-disabled-text);cursor:not-allowed}@media(max-width:768px){:host{width:100%}.date-picker{min-width:100%}}\n"] });
453
748
  }
454
749
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: DateInput, decorators: [{
455
750
  type: Component,
456
- args: [{ selector: 'lib-date-input', standalone: true, imports: [], template: "<div\n class=\"date-input-container\"\n [class]=\"customClass\"\n [class.date-input-disabled]=\"disabled\"\n [class.date-input-open]=\"isOpen\"\n>\n\n <!-- INPUT -->\n\n <div\n class=\"date-input-field\"\n (click)=\"toggleCalendar($event)\"\n >\n\n @if (label) {\n <label class=\"date-input-label\">\n {{ label }}\n </label>\n }\n\n <span\n class=\"date-input-value\"\n [class.date-input-placeholder]=\"!value\"\n >\n {{ value || placeholder }}\n </span>\n\n <!-- Calendar Icon -->\n\n <span class=\"calendar-icon\">\n\n <span class=\"calendar-top\"></span>\n\n <span class=\"calendar-body\"></span>\n\n </span>\n\n </div>\n\n\n <!-- DATE PICKER -->\n\n @if (isOpen) {\n\n <div\n class=\"date-picker\"\n (click)=\"$event.stopPropagation()\"\n >\n\n <!-- HEADER -->\n\n <div class=\"date-picker-header\">\n\n <button\n type=\"button\"\n class=\"month-button\"\n (click)=\"previousMonth()\"\n >\n \u2039\n </button>\n\n <span class=\"month-title\">\n {{ monthName }} {{ year }}\n </span>\n\n <button\n type=\"button\"\n class=\"month-button\"\n (click)=\"nextMonth()\"\n >\n \u203A\n </button>\n\n </div>\n\n\n <!-- WEEK DAYS -->\n\n <div class=\"week-days\">\n\n <span>Sun</span>\n <span>Mon</span>\n <span>Tue</span>\n <span>Wed</span>\n <span>Thu</span>\n <span>Fri</span>\n <span>Sat</span>\n\n </div>\n\n\n <!-- DAYS -->\n\n <div class=\"calendar-days\">\n\n @for (\n date of calendarDays;\n track date.getTime()\n ) {\n\n <button\n type=\"button\"\n\n class=\"calendar-day\"\n\n [class.other-month]=\"\n !isCurrentMonth(date)\n \"\n\n [class.today]=\"\n isToday(date)\n \"\n\n [class.selected]=\"\n isSelected(date)\n \"\n\n (click)=\"\n selectDate(date, $event)\n \"\n >\n\n {{ date.getDate() }}\n\n </button>\n\n }\n\n </div>\n\n </div>\n\n }\n\n</div>", styles: [".date-input-container{--date-width: 300px;--date-height: 44px;--date-background: #ffffff;--date-border: 1px solid #a9a9a9;--date-border-hover: #777777;--date-border-focus: #68479b;--date-radius: 6px;--date-text: #222222;--date-placeholder: #777777;--date-primary: #68479b;--date-hover: #f3f0f7;--date-selected: #68479b;--date-selected-text: #ffffff;--date-font-family: Arial, Helvetica, sans-serif;--date-font-size: 14px;--date-shadow: 0 4px 12px rgba(0, 0, 0, .12);position:relative;width:var(--date-width);font-family:var(--date-font-family);box-sizing:border-box}.date-input-field{position:relative;width:100%;height:var(--date-height);display:flex;align-items:center;box-sizing:border-box;padding:0 50px 0 18px;border:var(--date-border);border-radius:var(--date-radius);background:var(--date-background);color:var(--date-text);font-size:var(--date-font-size);font-weight:600;cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease}.date-input-field:hover{border-color:var(--date-border-hover)}.date-input-open .date-input-field{border-color:var(--date-border-focus);box-shadow:0 0 0 1px #68479b1f}.date-input-label{position:absolute;top:0;left:14px;transform:translateY(-50%);padding:0 6px;background:var(--date-background);color:var(--date-border-focus);font-size:13px;font-weight:500;line-height:1;pointer-events:none}.date-input-value{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.date-input-placeholder{color:var(--date-placeholder)}.calendar-icon{position:absolute;right:17px;width:18px;height:18px;box-sizing:border-box;border:1.8px solid #555;border-radius:3px}.calendar-top{position:absolute;left:0;top:4px;width:100%;border-top:1.8px solid #555}.calendar-icon:before,.calendar-icon:after{content:\"\";position:absolute;top:-4px;width:2px;height:6px;background:#555;border-radius:2px}.calendar-icon:before{left:4px}.calendar-icon:after{right:4px}.date-picker{position:absolute;top:calc(100% + 6px);left:0;width:100%;min-width:300px;z-index:1000;padding:14px;box-sizing:border-box;background:#fff;border:1px solid #d5d5d5;border-radius:var(--date-radius);box-shadow:var(--date-shadow)}.date-picker-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}.month-title{font-size:15px;font-weight:700;color:var(--date-text)}.month-button{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:transparent;color:#555;font-size:24px;line-height:1;cursor:pointer}.month-button:hover{background:var(--date-hover);color:var(--date-primary)}.week-days{display:grid;grid-template-columns:repeat(7,1fr);margin-bottom:6px;text-align:center;color:#777;font-size:12px;font-weight:600}.calendar-days{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}.calendar-day{width:100%;aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:transparent;color:var(--date-text);font-size:13px;cursor:pointer;transition:background-color .15s ease,color .15s ease}.calendar-day:hover{background:var(--date-hover)}.calendar-day.other-month{color:silver}.calendar-day.today{border:1px solid var(--date-primary);color:var(--date-primary)}.calendar-day.selected{background:var(--date-selected);color:var(--date-selected-text);border:none}.date-input-disabled .date-input-field{background:#f5f5f5;border-color:#d0d0d0;color:#999;cursor:not-allowed}@media(max-width:768px){.date-input-container{width:100%}.date-picker{min-width:100%}}\n"] }]
457
- }], propDecorators: { label: [{
751
+ args: [{ selector: 'lib-date-input', standalone: true, imports: [], template: "<div\n class=\"date-input-container\"\n [class.date-input-disabled]=\"disabled\"\n [class.date-input-open]=\"isOpen\"\n>\n\n <!-- =====================================\n INPUT FIELD\n ===================================== -->\n\n <div\n class=\"date-input-field\"\n (click)=\"toggleCalendar($event)\"\n >\n\n <!-- LABEL -->\n\n @if (label) {\n\n <label class=\"date-input-label\">\n\n {{ label }}\n\n </label>\n\n }\n\n\n <!-- VALUE -->\n\n <span\n class=\"date-input-value\"\n [class.date-input-placeholder]=\"!value\"\n >\n\n {{ value || placeholder }}\n\n </span>\n\n\n <!-- CALENDAR ICON -->\n\n <span class=\"calendar-icon\">\n\n <span class=\"calendar-top\"></span>\n\n <span class=\"calendar-body\"></span>\n\n </span>\n\n </div>\n\n\n <!-- =====================================\n DATE PICKER\n ===================================== -->\n\n @if (isOpen) {\n\n <div\n class=\"date-picker\"\n (click)=\"$event.stopPropagation()\"\n >\n\n <!-- =================================\n HEADER\n ================================= -->\n\n <div class=\"date-picker-header\">\n\n <button\n type=\"button\"\n class=\"month-button\"\n\n aria-label=\"Previous month\"\n\n (click)=\"previousMonth($event)\"\n >\n\n \u2039\n\n </button>\n\n\n <span class=\"month-title\">\n\n {{ monthName }} {{ year }}\n\n </span>\n\n\n <button\n type=\"button\"\n class=\"month-button\"\n\n aria-label=\"Next month\"\n\n (click)=\"nextMonth($event)\"\n >\n\n \u203A\n\n </button>\n\n </div>\n\n\n <!-- =================================\n WEEK DAYS\n ================================= -->\n\n <div class=\"week-days\">\n\n <span>Sun</span>\n\n <span>Mon</span>\n\n <span>Tue</span>\n\n <span>Wed</span>\n\n <span>Thu</span>\n\n <span>Fri</span>\n\n <span>Sat</span>\n\n </div>\n\n\n <!-- =================================\n CALENDAR DAYS\n ================================= -->\n\n <div class=\"calendar-days\">\n\n @for (\n date of calendarDays;\n track date.getTime()\n ) {\n\n <button\n type=\"button\"\n\n class=\"calendar-day\"\n\n [class.other-month]=\"\n !isCurrentMonth(date)\n \"\n\n [class.today]=\"\n isToday(date)\n \"\n\n [class.selected]=\"\n isSelected(date)\n \"\n\n (click)=\"\n selectDate(date, $event)\n \"\n >\n\n {{ date.getDate() }}\n\n </button>\n\n }\n\n </div>\n\n </div>\n\n }\n\n</div>", styles: [":host{--date-width: 300px;--date-height: 44px;--date-background: #ffffff;--date-border: 1px solid #a9a9a9;--date-border-hover: #777777;--date-border-focus: #68479b;--date-radius: 6px;--date-text: #222222;--date-placeholder: #777777;--date-primary: #68479b;--date-hover: #f3f0f7;--date-selected: #68479b;--date-selected-text: #ffffff;--date-font-family: Arial, Helvetica, sans-serif;--date-font-size: 14px;--date-font-weight: 600;--date-shadow: 0 4px 12px rgba(0, 0, 0, .12);--date-icon-color: #555555;--date-disabled-background: #f5f5f5;--date-disabled-border: #d0d0d0;--date-disabled-text: #999999;display:block;position:relative;width:var(--date-width);box-sizing:border-box;font-family:var(--date-font-family)}.date-input-container{position:relative;width:100%;box-sizing:border-box}.date-input-field{position:relative;width:100%;height:var(--date-height);display:flex;align-items:center;box-sizing:border-box;padding:0 50px 0 18px;border:var(--date-border);border-radius:var(--date-radius);background:var(--date-background);color:var(--date-text);font-size:var(--date-font-size);font-weight:var(--date-font-weight);cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease,background-color .2s ease}.date-input-field:hover{border-color:var(--date-border-hover)}.date-input-open .date-input-field{border-color:var(--date-border-focus);box-shadow:0 0 0 1px #68479b1f}.date-input-label{position:absolute;top:0;left:14px;transform:translateY(-50%);padding:0 6px;background:var(--date-background);color:var(--date-border-focus);font-size:13px;font-weight:500;line-height:1;pointer-events:none}.date-input-value{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--date-text)}.date-input-placeholder{color:var(--date-placeholder)}.calendar-icon{position:absolute;right:17px;width:18px;height:18px;box-sizing:border-box;border:1.8px solid var(--date-icon-color);border-radius:3px}.calendar-top{position:absolute;left:0;top:4px;width:100%;border-top:1.8px solid var(--date-icon-color)}.calendar-icon:before,.calendar-icon:after{content:\"\";position:absolute;top:-4px;width:2px;height:6px;background:var(--date-icon-color);border-radius:2px}.calendar-icon:before{left:4px}.calendar-icon:after{right:4px}.date-picker{position:absolute;top:calc(100% + 6px);left:0;width:100%;min-width:300px;z-index:1000;padding:14px;box-sizing:border-box;background:#fff;border:1px solid #d5d5d5;border-radius:var(--date-radius);box-shadow:var(--date-shadow)}.date-picker-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}.month-title{font-size:15px;font-weight:700;color:var(--date-text)}.month-button{width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:transparent;color:#555;font-size:24px;line-height:1;cursor:pointer;transition:background-color .15s ease,color .15s ease}.month-button:hover{background:var(--date-hover);color:var(--date-primary)}.week-days{display:grid;grid-template-columns:repeat(7,1fr);margin-bottom:6px;text-align:center;color:#777;font-size:12px;font-weight:600}.calendar-days{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}.calendar-day{width:100%;aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:transparent;color:var(--date-text);font-family:var(--date-font-family);font-size:13px;cursor:pointer;transition:background-color .15s ease,color .15s ease}.calendar-day:hover{background:var(--date-hover)}.calendar-day.other-month{color:silver}.calendar-day.today{border:1px solid var(--date-primary);color:var(--date-primary)}.calendar-day.selected{background:var(--date-selected);color:var(--date-selected-text);border:none}.calendar-day.selected.today{background:var(--date-selected);color:var(--date-selected-text)}.date-input-disabled .date-input-field{background:var(--date-disabled-background);border-color:var(--date-disabled-border);color:var(--date-disabled-text);cursor:not-allowed}@media(max-width:768px){:host{width:100%}.date-picker{min-width:100%}}\n"] }]
752
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { label: [{
458
753
  type: Input
459
754
  }], placeholder: [{
460
755
  type: Input
@@ -466,6 +761,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
466
761
  type: Input
467
762
  }], customClass: [{
468
763
  type: Input
764
+ }, {
765
+ type: HostBinding,
766
+ args: ['class']
469
767
  }], valueChange: [{
470
768
  type: Output
471
769
  }], dateChange: [{
@@ -481,6 +779,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
481
779
  }] } });
482
780
 
483
781
  class Dropdown {
782
+ elementRef;
484
783
  // =========================================
485
784
  // INPUTS
486
785
  // =========================================
@@ -494,27 +793,18 @@ class Dropdown {
494
793
  // =========================================
495
794
  // OUTPUTS
496
795
  // =========================================
497
- /**
498
- * Emits the selected value.
499
- */
500
796
  valueChange = new EventEmitter();
501
- /**
502
- * Emits the complete selected option.
503
- */
504
797
  selectionChange = new EventEmitter();
505
- /**
506
- * Emits when the dropdown opens/closes.
507
- */
508
798
  openedChange = new EventEmitter();
509
- /**
510
- * Developer click event.
511
- */
512
799
  clicked = new EventEmitter();
513
800
  // =========================================
514
- // INTERNAL STATE
801
+ // STATE
515
802
  // =========================================
516
803
  isOpen = false;
517
804
  searchText = '';
805
+ constructor(elementRef) {
806
+ this.elementRef = elementRef;
807
+ }
518
808
  // =========================================
519
809
  // FILTERED OPTIONS
520
810
  // =========================================
@@ -536,7 +826,7 @@ class Dropdown {
536
826
  return this.options.find(option => option.value === this.value);
537
827
  }
538
828
  // =========================================
539
- // OPEN / CLOSE
829
+ // TOGGLE
540
830
  // =========================================
541
831
  toggleDropdown(event) {
542
832
  if (this.disabled) {
@@ -545,35 +835,52 @@ class Dropdown {
545
835
  if (event) {
546
836
  this.clicked.emit(event);
547
837
  }
548
- this.isOpen = !this.isOpen;
838
+ this.isOpen =
839
+ !this.isOpen;
549
840
  this.openedChange.emit(this.isOpen);
550
841
  if (!this.isOpen) {
551
842
  this.searchText = '';
552
843
  }
553
844
  }
845
+ // =========================================
846
+ // DOCUMENT CLICK
847
+ // =========================================
554
848
  onDocumentClick(event) {
849
+ if (!this.isOpen) {
850
+ return;
851
+ }
555
852
  const target = event.target;
556
- const dropdown = target.closest('lib-dropdown');
557
- if (!dropdown && this.isOpen) {
558
- this.isOpen = false;
559
- this.searchText = '';
560
- this.openedChange.emit(false);
853
+ const host = this.elementRef.nativeElement;
854
+ if (!host.contains(target)) {
855
+ this.closeDropdown();
856
+ }
857
+ }
858
+ // =========================================
859
+ // CLOSE
860
+ // =========================================
861
+ closeDropdown() {
862
+ if (!this.isOpen) {
863
+ return;
561
864
  }
865
+ this.isOpen = false;
866
+ this.searchText = '';
867
+ this.openedChange.emit(false);
562
868
  }
563
869
  // =========================================
564
- // SELECT OPTION
870
+ // SELECT
565
871
  // =========================================
566
872
  selectOption(option, event) {
567
873
  if (option.disabled) {
568
874
  return;
569
875
  }
570
- this.value = option.value;
876
+ this.value =
877
+ option.value;
571
878
  this.valueChange.emit(option.value);
572
879
  this.selectionChange.emit(option);
573
880
  this.clicked.emit(event);
574
881
  this.isOpen = false;
575
- this.openedChange.emit(false);
576
882
  this.searchText = '';
883
+ this.openedChange.emit(false);
577
884
  }
578
885
  // =========================================
579
886
  // SEARCH
@@ -583,13 +890,13 @@ class Dropdown {
583
890
  this.searchText =
584
891
  input.value;
585
892
  }
586
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: Dropdown, deps: [], target: i0.ɵɵFactoryTarget.Component });
587
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: Dropdown, isStandalone: true, selector: "lib-dropdown", inputs: { label: "label", placeholder: "placeholder", options: "options", value: "value", disabled: "disabled", searchable: "searchable", customClass: "customClass" }, outputs: { valueChange: "valueChange", selectionChange: "selectionChange", openedChange: "openedChange", clicked: "clicked" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, ngImport: i0, template: "<div\n class=\"dropdown-container\"\n [class]=\"customClass\"\n [class.dropdown-disabled]=\"disabled\"\n [class.dropdown-open]=\"isOpen\"\n>\n\n <!-- =====================================\n DROPDOWN FIELD\n ===================================== -->\n\n <div\n class=\"dropdown-field\"\n (click)=\"toggleDropdown($event)\"\n >\n\n <!-- Label -->\n\n @if (label) {\n <label class=\"dropdown-label\">\n {{ label }}\n </label>\n }\n\n\n <!-- Selected value -->\n\n <span\n class=\"dropdown-value\"\n [class.dropdown-placeholder]=\"!selectedOption\"\n >\n {{\n selectedOption?.label ||\n placeholder\n }}\n </span>\n\n\n <!-- Arrow -->\n\n <span\n class=\"dropdown-arrow\"\n [class.arrow-up]=\"isOpen\"\n >\n </span>\n\n </div>\n\n\n <!-- =====================================\n DROPDOWN MENU\n ===================================== -->\n\n @if (isOpen) {\n\n <div\n class=\"dropdown-menu\"\n (click)=\"$event.stopPropagation()\"\n >\n\n <!-- Search -->\n\n @if (searchable) {\n\n <div class=\"dropdown-search\">\n\n <input\n type=\"text\"\n class=\"dropdown-search-input\"\n\n placeholder=\"Search...\"\n\n [value]=\"searchText\"\n\n (input)=\"onSearch($event)\"\n />\n\n </div>\n\n }\n\n\n <!-- Options -->\n\n <div class=\"dropdown-options\">\n\n @for (\n option of filteredOptions;\n track option.value\n ) {\n\n <div\n class=\"dropdown-option\"\n\n [class.option-disabled]=\"\n option.disabled\n \"\n\n [class.option-selected]=\"\n option.value === value\n \"\n\n (click)=\"\n selectOption(option, $event)\n \"\n >\n\n {{ option.label }}\n\n </div>\n\n }\n\n\n <!-- No result -->\n\n @if (filteredOptions.length === 0) {\n\n <div class=\"dropdown-no-result\">\n No results found\n </div>\n\n }\n\n </div>\n\n </div>\n\n }\n\n</div>", styles: [".dropdown-container{--dropdown-width: 300px;--dropdown-height: 44px;--dropdown-background: #ffffff;--dropdown-border: 1px solid #a9a9a9;--dropdown-border-hover: #777777;--dropdown-border-focus: #68479b;--dropdown-radius: 6px;--dropdown-text-color: #222222;--dropdown-placeholder-color: #777777;--dropdown-menu-background: #ffffff;--dropdown-option-hover: #f3f0f7;--dropdown-option-selected: #eee8f5;--dropdown-disabled: #f5f5f5;--dropdown-font-family: Arial, Helvetica, sans-serif;--dropdown-font-size: 14px;--dropdown-font-weight: 600;--dropdown-shadow: 0 4px 12px rgba(0, 0, 0, .12);position:relative;width:var(--dropdown-width);font-family:var(--dropdown-font-family);box-sizing:border-box}.dropdown-field{position:relative;width:100%;height:var(--dropdown-height);display:flex;align-items:center;box-sizing:border-box;padding:0 48px 0 18px;border:var(--dropdown-border);border-radius:var(--dropdown-radius);background:var(--dropdown-background);color:var(--dropdown-text-color);font-size:var(--dropdown-font-size);font-weight:var(--dropdown-font-weight);cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease}.dropdown-field:hover{border-color:var(--dropdown-border-hover)}.dropdown-open .dropdown-field{border-color:var(--dropdown-border-focus);box-shadow:0 0 0 1px #68479b1f}.dropdown-label{position:absolute;top:0;left:14px;transform:translateY(-50%);padding:0 6px;background:var(--dropdown-background);color:var(--dropdown-border-focus);font-size:13px;font-weight:500;line-height:1;pointer-events:none}.dropdown-value{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--dropdown-text-color)}.dropdown-placeholder{color:var(--dropdown-placeholder-color)}.dropdown-arrow{position:absolute;right:18px;top:50%;width:9px;height:9px;border-right:2px solid #555;border-bottom:2px solid #555;transform:translateY(-65%) rotate(45deg);transition:transform .2s ease}.dropdown-arrow.arrow-up{transform:translateY(-25%) rotate(225deg)}.dropdown-menu{position:absolute;top:calc(100% + 6px);left:0;width:100%;z-index:1000;overflow:hidden;background:var(--dropdown-menu-background);border:1px solid #d0d0d0;border-radius:var(--dropdown-radius);box-shadow:var(--dropdown-shadow)}.dropdown-search{padding:8px;border-bottom:1px solid #eeeeee}.dropdown-search-input{width:100%;height:38px;box-sizing:border-box;padding:0 12px;border:1px solid #cfcfcf;border-radius:5px;outline:none;background:#fff;font-family:var(--dropdown-font-family);font-size:14px}.dropdown-search-input:focus{border-color:var(--dropdown-border-focus)}.dropdown-options{max-height:240px;overflow-y:auto}.dropdown-option{min-height:42px;display:flex;align-items:center;padding:0 14px;box-sizing:border-box;color:var(--dropdown-text-color);font-size:var(--dropdown-font-size);cursor:pointer;transition:background-color .15s ease}.dropdown-option:hover{background:var(--dropdown-option-hover)}.dropdown-option.option-selected{background:var(--dropdown-option-selected);color:var(--dropdown-border-focus);font-weight:600}.dropdown-option.option-disabled{color:#aaa;cursor:not-allowed;background:transparent}.dropdown-no-result{min-height:50px;display:flex;align-items:center;justify-content:center;padding:0 15px;color:#888;font-size:13px}.dropdown-disabled .dropdown-field{background:var(--dropdown-disabled);color:#999;border-color:#d0d0d0;cursor:not-allowed}.dropdown-options::-webkit-scrollbar{width:6px}.dropdown-options::-webkit-scrollbar-thumb{background:#c5c5c5;border-radius:10px}@media(max-width:768px){.dropdown-container{width:100%}.dropdown-field{height:var(--dropdown-height)}}\n"] });
893
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: Dropdown, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
894
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: Dropdown, isStandalone: true, selector: "lib-dropdown", inputs: { label: "label", placeholder: "placeholder", options: "options", value: "value", disabled: "disabled", searchable: "searchable", customClass: "customClass" }, outputs: { valueChange: "valueChange", selectionChange: "selectionChange", openedChange: "openedChange", clicked: "clicked" }, host: { listeners: { "document:click": "onDocumentClick($event)" }, properties: { "class": "this.customClass" } }, ngImport: i0, template: "<div\n class=\"dropdown-container\"\n [class.dropdown-disabled]=\"disabled\"\n [class.dropdown-open]=\"isOpen\"\n>\n\n <!-- =====================================\n FIELD\n ===================================== -->\n\n <div\n class=\"dropdown-field\"\n (click)=\"toggleDropdown($event)\"\n >\n\n <!-- Label -->\n\n @if (label) {\n\n <label class=\"dropdown-label\">\n {{ label }}\n </label>\n\n }\n\n\n <!-- Selected Value -->\n\n <span\n class=\"dropdown-value\"\n [class.dropdown-placeholder]=\"\n !selectedOption\n \"\n >\n\n {{\n selectedOption?.label ||\n placeholder\n }}\n\n </span>\n\n\n <!-- Arrow -->\n\n <span\n class=\"dropdown-arrow\"\n [class.arrow-up]=\"isOpen\"\n ></span>\n\n </div>\n\n\n <!-- =====================================\n MENU\n ===================================== -->\n\n @if (isOpen) {\n\n <div\n class=\"dropdown-menu\"\n (click)=\"$event.stopPropagation()\"\n >\n\n <!-- SEARCH -->\n\n @if (searchable) {\n\n <div class=\"dropdown-search\">\n\n <input\n type=\"text\"\n class=\"dropdown-search-input\"\n\n placeholder=\"Search...\"\n\n [value]=\"searchText\"\n\n (input)=\"onSearch($event)\"\n />\n\n </div>\n\n }\n\n\n <!-- OPTIONS -->\n\n <div class=\"dropdown-options\">\n\n @for (\n option of filteredOptions;\n track option.value\n ) {\n\n <div\n class=\"dropdown-option\"\n\n [class.option-disabled]=\"\n option.disabled\n \"\n\n [class.option-selected]=\"\n option.value === value\n \"\n\n (click)=\"\n selectOption(option, $event)\n \"\n >\n\n {{ option.label }}\n\n </div>\n\n }\n\n\n <!-- NO RESULTS -->\n\n @if (\n filteredOptions.length === 0\n ) {\n\n <div class=\"dropdown-no-result\">\n\n No results found\n\n </div>\n\n }\n\n </div>\n\n </div>\n\n }\n\n</div>", styles: [":host{--dropdown-width: 300px;--dropdown-height: 44px;--dropdown-background: #ffffff;--dropdown-border: 1px solid #a9a9a9;--dropdown-border-hover: #777777;--dropdown-border-focus: #68479b;--dropdown-radius: 6px;--dropdown-text-color: #222222;--dropdown-placeholder-color: #777777;--dropdown-menu-background: #ffffff;--dropdown-option-hover: #f3f0f7;--dropdown-option-selected: #eee8f5;--dropdown-disabled: #f5f5f5;--dropdown-font-family: Arial, Helvetica, sans-serif;--dropdown-font-size: 14px;--dropdown-font-weight: 600;--dropdown-shadow: 0 4px 12px rgba(0, 0, 0, .12);--dropdown-label-color: #68479b;--dropdown-arrow-color: #555555;--dropdown-search-border: #cfcfcf;display:block;position:relative;width:var(--dropdown-width);box-sizing:border-box}.dropdown-container{position:relative;width:100%;font-family:var(--dropdown-font-family);box-sizing:border-box}.dropdown-field{position:relative;width:100%;height:var(--dropdown-height);display:flex;align-items:center;box-sizing:border-box;padding:0 48px 0 18px;border:var(--dropdown-border);border-radius:var(--dropdown-radius);background:var(--dropdown-background);color:var(--dropdown-text-color);font-size:var(--dropdown-font-size);font-weight:var(--dropdown-font-weight);cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease}.dropdown-field:hover{border-color:var(--dropdown-border-hover)}.dropdown-open .dropdown-field{border-color:var(--dropdown-border-focus);box-shadow:0 0 0 1px #68479b1f}.dropdown-label{position:absolute;top:0;left:14px;transform:translateY(-50%);padding:0 6px;background:var(--dropdown-background);color:var(--dropdown-label-color);font-size:13px;font-weight:500;line-height:1;pointer-events:none}.dropdown-value{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--dropdown-text-color)}.dropdown-placeholder{color:var(--dropdown-placeholder-color)}.dropdown-arrow{position:absolute;right:18px;top:50%;width:9px;height:9px;border-right:2px solid var(--dropdown-arrow-color);border-bottom:2px solid var(--dropdown-arrow-color);transform:translateY(-65%) rotate(45deg);transition:transform .2s ease}.dropdown-arrow.arrow-up{transform:translateY(-25%) rotate(225deg)}.dropdown-menu{position:absolute;top:calc(100% + 6px);left:0;width:100%;z-index:1000;overflow:hidden;background:var(--dropdown-menu-background);border:1px solid #d0d0d0;border-radius:var(--dropdown-radius);box-shadow:var(--dropdown-shadow)}.dropdown-search{padding:8px;border-bottom:1px solid #eeeeee}.dropdown-search-input{width:100%;height:38px;box-sizing:border-box;padding:0 12px;border:1px solid var(--dropdown-search-border);border-radius:5px;outline:none;background:#fff;color:var(--dropdown-text-color);font-family:var(--dropdown-font-family);font-size:14px}.dropdown-search-input:focus{border-color:var(--dropdown-border-focus)}.dropdown-options{max-height:240px;overflow-y:auto}.dropdown-option{min-height:42px;display:flex;align-items:center;padding:0 14px;box-sizing:border-box;color:var(--dropdown-text-color);font-size:var(--dropdown-font-size);cursor:pointer;transition:background-color .15s ease}.dropdown-option:hover{background:var(--dropdown-option-hover)}.dropdown-option.option-selected{background:var(--dropdown-option-selected);color:var(--dropdown-border-focus);font-weight:600}.dropdown-option.option-disabled{color:#aaa;cursor:not-allowed;background:transparent}.dropdown-no-result{min-height:50px;display:flex;align-items:center;justify-content:center;padding:0 15px;color:#888;font-size:13px}.dropdown-disabled .dropdown-field{background:var(--dropdown-disabled);color:#999;border-color:#d0d0d0;cursor:not-allowed}.dropdown-options::-webkit-scrollbar{width:6px}.dropdown-options::-webkit-scrollbar-thumb{background:#c5c5c5;border-radius:10px}@media(max-width:768px){:host{width:100%}.dropdown-field{height:var(--dropdown-height)}}\n"] });
588
895
  }
589
896
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: Dropdown, decorators: [{
590
897
  type: Component,
591
- args: [{ selector: 'lib-dropdown', standalone: true, imports: [], template: "<div\n class=\"dropdown-container\"\n [class]=\"customClass\"\n [class.dropdown-disabled]=\"disabled\"\n [class.dropdown-open]=\"isOpen\"\n>\n\n <!-- =====================================\n DROPDOWN FIELD\n ===================================== -->\n\n <div\n class=\"dropdown-field\"\n (click)=\"toggleDropdown($event)\"\n >\n\n <!-- Label -->\n\n @if (label) {\n <label class=\"dropdown-label\">\n {{ label }}\n </label>\n }\n\n\n <!-- Selected value -->\n\n <span\n class=\"dropdown-value\"\n [class.dropdown-placeholder]=\"!selectedOption\"\n >\n {{\n selectedOption?.label ||\n placeholder\n }}\n </span>\n\n\n <!-- Arrow -->\n\n <span\n class=\"dropdown-arrow\"\n [class.arrow-up]=\"isOpen\"\n >\n </span>\n\n </div>\n\n\n <!-- =====================================\n DROPDOWN MENU\n ===================================== -->\n\n @if (isOpen) {\n\n <div\n class=\"dropdown-menu\"\n (click)=\"$event.stopPropagation()\"\n >\n\n <!-- Search -->\n\n @if (searchable) {\n\n <div class=\"dropdown-search\">\n\n <input\n type=\"text\"\n class=\"dropdown-search-input\"\n\n placeholder=\"Search...\"\n\n [value]=\"searchText\"\n\n (input)=\"onSearch($event)\"\n />\n\n </div>\n\n }\n\n\n <!-- Options -->\n\n <div class=\"dropdown-options\">\n\n @for (\n option of filteredOptions;\n track option.value\n ) {\n\n <div\n class=\"dropdown-option\"\n\n [class.option-disabled]=\"\n option.disabled\n \"\n\n [class.option-selected]=\"\n option.value === value\n \"\n\n (click)=\"\n selectOption(option, $event)\n \"\n >\n\n {{ option.label }}\n\n </div>\n\n }\n\n\n <!-- No result -->\n\n @if (filteredOptions.length === 0) {\n\n <div class=\"dropdown-no-result\">\n No results found\n </div>\n\n }\n\n </div>\n\n </div>\n\n }\n\n</div>", styles: [".dropdown-container{--dropdown-width: 300px;--dropdown-height: 44px;--dropdown-background: #ffffff;--dropdown-border: 1px solid #a9a9a9;--dropdown-border-hover: #777777;--dropdown-border-focus: #68479b;--dropdown-radius: 6px;--dropdown-text-color: #222222;--dropdown-placeholder-color: #777777;--dropdown-menu-background: #ffffff;--dropdown-option-hover: #f3f0f7;--dropdown-option-selected: #eee8f5;--dropdown-disabled: #f5f5f5;--dropdown-font-family: Arial, Helvetica, sans-serif;--dropdown-font-size: 14px;--dropdown-font-weight: 600;--dropdown-shadow: 0 4px 12px rgba(0, 0, 0, .12);position:relative;width:var(--dropdown-width);font-family:var(--dropdown-font-family);box-sizing:border-box}.dropdown-field{position:relative;width:100%;height:var(--dropdown-height);display:flex;align-items:center;box-sizing:border-box;padding:0 48px 0 18px;border:var(--dropdown-border);border-radius:var(--dropdown-radius);background:var(--dropdown-background);color:var(--dropdown-text-color);font-size:var(--dropdown-font-size);font-weight:var(--dropdown-font-weight);cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease}.dropdown-field:hover{border-color:var(--dropdown-border-hover)}.dropdown-open .dropdown-field{border-color:var(--dropdown-border-focus);box-shadow:0 0 0 1px #68479b1f}.dropdown-label{position:absolute;top:0;left:14px;transform:translateY(-50%);padding:0 6px;background:var(--dropdown-background);color:var(--dropdown-border-focus);font-size:13px;font-weight:500;line-height:1;pointer-events:none}.dropdown-value{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--dropdown-text-color)}.dropdown-placeholder{color:var(--dropdown-placeholder-color)}.dropdown-arrow{position:absolute;right:18px;top:50%;width:9px;height:9px;border-right:2px solid #555;border-bottom:2px solid #555;transform:translateY(-65%) rotate(45deg);transition:transform .2s ease}.dropdown-arrow.arrow-up{transform:translateY(-25%) rotate(225deg)}.dropdown-menu{position:absolute;top:calc(100% + 6px);left:0;width:100%;z-index:1000;overflow:hidden;background:var(--dropdown-menu-background);border:1px solid #d0d0d0;border-radius:var(--dropdown-radius);box-shadow:var(--dropdown-shadow)}.dropdown-search{padding:8px;border-bottom:1px solid #eeeeee}.dropdown-search-input{width:100%;height:38px;box-sizing:border-box;padding:0 12px;border:1px solid #cfcfcf;border-radius:5px;outline:none;background:#fff;font-family:var(--dropdown-font-family);font-size:14px}.dropdown-search-input:focus{border-color:var(--dropdown-border-focus)}.dropdown-options{max-height:240px;overflow-y:auto}.dropdown-option{min-height:42px;display:flex;align-items:center;padding:0 14px;box-sizing:border-box;color:var(--dropdown-text-color);font-size:var(--dropdown-font-size);cursor:pointer;transition:background-color .15s ease}.dropdown-option:hover{background:var(--dropdown-option-hover)}.dropdown-option.option-selected{background:var(--dropdown-option-selected);color:var(--dropdown-border-focus);font-weight:600}.dropdown-option.option-disabled{color:#aaa;cursor:not-allowed;background:transparent}.dropdown-no-result{min-height:50px;display:flex;align-items:center;justify-content:center;padding:0 15px;color:#888;font-size:13px}.dropdown-disabled .dropdown-field{background:var(--dropdown-disabled);color:#999;border-color:#d0d0d0;cursor:not-allowed}.dropdown-options::-webkit-scrollbar{width:6px}.dropdown-options::-webkit-scrollbar-thumb{background:#c5c5c5;border-radius:10px}@media(max-width:768px){.dropdown-container{width:100%}.dropdown-field{height:var(--dropdown-height)}}\n"] }]
592
- }], propDecorators: { label: [{
898
+ args: [{ selector: 'lib-dropdown', standalone: true, imports: [], template: "<div\n class=\"dropdown-container\"\n [class.dropdown-disabled]=\"disabled\"\n [class.dropdown-open]=\"isOpen\"\n>\n\n <!-- =====================================\n FIELD\n ===================================== -->\n\n <div\n class=\"dropdown-field\"\n (click)=\"toggleDropdown($event)\"\n >\n\n <!-- Label -->\n\n @if (label) {\n\n <label class=\"dropdown-label\">\n {{ label }}\n </label>\n\n }\n\n\n <!-- Selected Value -->\n\n <span\n class=\"dropdown-value\"\n [class.dropdown-placeholder]=\"\n !selectedOption\n \"\n >\n\n {{\n selectedOption?.label ||\n placeholder\n }}\n\n </span>\n\n\n <!-- Arrow -->\n\n <span\n class=\"dropdown-arrow\"\n [class.arrow-up]=\"isOpen\"\n ></span>\n\n </div>\n\n\n <!-- =====================================\n MENU\n ===================================== -->\n\n @if (isOpen) {\n\n <div\n class=\"dropdown-menu\"\n (click)=\"$event.stopPropagation()\"\n >\n\n <!-- SEARCH -->\n\n @if (searchable) {\n\n <div class=\"dropdown-search\">\n\n <input\n type=\"text\"\n class=\"dropdown-search-input\"\n\n placeholder=\"Search...\"\n\n [value]=\"searchText\"\n\n (input)=\"onSearch($event)\"\n />\n\n </div>\n\n }\n\n\n <!-- OPTIONS -->\n\n <div class=\"dropdown-options\">\n\n @for (\n option of filteredOptions;\n track option.value\n ) {\n\n <div\n class=\"dropdown-option\"\n\n [class.option-disabled]=\"\n option.disabled\n \"\n\n [class.option-selected]=\"\n option.value === value\n \"\n\n (click)=\"\n selectOption(option, $event)\n \"\n >\n\n {{ option.label }}\n\n </div>\n\n }\n\n\n <!-- NO RESULTS -->\n\n @if (\n filteredOptions.length === 0\n ) {\n\n <div class=\"dropdown-no-result\">\n\n No results found\n\n </div>\n\n }\n\n </div>\n\n </div>\n\n }\n\n</div>", styles: [":host{--dropdown-width: 300px;--dropdown-height: 44px;--dropdown-background: #ffffff;--dropdown-border: 1px solid #a9a9a9;--dropdown-border-hover: #777777;--dropdown-border-focus: #68479b;--dropdown-radius: 6px;--dropdown-text-color: #222222;--dropdown-placeholder-color: #777777;--dropdown-menu-background: #ffffff;--dropdown-option-hover: #f3f0f7;--dropdown-option-selected: #eee8f5;--dropdown-disabled: #f5f5f5;--dropdown-font-family: Arial, Helvetica, sans-serif;--dropdown-font-size: 14px;--dropdown-font-weight: 600;--dropdown-shadow: 0 4px 12px rgba(0, 0, 0, .12);--dropdown-label-color: #68479b;--dropdown-arrow-color: #555555;--dropdown-search-border: #cfcfcf;display:block;position:relative;width:var(--dropdown-width);box-sizing:border-box}.dropdown-container{position:relative;width:100%;font-family:var(--dropdown-font-family);box-sizing:border-box}.dropdown-field{position:relative;width:100%;height:var(--dropdown-height);display:flex;align-items:center;box-sizing:border-box;padding:0 48px 0 18px;border:var(--dropdown-border);border-radius:var(--dropdown-radius);background:var(--dropdown-background);color:var(--dropdown-text-color);font-size:var(--dropdown-font-size);font-weight:var(--dropdown-font-weight);cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease}.dropdown-field:hover{border-color:var(--dropdown-border-hover)}.dropdown-open .dropdown-field{border-color:var(--dropdown-border-focus);box-shadow:0 0 0 1px #68479b1f}.dropdown-label{position:absolute;top:0;left:14px;transform:translateY(-50%);padding:0 6px;background:var(--dropdown-background);color:var(--dropdown-label-color);font-size:13px;font-weight:500;line-height:1;pointer-events:none}.dropdown-value{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:var(--dropdown-text-color)}.dropdown-placeholder{color:var(--dropdown-placeholder-color)}.dropdown-arrow{position:absolute;right:18px;top:50%;width:9px;height:9px;border-right:2px solid var(--dropdown-arrow-color);border-bottom:2px solid var(--dropdown-arrow-color);transform:translateY(-65%) rotate(45deg);transition:transform .2s ease}.dropdown-arrow.arrow-up{transform:translateY(-25%) rotate(225deg)}.dropdown-menu{position:absolute;top:calc(100% + 6px);left:0;width:100%;z-index:1000;overflow:hidden;background:var(--dropdown-menu-background);border:1px solid #d0d0d0;border-radius:var(--dropdown-radius);box-shadow:var(--dropdown-shadow)}.dropdown-search{padding:8px;border-bottom:1px solid #eeeeee}.dropdown-search-input{width:100%;height:38px;box-sizing:border-box;padding:0 12px;border:1px solid var(--dropdown-search-border);border-radius:5px;outline:none;background:#fff;color:var(--dropdown-text-color);font-family:var(--dropdown-font-family);font-size:14px}.dropdown-search-input:focus{border-color:var(--dropdown-border-focus)}.dropdown-options{max-height:240px;overflow-y:auto}.dropdown-option{min-height:42px;display:flex;align-items:center;padding:0 14px;box-sizing:border-box;color:var(--dropdown-text-color);font-size:var(--dropdown-font-size);cursor:pointer;transition:background-color .15s ease}.dropdown-option:hover{background:var(--dropdown-option-hover)}.dropdown-option.option-selected{background:var(--dropdown-option-selected);color:var(--dropdown-border-focus);font-weight:600}.dropdown-option.option-disabled{color:#aaa;cursor:not-allowed;background:transparent}.dropdown-no-result{min-height:50px;display:flex;align-items:center;justify-content:center;padding:0 15px;color:#888;font-size:13px}.dropdown-disabled .dropdown-field{background:var(--dropdown-disabled);color:#999;border-color:#d0d0d0;cursor:not-allowed}.dropdown-options::-webkit-scrollbar{width:6px}.dropdown-options::-webkit-scrollbar-thumb{background:#c5c5c5;border-radius:10px}@media(max-width:768px){:host{width:100%}.dropdown-field{height:var(--dropdown-height)}}\n"] }]
899
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { label: [{
593
900
  type: Input
594
901
  }], placeholder: [{
595
902
  type: Input
@@ -603,6 +910,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
603
910
  type: Input
604
911
  }], customClass: [{
605
912
  type: Input
913
+ }, {
914
+ type: HostBinding,
915
+ args: ['class']
606
916
  }], valueChange: [{
607
917
  type: Output
608
918
  }], selectionChange: [{
@@ -613,7 +923,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImpor
613
923
  type: Output
614
924
  }], onDocumentClick: [{
615
925
  type: HostListener,
616
- args: ['document:click', ['$event']]
926
+ args: ['document:click',
927
+ ['$event']]
617
928
  }] } });
618
929
 
619
930
  /*