@lamenna/lxp-angular 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,11 @@
1
1
  import * as i1 from '@angular/common';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { EventEmitter, HostBinding, Output, Input, Component } from '@angular/core';
5
- import { buttonConfig } from '@lamenna/lxp-shared-components';
4
+ import { EventEmitter, HostBinding, Output, Input, Component, Injectable } from '@angular/core';
5
+ import { buttonConfig, tableThemeConfig, tableConfig, defaultTheme } from '@lamenna/lxp-shared-components';
6
+ import * as i2 from '@angular/forms';
7
+ import { FormsModule } from '@angular/forms';
8
+ import { BehaviorSubject } from 'rxjs';
6
9
 
7
10
  class ButtonComponent {
8
11
  content;
@@ -13,7 +16,12 @@ class ButtonComponent {
13
16
  id;
14
17
  ariaLabel;
15
18
  testID;
16
- label;
19
+ get label() {
20
+ return this.content;
21
+ }
22
+ set label(value) {
23
+ this.content = value;
24
+ }
17
25
  onClick = new EventEmitter();
18
26
  get hostStyles() {
19
27
  const variantConfig = buttonConfig.variants[this.variant];
@@ -31,8 +39,8 @@ class ButtonComponent {
31
39
  [this.className || ""]: !!this.className,
32
40
  };
33
41
  }
34
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
35
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: ButtonComponent, isStandalone: true, selector: "lxp-button", inputs: { content: "content", variant: "variant", size: "size", disabled: "disabled", className: "className", id: "id", ariaLabel: "ariaLabel", testID: "testID", label: "label" }, outputs: { onClick: "onClick" }, host: { properties: { "style": "this.hostStyles" } }, ngImport: i0, template: `
42
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
43
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.0", type: ButtonComponent, isStandalone: true, selector: "lxp-button", inputs: { content: "content", variant: "variant", size: "size", disabled: "disabled", className: "className", id: "id", ariaLabel: "ariaLabel", testID: "testID", label: "label" }, outputs: { onClick: "onClick" }, host: { properties: { "style": "this.hostStyles" } }, ngImport: i0, template: `
36
44
  <button
37
45
  [attr.id]="id"
38
46
  [attr.data-testid]="testID"
@@ -45,7 +53,7 @@ class ButtonComponent {
45
53
  </button>
46
54
  `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
47
55
  }
48
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ButtonComponent, decorators: [{
56
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ButtonComponent, decorators: [{
49
57
  type: Component,
50
58
  args: [{
51
59
  selector: "lxp-button",
@@ -89,9 +97,671 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
89
97
  args: ["style"]
90
98
  }] } });
91
99
 
100
+ class TableComponent {
101
+ columns = [];
102
+ data = [];
103
+ actions = [];
104
+ selectable = false;
105
+ showPagination = true;
106
+ showSearch = true;
107
+ loading = false;
108
+ theme = "tera";
109
+ title;
110
+ titleLink;
111
+ serverSide = false;
112
+ totalCount;
113
+ currentPage;
114
+ pageSize;
115
+ pageSizeOptions;
116
+ emptyState;
117
+ enableRowClick = false;
118
+ searchPlaceholder;
119
+ onSelectionChange = new EventEmitter();
120
+ onPageChange = new EventEmitter();
121
+ onPageSizeChange = new EventEmitter();
122
+ onSearch = new EventEmitter();
123
+ onRowClick = new EventEmitter();
124
+ get fontFamily() {
125
+ return tableThemeConfig[this.theme].fontFamily;
126
+ }
127
+ defaultTitle = tableConfig.defaultTitle;
128
+ loadingMessage = tableConfig.loadingMessage;
129
+ searchTerm = "";
130
+ selectedRows = [];
131
+ get columnSpan() {
132
+ return (this.columns.length +
133
+ (this.selectable ? 1 : 0) +
134
+ (this.actions?.length ? 1 : 0));
135
+ }
136
+ get totalItems() {
137
+ if (this.serverSide) {
138
+ return this.totalCount ?? this.data.length;
139
+ }
140
+ return this.filteredData.length;
141
+ }
142
+ get currentPageInternal() {
143
+ return this.currentPage ?? this._currentPage;
144
+ }
145
+ get pageSizeInternal() {
146
+ return this.pageSize ?? this._pageSize;
147
+ }
148
+ get pageSizeOptionsInternal() {
149
+ return this.pageSizeOptions ?? tableConfig.defaultPageSizeOptions;
150
+ }
151
+ _currentPage = 1;
152
+ _pageSize = tableConfig.defaultPageSize;
153
+ get filteredData() {
154
+ if (!this.showSearch || !this.searchTerm.trim()) {
155
+ return this.data;
156
+ }
157
+ const term = this.searchTerm.toLowerCase();
158
+ return this.data.filter((row) => Object.values(row).some((value) => String(typeof value === "object" && value !== null
159
+ ? value.line1 ?? value.line2 ?? ""
160
+ : value ?? "")
161
+ .toLowerCase()
162
+ .includes(term)));
163
+ }
164
+ get pagedData() {
165
+ if (!this.showPagination || this.serverSide) {
166
+ return this.filteredData;
167
+ }
168
+ const start = (this.currentPageInternal - 1) * this.pageSizeInternal;
169
+ return this.filteredData.slice(start, start + this.pageSizeInternal);
170
+ }
171
+ get totalPages() {
172
+ if (!this.showPagination) {
173
+ return 1;
174
+ }
175
+ return Math.max(1, Math.ceil(this.totalItems / this.pageSizeInternal));
176
+ }
177
+ isRichCell(value) {
178
+ return (value &&
179
+ typeof value === "object" &&
180
+ ("line1" in value || "line2" in value || "text" in value || "name" in value));
181
+ }
182
+ isRowSelected(index) {
183
+ return this.selectedRows.includes(index);
184
+ }
185
+ globalRowIndex(localIndex) {
186
+ if (this.serverSide) {
187
+ return localIndex;
188
+ }
189
+ return (this.currentPageInternal - 1) * this.pageSizeInternal + localIndex;
190
+ }
191
+ toggleRowSelection(index) {
192
+ const exists = this.selectedRows.includes(index);
193
+ this.selectedRows = exists
194
+ ? this.selectedRows.filter((i) => i !== index)
195
+ : [...this.selectedRows, index];
196
+ this.onSelectionChange.emit(this.selectedRows);
197
+ }
198
+ get emptyMessage() {
199
+ const custom = this.emptyState?.message;
200
+ const showDefault = this.emptyState?.showDefault ?? true;
201
+ if (custom)
202
+ return custom;
203
+ return showDefault ? tableConfig.emptyMessage : "";
204
+ }
205
+ onSearchChange(term) {
206
+ const value = typeof term === "string"
207
+ ? term
208
+ : term?.target?.value ?? "";
209
+ this.searchTerm = value;
210
+ this.onSearch.emit({
211
+ page: this.currentPageInternal,
212
+ pageSize: this.pageSizeInternal,
213
+ searchTerm: value,
214
+ filters: {},
215
+ });
216
+ }
217
+ onPageChangeInternal(nextPage) {
218
+ if (nextPage < 1 || nextPage > this.totalPages)
219
+ return;
220
+ if (this.currentPage == null) {
221
+ this._currentPage = nextPage;
222
+ }
223
+ this.onPageChange.emit({
224
+ page: nextPage,
225
+ pageSize: this.pageSizeInternal,
226
+ searchTerm: this.searchTerm,
227
+ filters: {},
228
+ });
229
+ }
230
+ onPageSizeChangeInternal(nextSize) {
231
+ const size = typeof nextSize === "number" ? nextSize : Number(nextSize ?? 0);
232
+ if (this.pageSize == null) {
233
+ this._pageSize = size;
234
+ this._currentPage = 1;
235
+ }
236
+ this.onPageSizeChange.emit({
237
+ page: 1,
238
+ pageSize: size,
239
+ searchTerm: this.searchTerm,
240
+ filters: {},
241
+ });
242
+ }
243
+ handleRowClick(row, localIndex) {
244
+ if (!this.enableRowClick)
245
+ return;
246
+ const globalIndex = this.globalRowIndex(localIndex);
247
+ this.onRowClick.emit({ row, index: globalIndex });
248
+ }
249
+ isActionDisabled(action, row) {
250
+ return action.disabled ? action.disabled(row) : false;
251
+ }
252
+ runAction(action, row) {
253
+ if (this.isActionDisabled(action, row))
254
+ return;
255
+ action.action(row);
256
+ }
257
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
258
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.0", type: TableComponent, isStandalone: true, selector: "lxp-table", inputs: { columns: "columns", data: "data", actions: "actions", selectable: "selectable", showPagination: "showPagination", showSearch: "showSearch", loading: "loading", theme: "theme", title: "title", titleLink: "titleLink", serverSide: "serverSide", totalCount: "totalCount", currentPage: "currentPage", pageSize: "pageSize", pageSizeOptions: "pageSizeOptions", emptyState: "emptyState", enableRowClick: "enableRowClick", searchPlaceholder: "searchPlaceholder" }, outputs: { onSelectionChange: "onSelectionChange", onPageChange: "onPageChange", onPageSizeChange: "onPageSizeChange", onSearch: "onSearch", onRowClick: "onRowClick" }, host: { properties: { "style.fontFamily": "this.fontFamily" } }, ngImport: i0, template: `
259
+ <div class="lxp-table">
260
+ <div class="lxp-table__header">
261
+ <div class="lxp-table__title">
262
+ <h3 class="lxp-table__title-text">{{ title || defaultTitle }}</h3>
263
+ <span
264
+ *ngIf="totalItems > 0"
265
+ class="lxp-table__title-count"
266
+ >
267
+ ({{ totalItems }})
268
+ </span>
269
+ </div>
270
+
271
+ <div class="lxp-table__controls" *ngIf="showSearch">
272
+ <input
273
+ type="search"
274
+ class="lxp-table__search"
275
+ [placeholder]="searchPlaceholder || 'Search...'"
276
+ [(ngModel)]="searchTerm"
277
+ (ngModelChange)="onSearchChange($event)"
278
+ />
279
+ </div>
280
+ </div>
281
+
282
+ <div class="lxp-table__body-wrapper">
283
+ <table class="lxp-table__table">
284
+ <thead>
285
+ <tr>
286
+ <th
287
+ *ngIf="selectable"
288
+ class="lxp-table__cell lxp-table__cell--checkbox"
289
+ ></th>
290
+ <th
291
+ *ngFor="let column of columns"
292
+ class="lxp-table__cell lxp-table__cell--header"
293
+ [style.text-align]="column.align || 'left'"
294
+ >
295
+ {{ column.label }}
296
+ </th>
297
+ <th
298
+ *ngIf="actions?.length"
299
+ class="lxp-table__cell lxp-table__cell--header lxp-table__cell--actions"
300
+ >
301
+ Actions
302
+ </th>
303
+ </tr>
304
+ </thead>
305
+ <tbody>
306
+ <tr *ngIf="loading">
307
+ <td
308
+ class="lxp-table__cell lxp-table__cell--status"
309
+ [attr.colspan]="columnSpan"
310
+ >
311
+ {{ loadingMessage }}
312
+ </td>
313
+ </tr>
314
+
315
+ <tr *ngIf="!loading && pagedData.length === 0">
316
+ <td
317
+ class="lxp-table__cell lxp-table__cell--status"
318
+ [attr.colspan]="columnSpan"
319
+ >
320
+ {{ emptyMessage }}
321
+ </td>
322
+ </tr>
323
+
324
+ <tr
325
+ *ngFor="let row of pagedData; let rowIndex = index"
326
+ class="lxp-table__row"
327
+ (click)="handleRowClick(row, rowIndex)"
328
+ >
329
+ <td
330
+ *ngIf="selectable"
331
+ class="lxp-table__cell lxp-table__cell--checkbox"
332
+ >
333
+ <input
334
+ type="checkbox"
335
+ [checked]="isRowSelected(globalRowIndex(rowIndex))"
336
+ (click)="$event.stopPropagation()"
337
+ (change)="toggleRowSelection(globalRowIndex(rowIndex))"
338
+ />
339
+ </td>
340
+
341
+ <td
342
+ *ngFor="let column of columns"
343
+ class="lxp-table__cell"
344
+ [style.text-align]="column.align || 'left'"
345
+ >
346
+ <ng-container [ngTemplateOutlet]="cellTemplate"
347
+ [ngTemplateOutletContext]="{ column: column, row: row }">
348
+ </ng-container>
349
+ </td>
350
+
351
+ <td
352
+ *ngIf="actions?.length"
353
+ class="lxp-table__cell lxp-table__cell--actions"
354
+ >
355
+ <button
356
+ *ngFor="let action of actions"
357
+ type="button"
358
+ class="lxp-table__action"
359
+ [disabled]="isActionDisabled(action, row)"
360
+ (click)="runAction(action, row); $event.stopPropagation()"
361
+ >
362
+ {{ action.label }}
363
+ </button>
364
+ </td>
365
+ </tr>
366
+ </tbody>
367
+ </table>
368
+ </div>
369
+
370
+ <div
371
+ *ngIf="showPagination && totalPages > 1"
372
+ class="lxp-table__footer"
373
+ >
374
+ <div class="lxp-table__footer-info">
375
+ Page {{ currentPageInternal }} of {{ totalPages }}
376
+ </div>
377
+ <div class="lxp-table__footer-controls">
378
+ <label class="lxp-table__page-size">
379
+ <span>Rows per page</span>
380
+ <select
381
+ [ngModel]="pageSizeInternal"
382
+ (ngModelChange)="onPageSizeChangeInternal($event)"
383
+ >
384
+ <option *ngFor="let size of pageSizeOptionsInternal" [ngValue]="size">
385
+ {{ size }}
386
+ </option>
387
+ </select>
388
+ </label>
389
+
390
+ <button
391
+ type="button"
392
+ class="lxp-table__pager"
393
+ [disabled]="currentPageInternal === 1"
394
+ (click)="onPageChangeInternal(currentPageInternal - 1)"
395
+ >
396
+ Previous
397
+ </button>
398
+ <button
399
+ type="button"
400
+ class="lxp-table__pager"
401
+ [disabled]="currentPageInternal === totalPages"
402
+ (click)="onPageChangeInternal(currentPageInternal + 1)"
403
+ >
404
+ Next
405
+ </button>
406
+ </div>
407
+ </div>
408
+
409
+ <ng-template #cellTemplate let-column="column" let-row="row">
410
+ <ng-container *ngIf="column.render; else defaultCell">
411
+ {{ column.render(row[column.key], row) }}
412
+ </ng-container>
413
+ <ng-template #defaultCell>
414
+ <ng-container
415
+ *ngIf="isRichCell(row[column.key]); else plainCell"
416
+ >
417
+ <div class="lxp-table__cell-text">
418
+ <div class="lxp-table__cell-line1">
419
+ {{ row[column.key].line1 || row[column.key].text || row[column.key].name }}
420
+ </div>
421
+ <div
422
+ *ngIf="row[column.key].line2"
423
+ class="lxp-table__cell-line2"
424
+ >
425
+ {{ row[column.key].line2 }}
426
+ </div>
427
+ </div>
428
+ </ng-container>
429
+ <ng-template #plainCell>
430
+ {{ row[column.key] }}
431
+ </ng-template>
432
+ </ng-template>
433
+ </ng-template>
434
+ </div>
435
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
436
+ }
437
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TableComponent, decorators: [{
438
+ type: Component,
439
+ args: [{
440
+ selector: "lxp-table",
441
+ standalone: true,
442
+ imports: [CommonModule, FormsModule],
443
+ template: `
444
+ <div class="lxp-table">
445
+ <div class="lxp-table__header">
446
+ <div class="lxp-table__title">
447
+ <h3 class="lxp-table__title-text">{{ title || defaultTitle }}</h3>
448
+ <span
449
+ *ngIf="totalItems > 0"
450
+ class="lxp-table__title-count"
451
+ >
452
+ ({{ totalItems }})
453
+ </span>
454
+ </div>
455
+
456
+ <div class="lxp-table__controls" *ngIf="showSearch">
457
+ <input
458
+ type="search"
459
+ class="lxp-table__search"
460
+ [placeholder]="searchPlaceholder || 'Search...'"
461
+ [(ngModel)]="searchTerm"
462
+ (ngModelChange)="onSearchChange($event)"
463
+ />
464
+ </div>
465
+ </div>
466
+
467
+ <div class="lxp-table__body-wrapper">
468
+ <table class="lxp-table__table">
469
+ <thead>
470
+ <tr>
471
+ <th
472
+ *ngIf="selectable"
473
+ class="lxp-table__cell lxp-table__cell--checkbox"
474
+ ></th>
475
+ <th
476
+ *ngFor="let column of columns"
477
+ class="lxp-table__cell lxp-table__cell--header"
478
+ [style.text-align]="column.align || 'left'"
479
+ >
480
+ {{ column.label }}
481
+ </th>
482
+ <th
483
+ *ngIf="actions?.length"
484
+ class="lxp-table__cell lxp-table__cell--header lxp-table__cell--actions"
485
+ >
486
+ Actions
487
+ </th>
488
+ </tr>
489
+ </thead>
490
+ <tbody>
491
+ <tr *ngIf="loading">
492
+ <td
493
+ class="lxp-table__cell lxp-table__cell--status"
494
+ [attr.colspan]="columnSpan"
495
+ >
496
+ {{ loadingMessage }}
497
+ </td>
498
+ </tr>
499
+
500
+ <tr *ngIf="!loading && pagedData.length === 0">
501
+ <td
502
+ class="lxp-table__cell lxp-table__cell--status"
503
+ [attr.colspan]="columnSpan"
504
+ >
505
+ {{ emptyMessage }}
506
+ </td>
507
+ </tr>
508
+
509
+ <tr
510
+ *ngFor="let row of pagedData; let rowIndex = index"
511
+ class="lxp-table__row"
512
+ (click)="handleRowClick(row, rowIndex)"
513
+ >
514
+ <td
515
+ *ngIf="selectable"
516
+ class="lxp-table__cell lxp-table__cell--checkbox"
517
+ >
518
+ <input
519
+ type="checkbox"
520
+ [checked]="isRowSelected(globalRowIndex(rowIndex))"
521
+ (click)="$event.stopPropagation()"
522
+ (change)="toggleRowSelection(globalRowIndex(rowIndex))"
523
+ />
524
+ </td>
525
+
526
+ <td
527
+ *ngFor="let column of columns"
528
+ class="lxp-table__cell"
529
+ [style.text-align]="column.align || 'left'"
530
+ >
531
+ <ng-container [ngTemplateOutlet]="cellTemplate"
532
+ [ngTemplateOutletContext]="{ column: column, row: row }">
533
+ </ng-container>
534
+ </td>
535
+
536
+ <td
537
+ *ngIf="actions?.length"
538
+ class="lxp-table__cell lxp-table__cell--actions"
539
+ >
540
+ <button
541
+ *ngFor="let action of actions"
542
+ type="button"
543
+ class="lxp-table__action"
544
+ [disabled]="isActionDisabled(action, row)"
545
+ (click)="runAction(action, row); $event.stopPropagation()"
546
+ >
547
+ {{ action.label }}
548
+ </button>
549
+ </td>
550
+ </tr>
551
+ </tbody>
552
+ </table>
553
+ </div>
554
+
555
+ <div
556
+ *ngIf="showPagination && totalPages > 1"
557
+ class="lxp-table__footer"
558
+ >
559
+ <div class="lxp-table__footer-info">
560
+ Page {{ currentPageInternal }} of {{ totalPages }}
561
+ </div>
562
+ <div class="lxp-table__footer-controls">
563
+ <label class="lxp-table__page-size">
564
+ <span>Rows per page</span>
565
+ <select
566
+ [ngModel]="pageSizeInternal"
567
+ (ngModelChange)="onPageSizeChangeInternal($event)"
568
+ >
569
+ <option *ngFor="let size of pageSizeOptionsInternal" [ngValue]="size">
570
+ {{ size }}
571
+ </option>
572
+ </select>
573
+ </label>
574
+
575
+ <button
576
+ type="button"
577
+ class="lxp-table__pager"
578
+ [disabled]="currentPageInternal === 1"
579
+ (click)="onPageChangeInternal(currentPageInternal - 1)"
580
+ >
581
+ Previous
582
+ </button>
583
+ <button
584
+ type="button"
585
+ class="lxp-table__pager"
586
+ [disabled]="currentPageInternal === totalPages"
587
+ (click)="onPageChangeInternal(currentPageInternal + 1)"
588
+ >
589
+ Next
590
+ </button>
591
+ </div>
592
+ </div>
593
+
594
+ <ng-template #cellTemplate let-column="column" let-row="row">
595
+ <ng-container *ngIf="column.render; else defaultCell">
596
+ {{ column.render(row[column.key], row) }}
597
+ </ng-container>
598
+ <ng-template #defaultCell>
599
+ <ng-container
600
+ *ngIf="isRichCell(row[column.key]); else plainCell"
601
+ >
602
+ <div class="lxp-table__cell-text">
603
+ <div class="lxp-table__cell-line1">
604
+ {{ row[column.key].line1 || row[column.key].text || row[column.key].name }}
605
+ </div>
606
+ <div
607
+ *ngIf="row[column.key].line2"
608
+ class="lxp-table__cell-line2"
609
+ >
610
+ {{ row[column.key].line2 }}
611
+ </div>
612
+ </div>
613
+ </ng-container>
614
+ <ng-template #plainCell>
615
+ {{ row[column.key] }}
616
+ </ng-template>
617
+ </ng-template>
618
+ </ng-template>
619
+ </div>
620
+ `,
621
+ }]
622
+ }], propDecorators: { columns: [{
623
+ type: Input
624
+ }], data: [{
625
+ type: Input
626
+ }], actions: [{
627
+ type: Input
628
+ }], selectable: [{
629
+ type: Input
630
+ }], showPagination: [{
631
+ type: Input
632
+ }], showSearch: [{
633
+ type: Input
634
+ }], loading: [{
635
+ type: Input
636
+ }], theme: [{
637
+ type: Input
638
+ }], title: [{
639
+ type: Input
640
+ }], titleLink: [{
641
+ type: Input
642
+ }], serverSide: [{
643
+ type: Input
644
+ }], totalCount: [{
645
+ type: Input
646
+ }], currentPage: [{
647
+ type: Input
648
+ }], pageSize: [{
649
+ type: Input
650
+ }], pageSizeOptions: [{
651
+ type: Input
652
+ }], emptyState: [{
653
+ type: Input
654
+ }], enableRowClick: [{
655
+ type: Input
656
+ }], searchPlaceholder: [{
657
+ type: Input
658
+ }], onSelectionChange: [{
659
+ type: Output
660
+ }], onPageChange: [{
661
+ type: Output
662
+ }], onPageSizeChange: [{
663
+ type: Output
664
+ }], onSearch: [{
665
+ type: Output
666
+ }], onRowClick: [{
667
+ type: Output
668
+ }], fontFamily: [{
669
+ type: HostBinding,
670
+ args: ["style.fontFamily"]
671
+ }] } });
672
+
673
+ class ThemeService {
674
+ themeSubject = new BehaviorSubject(defaultTheme);
675
+ theme$ = this.themeSubject.asObservable();
676
+ get theme() {
677
+ return this.themeSubject.value;
678
+ }
679
+ setTheme(theme) {
680
+ this.themeSubject.next(theme);
681
+ }
682
+ toggleTheme() {
683
+ this.themeSubject.next(this.theme === "tera" ? "cynk" : "tera");
684
+ }
685
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ThemeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
686
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ThemeService, providedIn: "root" });
687
+ }
688
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ThemeService, decorators: [{
689
+ type: Injectable,
690
+ args: [{
691
+ providedIn: "root",
692
+ }]
693
+ }] });
694
+
695
+ class ThemeSwitcherComponent {
696
+ themeService;
697
+ className;
698
+ showLabels = true;
699
+ constructor(themeService) {
700
+ this.themeService = themeService;
701
+ }
702
+ get label() {
703
+ return this.themeService.theme === "tera" ? "Tera theme" : "Cynk theme";
704
+ }
705
+ get shortLabel() {
706
+ return this.themeService.theme === "tera" ? "T" : "C";
707
+ }
708
+ get buttonTitle() {
709
+ const next = this.themeService.theme === "tera" ? "Cynk" : "Tera";
710
+ return `Switch to ${next} theme`;
711
+ }
712
+ toggleTheme() {
713
+ this.themeService.toggleTheme();
714
+ }
715
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ThemeSwitcherComponent, deps: [{ token: ThemeService }], target: i0.ɵɵFactoryTarget.Component });
716
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.0", type: ThemeSwitcherComponent, isStandalone: true, selector: "lxp-theme-switcher", inputs: { className: "className", showLabels: "showLabels" }, ngImport: i0, template: `
717
+ <button
718
+ type="button"
719
+ class="lxp-theme-switcher"
720
+ [ngClass]="className"
721
+ (click)="toggleTheme()"
722
+ [title]="buttonTitle"
723
+ >
724
+ <ng-container *ngIf="showLabels; else iconOnly">
725
+ {{ label }}
726
+ </ng-container>
727
+ <ng-template #iconOnly>
728
+ {{ shortLabel }}
729
+ </ng-template>
730
+ </button>
731
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
732
+ }
733
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ThemeSwitcherComponent, decorators: [{
734
+ type: Component,
735
+ args: [{
736
+ selector: "lxp-theme-switcher",
737
+ standalone: true,
738
+ imports: [CommonModule],
739
+ template: `
740
+ <button
741
+ type="button"
742
+ class="lxp-theme-switcher"
743
+ [ngClass]="className"
744
+ (click)="toggleTheme()"
745
+ [title]="buttonTitle"
746
+ >
747
+ <ng-container *ngIf="showLabels; else iconOnly">
748
+ {{ label }}
749
+ </ng-container>
750
+ <ng-template #iconOnly>
751
+ {{ shortLabel }}
752
+ </ng-template>
753
+ </button>
754
+ `,
755
+ }]
756
+ }], ctorParameters: () => [{ type: ThemeService }], propDecorators: { className: [{
757
+ type: Input
758
+ }], showLabels: [{
759
+ type: Input
760
+ }] } });
761
+
92
762
  /**
93
763
  * Generated bundle index. Do not edit.
94
764
  */
