@tony-ui-library/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +188 -0
- package/fesm2022/tony-ui-library-core.mjs +8756 -0
- package/fesm2022/tony-ui-library-core.mjs.map +1 -0
- package/package.json +55 -0
- package/schematics/collection.json +16 -0
- package/schematics/ng-add/index.d.ts +5 -0
- package/schematics/ng-add/index.js +53 -0
- package/schematics/ng-add/schema.json +19 -0
- package/schematics/ng-generate/component/index.d.ts +9 -0
- package/schematics/ng-generate/component/index.js +439 -0
- package/schematics/ng-generate/component/schema.json +32 -0
- package/src/lib/accordion/accordion.directives.spec.ts +173 -0
- package/src/lib/accordion/accordion.directives.ts +143 -0
- package/src/lib/accordion/index.ts +8 -0
- package/src/lib/alert/alert.directives.spec.ts +154 -0
- package/src/lib/alert/alert.directives.ts +67 -0
- package/src/lib/alert/alert.variants.ts +25 -0
- package/src/lib/alert/index.ts +6 -0
- package/src/lib/avatar/avatar.component.spec.ts +75 -0
- package/src/lib/avatar/avatar.component.ts +43 -0
- package/src/lib/avatar/avatar.variants.ts +26 -0
- package/src/lib/avatar/index.ts +2 -0
- package/src/lib/avatar-group/avatar-group.component.spec.ts +74 -0
- package/src/lib/avatar-group/avatar-group.component.ts +88 -0
- package/src/lib/avatar-group/index.ts +1 -0
- package/src/lib/badge/badge.directive.spec.ts +74 -0
- package/src/lib/badge/badge.directive.ts +17 -0
- package/src/lib/badge/badge.variants.ts +29 -0
- package/src/lib/badge/index.ts +2 -0
- package/src/lib/breadcrumb/breadcrumb.directives.spec.ts +80 -0
- package/src/lib/breadcrumb/breadcrumb.directives.ts +78 -0
- package/src/lib/breadcrumb/index.ts +8 -0
- package/src/lib/button/button.directive.spec.ts +92 -0
- package/src/lib/button/button.directive.ts +28 -0
- package/src/lib/button/button.variants.ts +30 -0
- package/src/lib/button/index.ts +2 -0
- package/src/lib/button-group/button-group.directive.spec.ts +46 -0
- package/src/lib/button-group/button-group.directive.ts +19 -0
- package/src/lib/button-group/button-group.variants.ts +18 -0
- package/src/lib/button-group/index.ts +2 -0
- package/src/lib/calendar/calendar.component.spec.ts +192 -0
- package/src/lib/calendar/calendar.component.ts +342 -0
- package/src/lib/calendar/calendar.types.ts +24 -0
- package/src/lib/calendar/index.ts +7 -0
- package/src/lib/card/card.directives.spec.ts +104 -0
- package/src/lib/card/card.directives.ts +72 -0
- package/src/lib/card/card.variants.ts +28 -0
- package/src/lib/card/index.ts +9 -0
- package/src/lib/carousel/carousel.directives.spec.ts +85 -0
- package/src/lib/carousel/carousel.directives.ts +159 -0
- package/src/lib/carousel/index.ts +8 -0
- package/src/lib/chat-bubble/chat-bubble.directives.spec.ts +52 -0
- package/src/lib/chat-bubble/chat-bubble.directives.ts +96 -0
- package/src/lib/chat-bubble/index.ts +11 -0
- package/src/lib/checkbox/checkbox.directive.spec.ts +57 -0
- package/src/lib/checkbox/checkbox.directive.ts +16 -0
- package/src/lib/checkbox/checkbox.variants.ts +19 -0
- package/src/lib/checkbox/index.ts +2 -0
- package/src/lib/color-picker/color-picker.component.spec.ts +328 -0
- package/src/lib/color-picker/color-picker.component.ts +537 -0
- package/src/lib/color-picker/color-picker.types.ts +24 -0
- package/src/lib/color-picker/color-picker.utils.ts +183 -0
- package/src/lib/color-picker/color-picker.variants.ts +17 -0
- package/src/lib/color-picker/index.ts +20 -0
- package/src/lib/combobox/combobox.component.spec.ts +151 -0
- package/src/lib/combobox/combobox.component.ts +264 -0
- package/src/lib/combobox/combobox.variants.ts +19 -0
- package/src/lib/combobox/index.ts +2 -0
- package/src/lib/command-palette/command-palette.component.spec.ts +178 -0
- package/src/lib/command-palette/command-palette.component.ts +194 -0
- package/src/lib/command-palette/command-palette.service.ts +36 -0
- package/src/lib/command-palette/command-palette.types.ts +23 -0
- package/src/lib/command-palette/index.ts +7 -0
- package/src/lib/data-table/data-table.component.spec.ts +443 -0
- package/src/lib/data-table/data-table.component.ts +622 -0
- package/src/lib/data-table/data-table.directives.ts +31 -0
- package/src/lib/data-table/data-table.types.ts +26 -0
- package/src/lib/data-table/index.ts +14 -0
- package/src/lib/date-picker/date-picker.component.spec.ts +131 -0
- package/src/lib/date-picker/date-picker.component.ts +220 -0
- package/src/lib/date-picker/date-picker.variants.ts +17 -0
- package/src/lib/date-picker/index.ts +2 -0
- package/src/lib/date-range-picker/date-range-picker.component.spec.ts +151 -0
- package/src/lib/date-range-picker/date-range-picker.component.ts +340 -0
- package/src/lib/date-range-picker/index.ts +1 -0
- package/src/lib/diff/diff.component.spec.ts +47 -0
- package/src/lib/diff/diff.component.ts +82 -0
- package/src/lib/diff/index.ts +1 -0
- package/src/lib/divider/divider.component.spec.ts +48 -0
- package/src/lib/divider/divider.component.ts +51 -0
- package/src/lib/divider/divider.variants.ts +22 -0
- package/src/lib/divider/index.ts +2 -0
- package/src/lib/dock/dock.directives.spec.ts +85 -0
- package/src/lib/dock/dock.directives.ts +81 -0
- package/src/lib/dock/index.ts +1 -0
- package/src/lib/drawer/drawer.directives.spec.ts +62 -0
- package/src/lib/drawer/drawer.directives.ts +80 -0
- package/src/lib/drawer/index.ts +8 -0
- package/src/lib/dropdown/dropdown.directives.spec.ts +106 -0
- package/src/lib/dropdown/dropdown.directives.ts +136 -0
- package/src/lib/dropdown/dropdown.variants.ts +27 -0
- package/src/lib/dropdown/index.ts +15 -0
- package/src/lib/fab/fab.directives.spec.ts +60 -0
- package/src/lib/fab/fab.directives.ts +77 -0
- package/src/lib/fab/index.ts +8 -0
- package/src/lib/fieldset/fieldset.directives.spec.ts +74 -0
- package/src/lib/fieldset/fieldset.directives.ts +49 -0
- package/src/lib/fieldset/fieldset.variants.ts +15 -0
- package/src/lib/fieldset/index.ts +6 -0
- package/src/lib/file-input/file-input.component.spec.ts +114 -0
- package/src/lib/file-input/file-input.component.ts +155 -0
- package/src/lib/file-input/file-input.variants.ts +25 -0
- package/src/lib/file-input/index.ts +6 -0
- package/src/lib/indicator/index.ts +6 -0
- package/src/lib/indicator/indicator.directives.spec.ts +64 -0
- package/src/lib/indicator/indicator.directives.ts +59 -0
- package/src/lib/input/index.ts +3 -0
- package/src/lib/input/input.directive.spec.ts +103 -0
- package/src/lib/input/input.directive.ts +25 -0
- package/src/lib/input/input.variants.ts +42 -0
- package/src/lib/input/label.directive.ts +16 -0
- package/src/lib/kbd/index.ts +2 -0
- package/src/lib/kbd/kbd.directive.spec.ts +42 -0
- package/src/lib/kbd/kbd.directive.ts +18 -0
- package/src/lib/kbd/kbd.variants.ts +19 -0
- package/src/lib/link/index.ts +2 -0
- package/src/lib/link/link.directive.spec.ts +41 -0
- package/src/lib/link/link.directive.ts +18 -0
- package/src/lib/link/link.variants.ts +20 -0
- package/src/lib/list/index.ts +8 -0
- package/src/lib/list/list.directives.spec.ts +65 -0
- package/src/lib/list/list.directives.ts +81 -0
- package/src/lib/loader/index.ts +2 -0
- package/src/lib/loader/loader.component.spec.ts +58 -0
- package/src/lib/loader/loader.component.ts +47 -0
- package/src/lib/loader/loader.variants.ts +21 -0
- package/src/lib/modal/dialog-ref.ts +19 -0
- package/src/lib/modal/dialog.directives.ts +84 -0
- package/src/lib/modal/dialog.service.spec.ts +52 -0
- package/src/lib/modal/dialog.service.ts +61 -0
- package/src/lib/modal/dialog.types.ts +16 -0
- package/src/lib/modal/index.ts +11 -0
- package/src/lib/navbar/index.ts +7 -0
- package/src/lib/navbar/navbar.directives.spec.ts +59 -0
- package/src/lib/navbar/navbar.directives.ts +57 -0
- package/src/lib/number-input/index.ts +2 -0
- package/src/lib/number-input/number-input.component.spec.ts +151 -0
- package/src/lib/number-input/number-input.component.ts +152 -0
- package/src/lib/number-input/number-input.variants.ts +17 -0
- package/src/lib/otp-input/index.ts +2 -0
- package/src/lib/otp-input/otp-input.component.spec.ts +252 -0
- package/src/lib/otp-input/otp-input.component.ts +274 -0
- package/src/lib/otp-input/otp-input.variants.ts +18 -0
- package/src/lib/pagination/index.ts +6 -0
- package/src/lib/pagination/pagination.component.spec.ts +59 -0
- package/src/lib/pagination/pagination.component.ts +143 -0
- package/src/lib/pagination/pagination.variants.ts +31 -0
- package/src/lib/popover/index.ts +6 -0
- package/src/lib/popover/popover.directives.spec.ts +147 -0
- package/src/lib/popover/popover.directives.ts +151 -0
- package/src/lib/progress/index.ts +7 -0
- package/src/lib/progress/progress.component.spec.ts +117 -0
- package/src/lib/progress/progress.component.ts +64 -0
- package/src/lib/progress/progress.variants.ts +43 -0
- package/src/lib/radial-progress/index.ts +5 -0
- package/src/lib/radial-progress/radial-progress.component.spec.ts +41 -0
- package/src/lib/radial-progress/radial-progress.component.ts +70 -0
- package/src/lib/radio/index.ts +2 -0
- package/src/lib/radio/radio.directive.spec.ts +46 -0
- package/src/lib/radio/radio.directive.ts +16 -0
- package/src/lib/radio/radio.variants.ts +19 -0
- package/src/lib/rating/index.ts +2 -0
- package/src/lib/rating/rating.component.spec.ts +157 -0
- package/src/lib/rating/rating.component.ts +163 -0
- package/src/lib/rating/rating.variants.ts +20 -0
- package/src/lib/select/index.ts +2 -0
- package/src/lib/select/select.component.spec.ts +112 -0
- package/src/lib/select/select.component.ts +235 -0
- package/src/lib/select/select.variants.ts +19 -0
- package/src/lib/sheet/index.ts +10 -0
- package/src/lib/sheet/sheet-ref.ts +18 -0
- package/src/lib/sheet/sheet.component.spec.ts +67 -0
- package/src/lib/sheet/sheet.directives.ts +70 -0
- package/src/lib/sheet/sheet.service.ts +100 -0
- package/src/lib/sheet/sheet.types.ts +23 -0
- package/src/lib/skeleton/index.ts +2 -0
- package/src/lib/skeleton/skeleton.directive.spec.ts +63 -0
- package/src/lib/skeleton/skeleton.directive.ts +21 -0
- package/src/lib/skeleton/skeleton.variants.ts +27 -0
- package/src/lib/slider/index.ts +2 -0
- package/src/lib/slider/slider.component.spec.ts +104 -0
- package/src/lib/slider/slider.component.ts +181 -0
- package/src/lib/slider/slider.variants.ts +25 -0
- package/src/lib/stat/index.ts +8 -0
- package/src/lib/stat/stat.directives.spec.ts +60 -0
- package/src/lib/stat/stat.directives.ts +79 -0
- package/src/lib/status/index.ts +2 -0
- package/src/lib/status/status.directive.spec.ts +43 -0
- package/src/lib/status/status.directive.ts +37 -0
- package/src/lib/status/status.variants.ts +26 -0
- package/src/lib/steps/index.ts +8 -0
- package/src/lib/steps/steps.directives.spec.ts +52 -0
- package/src/lib/steps/steps.directives.ts +78 -0
- package/src/lib/switch/index.ts +2 -0
- package/src/lib/switch/switch.component.spec.ts +98 -0
- package/src/lib/switch/switch.component.ts +76 -0
- package/src/lib/switch/switch.variants.ts +31 -0
- package/src/lib/table/index.ts +12 -0
- package/src/lib/table/table.directives.spec.ts +111 -0
- package/src/lib/table/table.directives.ts +126 -0
- package/src/lib/table/table.variants.ts +36 -0
- package/src/lib/tabs/index.ts +8 -0
- package/src/lib/tabs/tabs.directives.spec.ts +136 -0
- package/src/lib/tabs/tabs.directives.ts +126 -0
- package/src/lib/tabs/tabs.variants.ts +17 -0
- package/src/lib/tag-input/index.ts +2 -0
- package/src/lib/tag-input/tag-input.component.spec.ts +190 -0
- package/src/lib/tag-input/tag-input.component.ts +172 -0
- package/src/lib/tag-input/tag-input.variants.ts +31 -0
- package/src/lib/textarea/index.ts +7 -0
- package/src/lib/textarea/textarea.directive.spec.ts +84 -0
- package/src/lib/textarea/textarea.directive.ts +71 -0
- package/src/lib/textarea/textarea.variants.ts +34 -0
- package/src/lib/timeline/index.ts +11 -0
- package/src/lib/timeline/timeline.directives.spec.ts +55 -0
- package/src/lib/timeline/timeline.directives.ts +85 -0
- package/src/lib/toast/index.ts +3 -0
- package/src/lib/toast/toast.service.spec.ts +71 -0
- package/src/lib/toast/toast.service.ts +60 -0
- package/src/lib/toast/toast.variants.ts +38 -0
- package/src/lib/toast/toaster.component.spec.ts +38 -0
- package/src/lib/toast/toaster.component.ts +81 -0
- package/src/lib/toggle/index.ts +2 -0
- package/src/lib/toggle/toggle.directive.spec.ts +100 -0
- package/src/lib/toggle/toggle.directive.ts +61 -0
- package/src/lib/toggle/toggle.variants.ts +25 -0
- package/src/lib/tooltip/index.ts +2 -0
- package/src/lib/tooltip/tooltip.directive.spec.ts +113 -0
- package/src/lib/tooltip/tooltip.directive.ts +130 -0
- package/src/lib/tooltip/tooltip.variants.ts +20 -0
- package/src/lib/validator/index.ts +5 -0
- package/src/lib/validator/validator.directives.spec.ts +47 -0
- package/src/lib/validator/validator.directives.ts +50 -0
- package/src/styles/sonny-theme.css +171 -0
- package/types/tony-ui-library-core.d.ts +2179 -0
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChangeDetectionStrategy,
|
|
3
|
+
Component,
|
|
4
|
+
TemplateRef,
|
|
5
|
+
computed,
|
|
6
|
+
contentChild,
|
|
7
|
+
contentChildren,
|
|
8
|
+
effect,
|
|
9
|
+
input,
|
|
10
|
+
model,
|
|
11
|
+
output,
|
|
12
|
+
signal,
|
|
13
|
+
untracked,
|
|
14
|
+
} from '@angular/core';
|
|
15
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
16
|
+
import {
|
|
17
|
+
TonTableDirective,
|
|
18
|
+
TonTableHeaderDirective,
|
|
19
|
+
TonTableBodyDirective,
|
|
20
|
+
TonTableRowDirective,
|
|
21
|
+
TonTableHeadDirective,
|
|
22
|
+
TonTableCellDirective,
|
|
23
|
+
} from '../table/table.directives';
|
|
24
|
+
import type { TableVariant, TableDensity } from '../table/table.variants';
|
|
25
|
+
import { TonPaginationComponent } from '../pagination/pagination.component';
|
|
26
|
+
import { TonCheckboxDirective } from '../checkbox/checkbox.directive';
|
|
27
|
+
import { TonInputDirective } from '../input/input.directive';
|
|
28
|
+
import { TonButtonDirective } from '../button/button.directive';
|
|
29
|
+
import { TonSelectComponent, type SelectOption } from '../select/select.component';
|
|
30
|
+
import { TonSkeletonDirective } from '../skeleton/skeleton.directive';
|
|
31
|
+
import {
|
|
32
|
+
TonDropdownDirective,
|
|
33
|
+
TonDropdownTriggerDirective,
|
|
34
|
+
TonDropdownContentDirective,
|
|
35
|
+
TonMenuItemDirective,
|
|
36
|
+
} from '../dropdown/dropdown.directives';
|
|
37
|
+
import {
|
|
38
|
+
TonCellDefDirective,
|
|
39
|
+
TonHeaderCellDefDirective,
|
|
40
|
+
TonBulkActionsDefDirective,
|
|
41
|
+
TonRowExpandDefDirective,
|
|
42
|
+
} from './data-table.directives';
|
|
43
|
+
import type {
|
|
44
|
+
DataTableColumn,
|
|
45
|
+
DataTableLabels,
|
|
46
|
+
DataTablePaginationConfig,
|
|
47
|
+
SortState,
|
|
48
|
+
SortDirection,
|
|
49
|
+
} from './data-table.types';
|
|
50
|
+
|
|
51
|
+
const DEFAULT_PAGINATION: DataTablePaginationConfig = {
|
|
52
|
+
pageSize: 10,
|
|
53
|
+
pageSizeOptions: [5, 10, 25, 50],
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const DEFAULT_LABELS: Required<DataTableLabels> = {
|
|
57
|
+
rowsPerPage: 'Rows per page',
|
|
58
|
+
rowsSelected: (selected, total) => `${selected} of ${total} row(s) selected`,
|
|
59
|
+
totalRows: (total) => `${total} row(s)`,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
@Component({
|
|
63
|
+
selector: 'ton-data-table',
|
|
64
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
65
|
+
imports: [
|
|
66
|
+
NgTemplateOutlet,
|
|
67
|
+
TonTableDirective,
|
|
68
|
+
TonTableHeaderDirective,
|
|
69
|
+
TonTableBodyDirective,
|
|
70
|
+
TonTableRowDirective,
|
|
71
|
+
TonTableHeadDirective,
|
|
72
|
+
TonTableCellDirective,
|
|
73
|
+
TonPaginationComponent,
|
|
74
|
+
TonCheckboxDirective,
|
|
75
|
+
TonInputDirective,
|
|
76
|
+
TonButtonDirective,
|
|
77
|
+
TonSelectComponent,
|
|
78
|
+
TonSkeletonDirective,
|
|
79
|
+
TonDropdownDirective,
|
|
80
|
+
TonDropdownTriggerDirective,
|
|
81
|
+
TonDropdownContentDirective,
|
|
82
|
+
TonMenuItemDirective,
|
|
83
|
+
],
|
|
84
|
+
template: `
|
|
85
|
+
<!-- Toolbar -->
|
|
86
|
+
@if (filterable() || showExport() || showColumnToggle()) {
|
|
87
|
+
<div class="flex items-center justify-between gap-4 mb-4 flex-wrap">
|
|
88
|
+
@if (filterable()) {
|
|
89
|
+
<input
|
|
90
|
+
tonInput
|
|
91
|
+
[value]="filterText()"
|
|
92
|
+
(input)="onFilterInput($event)"
|
|
93
|
+
placeholder="Filter..."
|
|
94
|
+
class="w-full sm:max-w-sm"
|
|
95
|
+
/>
|
|
96
|
+
}
|
|
97
|
+
<div class="flex items-center gap-2">
|
|
98
|
+
@if (showExport()) {
|
|
99
|
+
<button tonBtn variant="outline" size="sm" (click)="onExport()">
|
|
100
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="sm:mr-2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"/><path d="M14 2v6h6"/><path d="M12 18v-6"/><path d="m9 15 3-3 3 3"/></svg>
|
|
101
|
+
<span class="hidden sm:inline">Export</span>
|
|
102
|
+
</button>
|
|
103
|
+
}
|
|
104
|
+
@if (showColumnToggle()) {
|
|
105
|
+
<div tonDropdown class="relative">
|
|
106
|
+
<button tonBtn variant="outline" size="sm" tonDropdownTrigger>
|
|
107
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="sm:mr-2"><path d="M12 3v18"/><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M3 9h18"/><path d="M3 15h18"/></svg>
|
|
108
|
+
<span class="hidden sm:inline">Columns</span>
|
|
109
|
+
</button>
|
|
110
|
+
<div tonDropdownContent class="w-48 right-0 left-auto">
|
|
111
|
+
@for (col of columns(); track col.key) {
|
|
112
|
+
<label tonMenuItem class="flex items-center gap-2 cursor-pointer">
|
|
113
|
+
<input
|
|
114
|
+
type="checkbox"
|
|
115
|
+
tonCheckbox
|
|
116
|
+
[checked]="!hiddenColumns().has(col.key)"
|
|
117
|
+
(change)="toggleColumnVisibility(col.key)"
|
|
118
|
+
(click)="$event.stopPropagation()"
|
|
119
|
+
/>
|
|
120
|
+
{{ col.label }}
|
|
121
|
+
</label>
|
|
122
|
+
}
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
}
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
<!-- Bulk Actions Bar -->
|
|
131
|
+
@if (showBulkActions()) {
|
|
132
|
+
@let selected = selectedRows();
|
|
133
|
+
<div class="flex items-center gap-2 mb-4 p-3 bg-muted/50 rounded-sm border border-border flex-wrap">
|
|
134
|
+
<span class="text-sm font-medium text-muted-foreground mr-2">
|
|
135
|
+
{{ selected.length }} selected
|
|
136
|
+
</span>
|
|
137
|
+
<ng-container
|
|
138
|
+
[ngTemplateOutlet]="bulkActionsDef()!.template"
|
|
139
|
+
[ngTemplateOutletContext]="{ $implicit: selected }"
|
|
140
|
+
/>
|
|
141
|
+
<button
|
|
142
|
+
tonBtn variant="ghost" size="sm" class="ml-auto"
|
|
143
|
+
(click)="selectedRows.set([])"
|
|
144
|
+
>
|
|
145
|
+
Clear
|
|
146
|
+
</button>
|
|
147
|
+
</div>
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
<!-- Table -->
|
|
151
|
+
<div class="overflow-auto border border-border rounded-sm">
|
|
152
|
+
<table
|
|
153
|
+
tonTable
|
|
154
|
+
[variant]="variant()"
|
|
155
|
+
[density]="density()"
|
|
156
|
+
[hoverable]="hoverable()"
|
|
157
|
+
[stickyHeader]="stickyHeader()"
|
|
158
|
+
>
|
|
159
|
+
<thead tonTableHeader>
|
|
160
|
+
<tr tonTableRow>
|
|
161
|
+
@if (selectable()) {
|
|
162
|
+
<th tonTableHead class="w-12">
|
|
163
|
+
<input
|
|
164
|
+
type="checkbox"
|
|
165
|
+
tonCheckbox
|
|
166
|
+
[checked]="allSelected()"
|
|
167
|
+
[indeterminate]="someSelected() && !allSelected()"
|
|
168
|
+
(change)="toggleSelectAll()"
|
|
169
|
+
/>
|
|
170
|
+
</th>
|
|
171
|
+
}
|
|
172
|
+
@if (expandable()) {
|
|
173
|
+
<th tonTableHead class="w-10"></th>
|
|
174
|
+
}
|
|
175
|
+
@let sort = sortState();
|
|
176
|
+
@let headerDefs = headerCellDefMap();
|
|
177
|
+
@for (col of visibleColumns(); track col.key) {
|
|
178
|
+
<th
|
|
179
|
+
tonTableHead
|
|
180
|
+
[style.width]="col.width ?? null"
|
|
181
|
+
[class]="col.sortable ? 'cursor-pointer select-none' : ''"
|
|
182
|
+
(click)="col.sortable ? toggleSort(col.key) : null"
|
|
183
|
+
>
|
|
184
|
+
@if (headerDefs.has(col.key)) {
|
|
185
|
+
<ng-container
|
|
186
|
+
[ngTemplateOutlet]="headerDefs.get(col.key)!"
|
|
187
|
+
[ngTemplateOutletContext]="{ $implicit: col }"
|
|
188
|
+
/>
|
|
189
|
+
} @else {
|
|
190
|
+
<div class="flex items-center gap-1">
|
|
191
|
+
<span>{{ col.label }}</span>
|
|
192
|
+
@if (col.sortable) {
|
|
193
|
+
@let isActive = sort.key === col.key;
|
|
194
|
+
@if (isActive && sort.direction === 'asc') {
|
|
195
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m5 12 7-7 7 7"/></svg>
|
|
196
|
+
} @else if (isActive && sort.direction === 'desc') {
|
|
197
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m19 12-7 7-7-7"/></svg>
|
|
198
|
+
} @else {
|
|
199
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="opacity-30"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
</div>
|
|
203
|
+
}
|
|
204
|
+
</th>
|
|
205
|
+
}
|
|
206
|
+
</tr>
|
|
207
|
+
</thead>
|
|
208
|
+
<tbody tonTableBody>
|
|
209
|
+
@if (loading()) {
|
|
210
|
+
@for (i of skeletonRows(); track i) {
|
|
211
|
+
<tr tonTableRow>
|
|
212
|
+
@if (selectable()) {
|
|
213
|
+
<td tonTableCell class="w-12"><div tonSkeleton class="w-4 h-4 rounded"></div></td>
|
|
214
|
+
}
|
|
215
|
+
@if (expandable()) {
|
|
216
|
+
<td tonTableCell class="w-10"><div tonSkeleton class="w-4 h-4 rounded"></div></td>
|
|
217
|
+
}
|
|
218
|
+
@for (col of visibleColumns(); track col.key) {
|
|
219
|
+
<td tonTableCell [style.width]="col.width ?? null">
|
|
220
|
+
<div tonSkeleton class="w-full h-4 rounded"></div>
|
|
221
|
+
</td>
|
|
222
|
+
}
|
|
223
|
+
</tr>
|
|
224
|
+
}
|
|
225
|
+
} @else if (paginatedData().length === 0) {
|
|
226
|
+
<tr tonTableRow>
|
|
227
|
+
<td
|
|
228
|
+
tonTableCell
|
|
229
|
+
[attr.colspan]="totalColSpan()"
|
|
230
|
+
class="text-center text-muted-foreground py-8"
|
|
231
|
+
>
|
|
232
|
+
{{ noDataText() }}
|
|
233
|
+
</td>
|
|
234
|
+
</tr>
|
|
235
|
+
} @else {
|
|
236
|
+
@let cellDefs = cellDefMap();
|
|
237
|
+
@let cols = visibleColumns();
|
|
238
|
+
@let expandTpl = rowExpandDef();
|
|
239
|
+
@for (row of paginatedData(); track trackByFn(row, $index)) {
|
|
240
|
+
<tr
|
|
241
|
+
tonTableRow
|
|
242
|
+
[attr.data-state]="isSelected(row) ? 'selected' : null"
|
|
243
|
+
(click)="onRowClick(row)"
|
|
244
|
+
class="cursor-pointer"
|
|
245
|
+
>
|
|
246
|
+
@if (selectable()) {
|
|
247
|
+
<td tonTableCell class="w-12">
|
|
248
|
+
<input
|
|
249
|
+
type="checkbox"
|
|
250
|
+
tonCheckbox
|
|
251
|
+
[checked]="isSelected(row)"
|
|
252
|
+
(change)="toggleRowSelection(row)"
|
|
253
|
+
(click)="$event.stopPropagation()"
|
|
254
|
+
/>
|
|
255
|
+
</td>
|
|
256
|
+
}
|
|
257
|
+
@if (expandable()) {
|
|
258
|
+
<td tonTableCell class="w-10">
|
|
259
|
+
<button
|
|
260
|
+
class="p-0.5 rounded hover:bg-accent transition-transform duration-150"
|
|
261
|
+
[class.rotate-90]="isExpanded(row)"
|
|
262
|
+
(click)="toggleRowExpansion(row); $event.stopPropagation()"
|
|
263
|
+
>
|
|
264
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>
|
|
265
|
+
</button>
|
|
266
|
+
</td>
|
|
267
|
+
}
|
|
268
|
+
@for (col of cols; track col.key) {
|
|
269
|
+
<td tonTableCell [style.width]="col.width ?? null">
|
|
270
|
+
@if (cellDefs.has(col.key)) {
|
|
271
|
+
<ng-container
|
|
272
|
+
[ngTemplateOutlet]="cellDefs.get(col.key)!"
|
|
273
|
+
[ngTemplateOutletContext]="{ $implicit: row[col.key], row: row }"
|
|
274
|
+
/>
|
|
275
|
+
} @else {
|
|
276
|
+
{{ row[col.key] }}
|
|
277
|
+
}
|
|
278
|
+
</td>
|
|
279
|
+
}
|
|
280
|
+
</tr>
|
|
281
|
+
@if (expandable() && isExpanded(row) && expandTpl) {
|
|
282
|
+
<tr tonTableRow>
|
|
283
|
+
<td tonTableCell [attr.colspan]="totalColSpan()" class="bg-muted/30">
|
|
284
|
+
<ng-container
|
|
285
|
+
[ngTemplateOutlet]="expandTpl.template"
|
|
286
|
+
[ngTemplateOutletContext]="{ $implicit: row }"
|
|
287
|
+
/>
|
|
288
|
+
</td>
|
|
289
|
+
</tr>
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
</tbody>
|
|
294
|
+
</table>
|
|
295
|
+
</div>
|
|
296
|
+
|
|
297
|
+
<!-- Footer -->
|
|
298
|
+
@if (paginated()) {
|
|
299
|
+
<div class="flex flex-col sm:flex-row items-start sm:items-center justify-between mt-4 gap-3 sm:gap-4">
|
|
300
|
+
<span class="text-sm text-muted-foreground">
|
|
301
|
+
@if (selectable()) {
|
|
302
|
+
{{ resolvedLabels().rowsSelected(selectedRows().length, filteredData().length) }}
|
|
303
|
+
} @else {
|
|
304
|
+
{{ resolvedLabels().totalRows(filteredData().length) }}
|
|
305
|
+
}
|
|
306
|
+
</span>
|
|
307
|
+
<div class="flex items-center gap-3 sm:gap-4 flex-wrap">
|
|
308
|
+
<div class="flex items-center gap-2">
|
|
309
|
+
<span class="hidden sm:inline text-sm text-muted-foreground whitespace-nowrap">{{ resolvedLabels().rowsPerPage }}</span>
|
|
310
|
+
<ton-select
|
|
311
|
+
[options]="pageSizeOptions()"
|
|
312
|
+
[value]="pageSizeValue()"
|
|
313
|
+
(valueChange)="onPageSizeChange($event)"
|
|
314
|
+
size="sm"
|
|
315
|
+
class="w-20"
|
|
316
|
+
/>
|
|
317
|
+
</div>
|
|
318
|
+
<ton-pagination
|
|
319
|
+
[currentPage]="currentPage()"
|
|
320
|
+
(currentPageChange)="currentPage.set($event)"
|
|
321
|
+
[totalPages]="totalPages()"
|
|
322
|
+
/>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
}
|
|
326
|
+
`,
|
|
327
|
+
})
|
|
328
|
+
export class TonDataTableComponent {
|
|
329
|
+
// Inputs
|
|
330
|
+
readonly columns = input.required<DataTableColumn[]>();
|
|
331
|
+
readonly data = input.required<Record<string, unknown>[]>();
|
|
332
|
+
readonly variant = input<TableVariant>('default');
|
|
333
|
+
readonly density = input<TableDensity>('normal');
|
|
334
|
+
readonly hoverable = input(true);
|
|
335
|
+
readonly stickyHeader = input(false);
|
|
336
|
+
readonly selectable = input(false);
|
|
337
|
+
readonly paginated = input(true);
|
|
338
|
+
readonly filterable = input(true);
|
|
339
|
+
readonly showExport = input(false);
|
|
340
|
+
readonly showColumnToggle = input(false);
|
|
341
|
+
readonly expandable = input(false);
|
|
342
|
+
readonly loading = input(false);
|
|
343
|
+
readonly loadingRows = input(5);
|
|
344
|
+
readonly paginationConfig = input<DataTablePaginationConfig>(DEFAULT_PAGINATION);
|
|
345
|
+
readonly trackBy = input('');
|
|
346
|
+
readonly noDataText = input('No data available');
|
|
347
|
+
readonly labels = input<DataTableLabels>({});
|
|
348
|
+
|
|
349
|
+
// Model
|
|
350
|
+
readonly selectedRows = model<Record<string, unknown>[]>([]);
|
|
351
|
+
|
|
352
|
+
// Outputs
|
|
353
|
+
readonly sortChanged = output<SortState>();
|
|
354
|
+
readonly rowClicked = output<Record<string, unknown>>();
|
|
355
|
+
readonly dataExported = output<Record<string, unknown>[]>();
|
|
356
|
+
|
|
357
|
+
// Content queries
|
|
358
|
+
readonly cellDefs = contentChildren(TonCellDefDirective);
|
|
359
|
+
readonly headerCellDefs = contentChildren(TonHeaderCellDefDirective);
|
|
360
|
+
readonly bulkActionsDef = contentChild(TonBulkActionsDefDirective);
|
|
361
|
+
readonly rowExpandDef = contentChild(TonRowExpandDefDirective);
|
|
362
|
+
|
|
363
|
+
// Resolved labels
|
|
364
|
+
readonly resolvedLabels = computed(() => ({ ...DEFAULT_LABELS, ...this.labels() }));
|
|
365
|
+
|
|
366
|
+
// Internal state
|
|
367
|
+
readonly sortState = signal<SortState>({ key: '', direction: null });
|
|
368
|
+
readonly filterText = signal('');
|
|
369
|
+
readonly currentPage = signal(1);
|
|
370
|
+
readonly pageSize = signal(10);
|
|
371
|
+
readonly hiddenColumns = signal<Set<string>>(new Set());
|
|
372
|
+
readonly expandedRows = signal<Set<unknown>>(new Set());
|
|
373
|
+
|
|
374
|
+
// Template def maps
|
|
375
|
+
readonly cellDefMap = computed(() => {
|
|
376
|
+
const map = new Map<string, TemplateRef<unknown>>();
|
|
377
|
+
for (const def of this.cellDefs()) {
|
|
378
|
+
map.set(def.tonCell(), def.template);
|
|
379
|
+
}
|
|
380
|
+
return map;
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
readonly headerCellDefMap = computed(() => {
|
|
384
|
+
const map = new Map<string, TemplateRef<unknown>>();
|
|
385
|
+
for (const def of this.headerCellDefs()) {
|
|
386
|
+
map.set(def.tonHeaderCell(), def.template);
|
|
387
|
+
}
|
|
388
|
+
return map;
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// Visible columns
|
|
392
|
+
readonly visibleColumns = computed(() =>
|
|
393
|
+
this.columns().filter(
|
|
394
|
+
(col) => col.visible !== false && !this.hiddenColumns().has(col.key)
|
|
395
|
+
)
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
// Page size options
|
|
399
|
+
readonly pageSizeOptions = computed<SelectOption[]>(() =>
|
|
400
|
+
this.paginationConfig().pageSizeOptions.map((n) => ({
|
|
401
|
+
value: String(n),
|
|
402
|
+
label: String(n),
|
|
403
|
+
}))
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
readonly pageSizeValue = computed(() => String(this.pageSize()));
|
|
407
|
+
|
|
408
|
+
// Skeleton rows
|
|
409
|
+
readonly skeletonRows = computed(() =>
|
|
410
|
+
Array.from({ length: this.loadingRows() }, (_, i) => i)
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
// Bulk actions visibility
|
|
414
|
+
readonly showBulkActions = computed(
|
|
415
|
+
() =>
|
|
416
|
+
this.selectable() &&
|
|
417
|
+
this.selectedRows().length > 0 &&
|
|
418
|
+
this.bulkActionsDef() != null
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
// Data pipeline (filter uses all columns, not just visible)
|
|
422
|
+
readonly filteredData = computed(() => {
|
|
423
|
+
const text = this.filterText().toLowerCase().trim();
|
|
424
|
+
const rows = this.data();
|
|
425
|
+
if (!text) return rows;
|
|
426
|
+
const cols = this.columns().filter((c) => c.filterable !== false);
|
|
427
|
+
return rows.filter((row) =>
|
|
428
|
+
cols.some((col) =>
|
|
429
|
+
String(row[col.key] ?? '').toLowerCase().includes(text)
|
|
430
|
+
)
|
|
431
|
+
);
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
readonly sortedData = computed(() => {
|
|
435
|
+
const { key, direction } = this.sortState();
|
|
436
|
+
const rows = this.filteredData();
|
|
437
|
+
if (!key || !direction) return rows;
|
|
438
|
+
return [...rows].sort((a, b) => {
|
|
439
|
+
const aVal = a[key];
|
|
440
|
+
const bVal = b[key];
|
|
441
|
+
if (aVal == null && bVal == null) return 0;
|
|
442
|
+
if (aVal == null) return direction === 'asc' ? -1 : 1;
|
|
443
|
+
if (bVal == null) return direction === 'asc' ? 1 : -1;
|
|
444
|
+
if (typeof aVal === 'number' && typeof bVal === 'number') {
|
|
445
|
+
return direction === 'asc' ? aVal - bVal : bVal - aVal;
|
|
446
|
+
}
|
|
447
|
+
const cmp = String(aVal).localeCompare(String(bVal));
|
|
448
|
+
return direction === 'asc' ? cmp : -cmp;
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
readonly totalPages = computed(() =>
|
|
453
|
+
Math.max(1, Math.ceil(this.filteredData().length / this.pageSize()))
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
readonly paginatedData = computed(() => {
|
|
457
|
+
if (!this.paginated()) return this.sortedData();
|
|
458
|
+
const start = (this.currentPage() - 1) * this.pageSize();
|
|
459
|
+
return this.sortedData().slice(start, start + this.pageSize());
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
readonly totalColSpan = computed(
|
|
463
|
+
() =>
|
|
464
|
+
this.visibleColumns().length +
|
|
465
|
+
(this.selectable() ? 1 : 0) +
|
|
466
|
+
(this.expandable() ? 1 : 0)
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
// Selection computed
|
|
470
|
+
readonly allSelected = computed(() => {
|
|
471
|
+
const page = this.paginatedData();
|
|
472
|
+
if (page.length === 0) return false;
|
|
473
|
+
const selected = this.selectedRows();
|
|
474
|
+
return page.every((row) => this.isRowInList(row, selected));
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
readonly someSelected = computed(() => {
|
|
478
|
+
const page = this.paginatedData();
|
|
479
|
+
const selected = this.selectedRows();
|
|
480
|
+
return page.some((row) => this.isRowInList(row, selected));
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
constructor() {
|
|
484
|
+
effect(() => {
|
|
485
|
+
const config = this.paginationConfig();
|
|
486
|
+
untracked(() => this.pageSize.set(config.pageSize));
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
effect(() => {
|
|
490
|
+
this.filterText();
|
|
491
|
+
this.pageSize();
|
|
492
|
+
const data = this.data();
|
|
493
|
+
untracked(() => {
|
|
494
|
+
this.currentPage.set(1);
|
|
495
|
+
const selected = this.selectedRows();
|
|
496
|
+
if (selected.length) {
|
|
497
|
+
const cleaned = selected.filter((row) => this.isRowInList(row, data));
|
|
498
|
+
if (cleaned.length !== selected.length) {
|
|
499
|
+
this.selectedRows.set(cleaned);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Sort
|
|
507
|
+
toggleSort(key: string): void {
|
|
508
|
+
const current = this.sortState();
|
|
509
|
+
let direction: SortDirection;
|
|
510
|
+
if (current.key !== key) {
|
|
511
|
+
direction = 'asc';
|
|
512
|
+
} else if (current.direction === 'asc') {
|
|
513
|
+
direction = 'desc';
|
|
514
|
+
} else if (current.direction === 'desc') {
|
|
515
|
+
direction = null;
|
|
516
|
+
} else {
|
|
517
|
+
direction = 'asc';
|
|
518
|
+
}
|
|
519
|
+
const next: SortState = { key: direction ? key : '', direction };
|
|
520
|
+
this.sortState.set(next);
|
|
521
|
+
this.sortChanged.emit(next);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Filter
|
|
525
|
+
onFilterInput(event: Event): void {
|
|
526
|
+
this.filterText.set((event.target as HTMLInputElement).value);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Page size
|
|
530
|
+
onPageSizeChange(value: string): void {
|
|
531
|
+
this.pageSize.set(Number(value));
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Selection
|
|
535
|
+
toggleSelectAll(): void {
|
|
536
|
+
if (this.allSelected()) {
|
|
537
|
+
const page = this.paginatedData();
|
|
538
|
+
this.selectedRows.update((sel) =>
|
|
539
|
+
sel.filter((r) => !page.some((p) => this.rowsEqual(r, p)))
|
|
540
|
+
);
|
|
541
|
+
} else {
|
|
542
|
+
const page = this.paginatedData();
|
|
543
|
+
this.selectedRows.update((sel) => {
|
|
544
|
+
const newSel = [...sel];
|
|
545
|
+
for (const row of page) {
|
|
546
|
+
if (!this.isRowInList(row, newSel)) newSel.push(row);
|
|
547
|
+
}
|
|
548
|
+
return newSel;
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
toggleRowSelection(row: Record<string, unknown>): void {
|
|
554
|
+
this.selectedRows.update((sel) =>
|
|
555
|
+
this.isRowInList(row, sel)
|
|
556
|
+
? sel.filter((r) => !this.rowsEqual(r, row))
|
|
557
|
+
: [...sel, row]
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// Row click
|
|
562
|
+
onRowClick(row: Record<string, unknown>): void {
|
|
563
|
+
this.rowClicked.emit(row);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// Export
|
|
567
|
+
onExport(): void {
|
|
568
|
+
this.dataExported.emit(this.filteredData());
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Column visibility
|
|
572
|
+
toggleColumnVisibility(key: string): void {
|
|
573
|
+
this.hiddenColumns.update((set) => {
|
|
574
|
+
const next = new Set(set);
|
|
575
|
+
if (next.has(key)) next.delete(key);
|
|
576
|
+
else next.add(key);
|
|
577
|
+
return next;
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Expansion
|
|
582
|
+
toggleRowExpansion(row: Record<string, unknown>): void {
|
|
583
|
+
const key = this.trackBy() ? row[this.trackBy()] : row;
|
|
584
|
+
this.expandedRows.update((set) => {
|
|
585
|
+
const next = new Set(set);
|
|
586
|
+
if (next.has(key)) next.delete(key);
|
|
587
|
+
else next.add(key);
|
|
588
|
+
return next;
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
isExpanded(row: Record<string, unknown>): boolean {
|
|
593
|
+
const key = this.trackBy() ? row[this.trackBy()] : row;
|
|
594
|
+
return this.expandedRows().has(key);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Helpers
|
|
598
|
+
isSelected(row: Record<string, unknown>): boolean {
|
|
599
|
+
return this.isRowInList(row, this.selectedRows());
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
trackByFn(row: Record<string, unknown>, index: number): unknown {
|
|
603
|
+
const key = this.trackBy();
|
|
604
|
+
return key ? row[key] : index;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
private isRowInList(
|
|
608
|
+
row: Record<string, unknown>,
|
|
609
|
+
list: Record<string, unknown>[]
|
|
610
|
+
): boolean {
|
|
611
|
+
return list.some((r) => this.rowsEqual(r, row));
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
private rowsEqual(
|
|
615
|
+
a: Record<string, unknown>,
|
|
616
|
+
b: Record<string, unknown>
|
|
617
|
+
): boolean {
|
|
618
|
+
const key = this.trackBy();
|
|
619
|
+
if (key) return a[key] === b[key];
|
|
620
|
+
return a === b;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Directive, TemplateRef, inject, input } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Directive({
|
|
4
|
+
selector: '[tonCell]',
|
|
5
|
+
})
|
|
6
|
+
export class TonCellDefDirective {
|
|
7
|
+
readonly tonCell = input.required<string>();
|
|
8
|
+
readonly template = inject(TemplateRef);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@Directive({
|
|
12
|
+
selector: '[tonHeaderCell]',
|
|
13
|
+
})
|
|
14
|
+
export class TonHeaderCellDefDirective {
|
|
15
|
+
readonly tonHeaderCell = input.required<string>();
|
|
16
|
+
readonly template = inject(TemplateRef);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@Directive({
|
|
20
|
+
selector: '[tonBulkActions]',
|
|
21
|
+
})
|
|
22
|
+
export class TonBulkActionsDefDirective {
|
|
23
|
+
readonly template = inject(TemplateRef);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@Directive({
|
|
27
|
+
selector: '[tonRowExpand]',
|
|
28
|
+
})
|
|
29
|
+
export class TonRowExpandDefDirective {
|
|
30
|
+
readonly template = inject(TemplateRef);
|
|
31
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface DataTableColumn {
|
|
2
|
+
key: string;
|
|
3
|
+
label: string;
|
|
4
|
+
sortable?: boolean;
|
|
5
|
+
filterable?: boolean;
|
|
6
|
+
width?: string;
|
|
7
|
+
visible?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type SortDirection = 'asc' | 'desc' | null;
|
|
11
|
+
|
|
12
|
+
export interface SortState {
|
|
13
|
+
key: string;
|
|
14
|
+
direction: SortDirection;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface DataTablePaginationConfig {
|
|
18
|
+
pageSize: number;
|
|
19
|
+
pageSizeOptions: number[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface DataTableLabels {
|
|
23
|
+
rowsPerPage?: string;
|
|
24
|
+
rowsSelected?: (selected: number, total: number) => string;
|
|
25
|
+
totalRows?: (total: number) => string;
|
|
26
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { TonDataTableComponent } from './data-table.component';
|
|
2
|
+
export {
|
|
3
|
+
TonCellDefDirective,
|
|
4
|
+
TonHeaderCellDefDirective,
|
|
5
|
+
TonBulkActionsDefDirective,
|
|
6
|
+
TonRowExpandDefDirective,
|
|
7
|
+
} from './data-table.directives';
|
|
8
|
+
export type {
|
|
9
|
+
DataTableColumn,
|
|
10
|
+
SortState,
|
|
11
|
+
SortDirection,
|
|
12
|
+
DataTableLabels,
|
|
13
|
+
DataTablePaginationConfig,
|
|
14
|
+
} from './data-table.types';
|