95
765
 
96
- export { ButtonComponent };
766
+ export { ButtonComponent, TableComponent, ThemeService, ThemeSwitcherComponent };
97
767
  //# sourceMappingURL=lamenna-lxp-angular.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"lamenna-lxp-angular.mjs","sources":["../../src/components/button/button.component.ts","../../src/lamenna-lxp-angular.ts"],"sourcesContent":["import { CommonModule } from \"@angular/common\";\nimport {\n Component,\n Input,\n Output,\n EventEmitter,\n HostBinding,\n} from \"@angular/core\";\nimport {\n AngularButtonProps,\n ButtonVariant,\n ButtonSize,\n buttonConfig,\n} from \"@lamenna/lxp-shared-components\";\n\n@Component({\n selector: \"lxp-button\",\n template: `\n <button\n [attr.id]=\"id\"\n [attr.data-testid]=\"testID\"\n [attr.aria-label]=\"ariaLabel\"\n [disabled]=\"disabled\"\n (click)=\"onClick.emit($event)\"\n [ngClass]=\"buttonClasses\"\n >\n {{ content }}\n </button>\n `,\n standalone: true,\n imports: [CommonModule],\n})\nexport class ButtonComponent implements AngularButtonProps {\n @Input() content?: string;\n @Input() variant: ButtonVariant = \"primary\";\n @Input() size: ButtonSize = \"md\";\n @Input() disabled: boolean = false;\n @Input() className?: string;\n @Input() id?: string;\n @Input() ariaLabel?: string;\n @Input() testID?: string;\n @Input() label?: string;\n\n @Output() onClick = new EventEmitter<MouseEvent>();\n\n @HostBinding(\"style\") get hostStyles() {\n const variantConfig = buttonConfig.variants[this.variant];\n const sizeConfig = buttonConfig.sizes[this.size];\n return {\n ...buttonConfig.common,\n ...variantConfig,\n ...sizeConfig,\n opacity: this.disabled ? \"0.6\" : \"1\",\n pointerEvents: this.disabled ? \"none\" : \"auto\",\n };\n }\n\n get buttonClasses() {\n return {\n [this.className || \"\"]: !!this.className,\n };\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;MAgCa,eAAe,CAAA;AACjB,IAAA,OAAO;IACP,OAAO,GAAkB,SAAS;IAClC,IAAI,GAAe,IAAI;IACvB,QAAQ,GAAY,KAAK;AACzB,IAAA,SAAS;AACT,IAAA,EAAE;AACF,IAAA,SAAS;AACT,IAAA,MAAM;AACN,IAAA,KAAK;AAEJ,IAAA,OAAO,GAAG,IAAI,YAAY,EAAc;AAElD,IAAA,IAA0B,UAAU,GAAA;QAClC,MAAM,aAAa,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;QACzD,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAChD,OAAO;YACL,GAAG,YAAY,CAAC,MAAM;AACtB,YAAA,GAAG,aAAa;AAChB,YAAA,GAAG,UAAU;YACb,OAAO,EAAE,IAAI,CAAC,QAAQ,GAAG,KAAK,GAAG,GAAG;YACpC,aAAa,EAAE,IAAI,CAAC,QAAQ,GAAG,MAAM,GAAG,MAAM;SAC/C;IACH;AAEA,IAAA,IAAI,aAAa,GAAA;QACf,OAAO;YACL,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS;SACzC;IACH;uGA7BW,eAAe,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAf,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAe,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,SAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,MAAA,EAAA,QAAA,EAAA,UAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,EAAA,IAAA,EAAA,SAAA,EAAA,WAAA,EAAA,MAAA,EAAA,QAAA,EAAA,KAAA,EAAA,OAAA,EAAA,EAAA,OAAA,EAAA,EAAA,OAAA,EAAA,SAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,iBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAfhB;;;;;;;;;;;AAWT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAES,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;2FAEX,eAAe,EAAA,UAAA,EAAA,CAAA;kBAjB3B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,YAAY;AACtB,oBAAA,QAAQ,EAAE;;;;;;;;;;;AAWT,EAAA,CAAA;AACD,oBAAA,UAAU,EAAE,IAAI;oBAChB,OAAO,EAAE,CAAC,YAAY,CAAC;AACxB,iBAAA;;sBAEE;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBACA;;sBAEA;;sBAEA,WAAW;uBAAC,OAAO;;;AC7CtB;;AAEG;;;;"}
1
+ {"version":3,"file":"lamenna-lxp-angular.mjs","sources":["../../src/components/button/button.component.ts","../../src/components/table/table.component.ts","../../src/theme/theme.service.ts","../../src/components/theme-switcher/theme-switcher.component.ts","../../src/lamenna-lxp-angular.ts"],"sourcesContent":["import { CommonModule } from \"@angular/common\";\nimport {\n Component,\n Input,\n Output,\n EventEmitter,\n HostBinding,\n} from \"@angular/core\";\nimport {\n AngularButtonProps,\n ButtonVariant,\n ButtonSize,\n buttonConfig,\n} from \"@lamenna/lxp-shared-components\";\n\n@Component({\n selector: \"lxp-button\",\n template: `\n <button\n [attr.id]=\"id\"\n [attr.data-testid]=\"testID\"\n [attr.aria-label]=\"ariaLabel\"\n [disabled]=\"disabled\"\n (click)=\"onClick.emit($event)\"\n [ngClass]=\"buttonClasses\"\n >\n {{ content }}\n </button>\n `,\n standalone: true,\n imports: [CommonModule],\n})\nexport class ButtonComponent implements AngularButtonProps {\n @Input() content?: string;\n @Input() variant: ButtonVariant = \"primary\";\n @Input() size: ButtonSize = \"md\";\n @Input() disabled: boolean = false;\n @Input() className?: string;\n @Input() id?: string;\n @Input() ariaLabel?: string;\n @Input() testID?: string;\n @Input()\n get label(): string | undefined {\n return this.content;\n }\n set label(value: string | undefined) {\n this.content = value;\n }\n\n @Output() onClick = new EventEmitter<MouseEvent>();\n\n @HostBinding(\"style\") get hostStyles() {\n const variantConfig = buttonConfig.variants[this.variant];\n const sizeConfig = buttonConfig.sizes[this.size];\n return {\n ...buttonConfig.common,\n ...variantConfig,\n ...sizeConfig,\n opacity: this.disabled ? \"0.6\" : \"1\",\n pointerEvents: this.disabled ? \"none\" : \"auto\",\n };\n }\n\n get buttonClasses() {\n return {\n [this.className || \"\"]: !!this.className,\n };\n }\n}\n","import { CommonModule } from \"@angular/common\";\nimport { FormsModule } from \"@angular/forms\";\nimport {\n Component,\n EventEmitter,\n HostBinding,\n Input,\n Output,\n} from \"@angular/core\";\nimport {\n BaseTableProps,\n TableColumn,\n TableAction,\n TablePageChange,\n TableSearchData,\n TableThemeKey,\n tableConfig,\n tableThemeConfig,\n} from \"@lamenna/lxp-shared-components\";\n\n@Component({\n selector: \"lxp-table\",\n standalone: true,\n imports: [CommonModule, FormsModule],\n template: `\n <div class=\"lxp-table\">\n <div class=\"lxp-table__header\">\n <div class=\"lxp-table__title\">\n <h3 class=\"lxp-table__title-text\">{{ title || defaultTitle }}</h3>\n <span\n *ngIf=\"totalItems > 0\"\n class=\"lxp-table__title-count\"\n >\n ({{ totalItems }})\n </span>\n </div>\n\n <div class=\"lxp-table__controls\" *ngIf=\"showSearch\">\n <input\n type=\"search\"\n class=\"lxp-table__search\"\n [placeholder]=\"searchPlaceholder || 'Search...'\"\n [(ngModel)]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange($event)\"\n />\n </div>\n </div>\n\n <div class=\"lxp-table__body-wrapper\">\n <table class=\"lxp-table__table\">\n <thead>\n <tr>\n <th\n *ngIf=\"selectable\"\n class=\"lxp-table__cell lxp-table__cell--checkbox\"\n ></th>\n <th\n *ngFor=\"let column of columns\"\n class=\"lxp-table__cell lxp-table__cell--header\"\n [style.text-align]=\"column.align || 'left'\"\n >\n {{ column.label }}\n </th>\n <th\n *ngIf=\"actions?.length\"\n class=\"lxp-table__cell lxp-table__cell--header lxp-table__cell--actions\"\n >\n Actions\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngIf=\"loading\">\n <td\n class=\"lxp-table__cell lxp-table__cell--status\"\n [attr.colspan]=\"columnSpan\"\n >\n {{ loadingMessage }}\n </td>\n </tr>\n\n <tr *ngIf=\"!loading && pagedData.length === 0\">\n <td\n class=\"lxp-table__cell lxp-table__cell--status\"\n [attr.colspan]=\"columnSpan\"\n >\n {{ emptyMessage }}\n </td>\n </tr>\n\n <tr\n *ngFor=\"let row of pagedData; let rowIndex = index\"\n class=\"lxp-table__row\"\n (click)=\"handleRowClick(row, rowIndex)\"\n >\n <td\n *ngIf=\"selectable\"\n class=\"lxp-table__cell lxp-table__cell--checkbox\"\n >\n <input\n type=\"checkbox\"\n [checked]=\"isRowSelected(globalRowIndex(rowIndex))\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleRowSelection(globalRowIndex(rowIndex))\"\n />\n </td>\n\n <td\n *ngFor=\"let column of columns\"\n class=\"lxp-table__cell\"\n [style.text-align]=\"column.align || 'left'\"\n >\n <ng-container [ngTemplateOutlet]=\"cellTemplate\"\n [ngTemplateOutletContext]=\"{ column: column, row: row }\">\n </ng-container>\n </td>\n\n <td\n *ngIf=\"actions?.length\"\n class=\"lxp-table__cell lxp-table__cell--actions\"\n >\n <button\n *ngFor=\"let action of actions\"\n type=\"button\"\n class=\"lxp-table__action\"\n [disabled]=\"isActionDisabled(action, row)\"\n (click)=\"runAction(action, row); $event.stopPropagation()\"\n >\n {{ action.label }}\n </button>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <div\n *ngIf=\"showPagination && totalPages > 1\"\n class=\"lxp-table__footer\"\n >\n <div class=\"lxp-table__footer-info\">\n Page {{ currentPageInternal }} of {{ totalPages }}\n </div>\n <div class=\"lxp-table__footer-controls\">\n <label class=\"lxp-table__page-size\">\n <span>Rows per page</span>\n <select\n [ngModel]=\"pageSizeInternal\"\n (ngModelChange)=\"onPageSizeChangeInternal($event)\"\n >\n <option *ngFor=\"let size of pageSizeOptionsInternal\" [ngValue]=\"size\">\n {{ size }}\n </option>\n </select>\n </label>\n\n <button\n type=\"button\"\n class=\"lxp-table__pager\"\n [disabled]=\"currentPageInternal === 1\"\n (click)=\"onPageChangeInternal(currentPageInternal - 1)\"\n >\n Previous\n </button>\n <button\n type=\"button\"\n class=\"lxp-table__pager\"\n [disabled]=\"currentPageInternal === totalPages\"\n (click)=\"onPageChangeInternal(currentPageInternal + 1)\"\n >\n Next\n </button>\n </div>\n </div>\n\n <ng-template #cellTemplate let-column=\"column\" let-row=\"row\">\n <ng-container *ngIf=\"column.render; else defaultCell\">\n {{ column.render(row[column.key], row) }}\n </ng-container>\n <ng-template #defaultCell>\n <ng-container\n *ngIf=\"isRichCell(row[column.key]); else plainCell\"\n >\n <div class=\"lxp-table__cell-text\">\n <div class=\"lxp-table__cell-line1\">\n {{ row[column.key].line1 || row[column.key].text || row[column.key].name }}\n </div>\n <div\n *ngIf=\"row[column.key].line2\"\n class=\"lxp-table__cell-line2\"\n >\n {{ row[column.key].line2 }}\n </div>\n </div>\n </ng-container>\n <ng-template #plainCell>\n {{ row[column.key] }}\n </ng-template>\n </ng-template>\n </ng-template>\n </div>\n `,\n})\nexport class TableComponent {\n @Input() columns: TableColumn[] = [];\n @Input() data: any[] = [];\n @Input() actions: TableAction[] = [];\n @Input() selectable = false;\n @Input() showPagination = true;\n @Input() showSearch = true;\n @Input() loading = false;\n @Input() theme: TableThemeKey = \"tera\";\n @Input() title?: string;\n @Input() titleLink?: string;\n @Input() serverSide = false;\n @Input() totalCount?: number;\n @Input() currentPage?: number;\n @Input() pageSize?: number;\n @Input() pageSizeOptions?: number[];\n @Input() emptyState?: BaseTableProps[\"emptyState\"];\n @Input() enableRowClick = false;\n @Input() searchPlaceholder?: string;\n\n @Output() onSelectionChange = new EventEmitter<number[]>();\n @Output() onPageChange = new EventEmitter<TablePageChange>();\n @Output() onPageSizeChange = new EventEmitter<TablePageChange>();\n @Output() onSearch = new EventEmitter<TableSearchData>();\n @Output() onRowClick = new EventEmitter<{ row: any; index: number }>();\n\n @HostBinding(\"style.fontFamily\")\n get fontFamily(): string {\n return tableThemeConfig[this.theme].fontFamily;\n }\n\n defaultTitle = tableConfig.defaultTitle;\n loadingMessage = tableConfig.loadingMessage;\n\n searchTerm = \"\";\n selectedRows: number[] = [];\n\n get columnSpan(): number {\n return (\n this.columns.length +\n (this.selectable ? 1 : 0) +\n (this.actions?.length ? 1 : 0)\n );\n }\n\n get totalItems(): number {\n if (this.serverSide) {\n return this.totalCount ?? this.data.length;\n }\n return this.filteredData.length;\n }\n\n get currentPageInternal(): number {\n return this.currentPage ?? this._currentPage;\n }\n\n get pageSizeInternal(): number {\n return this.pageSize ?? this._pageSize;\n }\n\n get pageSizeOptionsInternal(): ReadonlyArray<number> {\n return this.pageSizeOptions ?? tableConfig.defaultPageSizeOptions;\n }\n\n private _currentPage: number = 1;\n private _pageSize: number = tableConfig.defaultPageSize;\n\n get filteredData(): any[] {\n if (!this.showSearch || !this.searchTerm.trim()) {\n return this.data;\n }\n\n const term = this.searchTerm.toLowerCase();\n return this.data.filter((row) =>\n Object.values(row).some((value) =>\n String(\n typeof value === \"object\" && value !== null\n ? (value as any).line1 ?? (value as any).line2 ?? \"\"\n : value ?? \"\",\n )\n .toLowerCase()\n .includes(term),\n ),\n );\n }\n\n get pagedData(): any[] {\n if (!this.showPagination || this.serverSide) {\n return this.filteredData;\n }\n const start = (this.currentPageInternal - 1) * this.pageSizeInternal;\n return this.filteredData.slice(start, start + this.pageSizeInternal);\n }\n\n get totalPages(): number {\n if (!this.showPagination) {\n return 1;\n }\n return Math.max(1, Math.ceil(this.totalItems / this.pageSizeInternal));\n }\n\n isRichCell(value: any): boolean {\n return (\n value &&\n typeof value === \"object\" &&\n (\"line1\" in value || \"line2\" in value || \"text\" in value || \"name\" in value)\n );\n }\n\n isRowSelected(index: number): boolean {\n return this.selectedRows.includes(index);\n }\n\n globalRowIndex(localIndex: number): number {\n if (this.serverSide) {\n return localIndex;\n }\n return (this.currentPageInternal - 1) * this.pageSizeInternal + localIndex;\n }\n\n toggleRowSelection(index: number): void {\n const exists = this.selectedRows.includes(index);\n this.selectedRows = exists\n ? this.selectedRows.filter((i) => i !== index)\n : [...this.selectedRows, index];\n this.onSelectionChange.emit(this.selectedRows);\n }\n\n get emptyMessage(): string {\n const custom = this.emptyState?.message;\n const showDefault = this.emptyState?.showDefault ?? true;\n if (custom) return custom;\n return showDefault ? tableConfig.emptyMessage : \"\";\n }\n\n onSearchChange(term: any): void {\n const value =\n typeof term === \"string\"\n ? term\n : (term?.target as HTMLInputElement | null)?.value ?? \"\";\n this.searchTerm = value;\n this.onSearch.emit({\n page: this.currentPageInternal,\n pageSize: this.pageSizeInternal,\n searchTerm: value,\n filters: {},\n });\n }\n\n onPageChangeInternal(nextPage: number): void {\n if (nextPage < 1 || nextPage > this.totalPages) return;\n if (this.currentPage == null) {\n this._currentPage = nextPage;\n }\n this.onPageChange.emit({\n page: nextPage,\n pageSize: this.pageSizeInternal,\n searchTerm: this.searchTerm,\n filters: {},\n });\n }\n\n onPageSizeChangeInternal(nextSize: any): void {\n const size =\n typeof nextSize === \"number\" ? nextSize : Number(nextSize ?? 0);\n if (this.pageSize == null) {\n this._pageSize = size;\n this._currentPage = 1;\n }\n this.onPageSizeChange.emit({\n page: 1,\n pageSize: size,\n searchTerm: this.searchTerm,\n filters: {},\n });\n }\n\n handleRowClick(row: any, localIndex: number): void {\n if (!this.enableRowClick) return;\n const globalIndex = this.globalRowIndex(localIndex);\n this.onRowClick.emit({ row, index: globalIndex });\n }\n\n isActionDisabled(action: TableAction, row: any): boolean {\n return action.disabled ? action.disabled(row) : false;\n }\n\n runAction(action: TableAction, row: any): void {\n if (this.isActionDisabled(action, row)) return;\n action.action(row);\n }\n}\n\n\n","import { Injectable } from \"@angular/core\";\nimport { BehaviorSubject } from \"rxjs\";\nimport {\n defaultTheme,\n type CompanyTheme,\n} from \"@lamenna/lxp-shared-components\";\n\n@Injectable({\n providedIn: \"root\",\n})\nexport class ThemeService {\n private readonly themeSubject = new BehaviorSubject<CompanyTheme>(\n defaultTheme,\n );\n\n readonly theme$ = this.themeSubject.asObservable();\n\n get theme(): CompanyTheme {\n return this.themeSubject.value;\n }\n\n setTheme(theme: CompanyTheme): void {\n this.themeSubject.next(theme);\n }\n\n toggleTheme(): void {\n this.themeSubject.next(this.theme === \"tera\" ? \"cynk\" : \"tera\");\n }\n}\n\n\n\n\n\n","import { CommonModule } from \"@angular/common\";\nimport { Component, Input } from \"@angular/core\";\nimport { ThemeService } from \"../../theme/theme.service\";\n\n@Component({\n selector: \"lxp-theme-switcher\",\n standalone: true,\n imports: [CommonModule],\n template: `\n <button\n type=\"button\"\n class=\"lxp-theme-switcher\"\n [ngClass]=\"className\"\n (click)=\"toggleTheme()\"\n [title]=\"buttonTitle\"\n >\n <ng-container *ngIf=\"showLabels; else iconOnly\">\n {{ label }}\n </ng-container>\n <ng-template #iconOnly>\n {{ shortLabel }}\n </ng-template>\n </button>\n `,\n})\nexport class ThemeSwitcherComponent {\n @Input() className?: string;\n @Input() showLabels = true;\n\n constructor(private readonly themeService: ThemeService) {}\n\n get label(): string {\n return this.themeService.theme === \"tera\" ? \"Tera theme\" : \"Cynk theme\";\n }\n\n get shortLabel(): string {\n return this.themeService.theme === \"tera\" ? \"T\" : \"C\";\n }\n\n get buttonTitle(): string {\n const next = this.themeService.theme === \"tera\" ? \"Cynk\" : \"Tera\";\n return `Switch to ${next} theme`;\n }\n\n toggleTheme(): void {\n this.themeService.toggleTheme();\n }\n}\n\n\n\n\n\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1.ThemeService","i2"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { EventEmitter } from '@angular/core';
3
- import { AngularButtonProps, ButtonVariant, ButtonSize } from '@lamenna/lxp-shared-components';
3
+ import { AngularButtonProps, ButtonVariant, ButtonSize, TableColumn, TableAction, TableThemeKey, BaseTableProps, TablePageChange, TableSearchData, CompanyTheme } from '@lamenna/lxp-shared-components';
4
+ import * as rxjs from 'rxjs';
4
5
 
5
6
  declare class ButtonComponent implements AngularButtonProps {
6
7
  content?: string;
@@ -11,7 +12,8 @@ declare class ButtonComponent implements AngularButtonProps {
11
12
  id?: string;
12
13
  ariaLabel?: string;
13
14
  testID?: string;
14
- label?: string;
15
+ get label(): string | undefined;
16
+ set label(value: string | undefined);
15
17
  onClick: EventEmitter<MouseEvent>;
16
18
  get hostStyles(): {
17
19
  opacity: string;
@@ -111,4 +113,84 @@ declare class ButtonComponent implements AngularButtonProps {
111
113
  static ɵcmp: i0.ɵɵComponentDeclaration<ButtonComponent, "lxp-button", never, { "content": { "alias": "content"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "size": { "alias": "size"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "className": { "alias": "className"; "required": false; }; "id": { "alias": "id"; "required": false; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; }; "testID": { "alias": "testID"; "required": false; }; "label": { "alias": "label"; "required": false; }; }, { "onClick": "onClick"; }, never, never, true, never>;
112
114
  }
113
115
 
114
- export { ButtonComponent };
116
+ declare class TableComponent {
117
+ columns: TableColumn[];
118
+ data: any[];
119
+ actions: TableAction[];
120
+ selectable: boolean;
121
+ showPagination: boolean;
122
+ showSearch: boolean;
123
+ loading: boolean;
124
+ theme: TableThemeKey;
125
+ title?: string;
126
+ titleLink?: string;
127
+ serverSide: boolean;
128
+ totalCount?: number;
129
+ currentPage?: number;
130
+ pageSize?: number;
131
+ pageSizeOptions?: number[];
132
+ emptyState?: BaseTableProps["emptyState"];
133
+ enableRowClick: boolean;
134
+ searchPlaceholder?: string;
135
+ onSelectionChange: EventEmitter<number[]>;
136
+ onPageChange: EventEmitter<TablePageChange>;
137
+ onPageSizeChange: EventEmitter<TablePageChange>;
138
+ onSearch: EventEmitter<TableSearchData>;
139
+ onRowClick: EventEmitter<{
140
+ row: any;
141
+ index: number;
142
+ }>;
143
+ get fontFamily(): string;
144
+ defaultTitle: "Data Table";
145
+ loadingMessage: "Loading...";
146
+ searchTerm: string;
147
+ selectedRows: number[];
148
+ get columnSpan(): number;
149
+ get totalItems(): number;
150
+ get currentPageInternal(): number;
151
+ get pageSizeInternal(): number;
152
+ get pageSizeOptionsInternal(): ReadonlyArray<number>;
153
+ private _currentPage;
154
+ private _pageSize;
155
+ get filteredData(): any[];
156
+ get pagedData(): any[];
157
+ get totalPages(): number;
158
+ isRichCell(value: any): boolean;
159
+ isRowSelected(index: number): boolean;
160
+ globalRowIndex(localIndex: number): number;
161
+ toggleRowSelection(index: number): void;
162
+ get emptyMessage(): string;
163
+ onSearchChange(term: any): void;
164
+ onPageChangeInternal(nextPage: number): void;
165
+ onPageSizeChangeInternal(nextSize: any): void;
166
+ handleRowClick(row: any, localIndex: number): void;
167
+ isActionDisabled(action: TableAction, row: any): boolean;
168
+ runAction(action: TableAction, row: any): void;
169
+ static ɵfac: i0.ɵɵFactoryDeclaration<TableComponent, never>;
170
+ static ɵcmp: i0.ɵɵComponentDeclaration<TableComponent, "lxp-table", never, { "columns": { "alias": "columns"; "required": false; }; "data": { "alias": "data"; "required": false; }; "actions": { "alias": "actions"; "required": false; }; "selectable": { "alias": "selectable"; "required": false; }; "showPagination": { "alias": "showPagination"; "required": false; }; "showSearch": { "alias": "showSearch"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "theme": { "alias": "theme"; "required": false; }; "title": { "alias": "title"; "required": false; }; "titleLink": { "alias": "titleLink"; "required": false; }; "serverSide": { "alias": "serverSide"; "required": false; }; "totalCount": { "alias": "totalCount"; "required": false; }; "currentPage": { "alias": "currentPage"; "required": false; }; "pageSize": { "alias": "pageSize"; "required": false; }; "pageSizeOptions": { "alias": "pageSizeOptions"; "required": false; }; "emptyState": { "alias": "emptyState"; "required": false; }; "enableRowClick": { "alias": "enableRowClick"; "required": false; }; "searchPlaceholder": { "alias": "searchPlaceholder"; "required": false; }; }, { "onSelectionChange": "onSelectionChange"; "onPageChange": "onPageChange"; "onPageSizeChange": "onPageSizeChange"; "onSearch": "onSearch"; "onRowClick": "onRowClick"; }, never, never, true, never>;
171
+ }
172
+
173
+ declare class ThemeService {
174
+ private readonly themeSubject;
175
+ readonly theme$: rxjs.Observable<CompanyTheme>;
176
+ get theme(): CompanyTheme;
177
+ setTheme(theme: CompanyTheme): void;
178
+ toggleTheme(): void;
179
+ static ɵfac: i0.ɵɵFactoryDeclaration<ThemeService, never>;
180
+ static ɵprov: i0.ɵɵInjectableDeclaration<ThemeService>;
181
+ }
182
+
183
+ declare class ThemeSwitcherComponent {
184
+ private readonly themeService;
185
+ className?: string;
186
+ showLabels: boolean;
187
+ constructor(themeService: ThemeService);
188
+ get label(): string;
189
+ get shortLabel(): string;
190
+ get buttonTitle(): string;
191
+ toggleTheme(): void;
192
+ static ɵfac: i0.ɵɵFactoryDeclaration<ThemeSwitcherComponent, never>;
193
+ static ɵcmp: i0.ɵɵComponentDeclaration<ThemeSwitcherComponent, "lxp-theme-switcher", never, { "className": { "alias": "className"; "required": false; }; "showLabels": { "alias": "showLabels"; "required": false; }; }, {}, never, never, true, never>;
194
+ }
195
+
196
+ export { ButtonComponent, TableComponent, ThemeService, ThemeSwitcherComponent };
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@lamenna/lxp-angular",
3
- "version": "0.0.6",
3
+ "version": "0.1.0",
4
4
  "description": "Angular components for LXP",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
5
+ "main": "dist/fesm2022/lamenna-lxp-angular.mjs",
6
+ "types": "dist/types/lamenna-lxp-angular.d.ts",
7
7
  "files": [
8
8
  "dist"
9
9
  ],
@@ -12,18 +12,32 @@
12
12
  },
13
13
  "peerDependencies": {
14
14
  "@angular/common": "^21.0.0",
15
- "@angular/core": "^21.0.0"
15
+ "@angular/core": "^21.0.0",
16
+ "@angular/forms": "^21.0.0",
17
+ "rxjs": "^7.8.0"
16
18
  },
17
19
  "dependencies": {
18
20
  "tslib": "^2.8.1",
19
- "@lamenna/lxp-shared-components": "0.0.2",
20
- "@lamenna/lxp-tokens": "0.0.2"
21
+ "@lamenna/lxp-shared-components": "0.1.0",
22
+ "@lamenna/lxp-tokens": "0.1.0"
21
23
  },
22
24
  "devDependencies": {
23
25
  "@angular/compiler-cli": "^21.0.6",
24
26
  "ng-packagr": "^21.0.1",
25
- "typescript": "^5.3.3"
27
+ "typescript": "^5.9.3"
26
28
  },
29
+ "module": "dist/fesm2022/lamenna-lxp-angular.mjs",
30
+ "typings": "dist/types/lamenna-lxp-angular.d.ts",
31
+ "exports": {
32
+ "./package.json": {
33
+ "default": "./dist/package.json"
34
+ },
35
+ ".": {
36
+ "types": "./dist/types/lamenna-lxp-angular.d.ts",
37
+ "default": "./dist/fesm2022/lamenna-lxp-angular.mjs"
38
+ }
39
+ },
40
+ "sideEffects": false,
27
41
  "scripts": {
28
42
  "build": "ng-packagr -p ng-package.json",
29
43
  "dev": "ng-packagr -p ng-package.json -w",