b2b-tools 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +109 -28
  2. package/fesm2022/b2b-tools.mjs +1091 -0
  3. package/fesm2022/b2b-tools.mjs.map +1 -0
  4. package/package.json +24 -13
  5. package/types/b2b-tools.d.ts +578 -0
  6. package/LICENCE +0 -21
  7. package/ng-package.json +0 -7
  8. package/src/lib/b2b-tools.spec.ts +0 -23
  9. package/src/lib/b2b-tools.ts +0 -15
  10. package/src/lib/components/advanced-card/advanced-card.css +0 -265
  11. package/src/lib/components/advanced-card/advanced-card.html +0 -117
  12. package/src/lib/components/advanced-card/advanced-card.ts +0 -75
  13. package/src/lib/components/advanced-card/index.ts +0 -2
  14. package/src/lib/components/advanced-card/types/card.types.ts +0 -37
  15. package/src/lib/components/advanced-card/types/index.ts +0 -1
  16. package/src/lib/components/advanced-table/advanced-table.component.css +0 -81
  17. package/src/lib/components/advanced-table/advanced-table.component.html +0 -56
  18. package/src/lib/components/advanced-table/advanced-table.component.ts +0 -469
  19. package/src/lib/components/advanced-table/index.ts +0 -2
  20. package/src/lib/components/advanced-table/parts/table-grid/table-grid.component.css +0 -274
  21. package/src/lib/components/advanced-table/parts/table-grid/table-grid.component.html +0 -168
  22. package/src/lib/components/advanced-table/parts/table-grid/table-grid.component.ts +0 -224
  23. package/src/lib/components/advanced-table/parts/table-modal-image/table-modal-image.component.css +0 -49
  24. package/src/lib/components/advanced-table/parts/table-modal-image/table-modal-image.component.html +0 -14
  25. package/src/lib/components/advanced-table/parts/table-modal-image/table-modal-image.component.ts +0 -22
  26. package/src/lib/components/advanced-table/parts/table-pagination/table-pagination.component.css +0 -147
  27. package/src/lib/components/advanced-table/parts/table-pagination/table-pagination.component.html +0 -95
  28. package/src/lib/components/advanced-table/parts/table-pagination/table-pagination.component.ts +0 -61
  29. package/src/lib/components/advanced-table/parts/table-toolbar/table-toolbar.component.css +0 -32
  30. package/src/lib/components/advanced-table/parts/table-toolbar/table-toolbar.component.html +0 -17
  31. package/src/lib/components/advanced-table/parts/table-toolbar/table-toolbar.component.ts +0 -30
  32. package/src/lib/components/advanced-table/types/index.ts +0 -2
  33. package/src/lib/components/advanced-table/types/table.types.ts +0 -101
  34. package/src/lib/components/advanced-table/types/time-zone.types.ts +0 -91
  35. package/src/lib/components/index.ts +0 -2
  36. package/src/public-api.ts +0 -4
  37. package/tsconfig.lib.json +0 -17
  38. package/tsconfig.lib.prod.json +0 -11
  39. package/tsconfig.spec.json +0 -15
@@ -1,274 +0,0 @@
1
- .dt-grid {
2
- width: 100%;
3
- }
4
-
5
- .dt-row {
6
- display: grid;
7
- align-items: stretch;
8
- min-width: max-content;
9
- }
10
-
11
- .dt-xscroll {
12
- overflow-x: auto;
13
- overflow-y: hidden;
14
- }
15
-
16
- .dt-header {
17
- background: var(--gray-white);
18
- border-bottom: var(--border);
19
- font-weight: 600;
20
- color: var(--black);
21
- }
22
-
23
- .dt-cell--header {
24
- user-select: none;
25
- }
26
-
27
- .dt-cell--sortable {
28
- cursor: pointer;
29
- }
30
-
31
- .dt-filters {
32
- background: var(--xxs-light-gray);
33
- border-bottom: var(--border);
34
- }
35
-
36
- .dt-cell--filter {
37
- padding: 8px 12px;
38
- }
39
-
40
- input {
41
- width: 100%;
42
- padding: 7px 8px;
43
- border: 1px solid var(--light-gray);
44
- border-radius: var(--radius-sm);
45
- background: var(--white);
46
- color: var(--black);
47
- outline: none;
48
- }
49
-
50
- input::placeholder {
51
- color: var(--xs-dark-gray);
52
- }
53
-
54
- input:focus {
55
- border-color: var(--blue);
56
- box-shadow: var(--focus-ring);
57
- }
58
-
59
- .dt-body {
60
- overflow-y: auto;
61
- overflow-x: hidden;
62
- min-width: max-content;
63
- }
64
-
65
- @media (max-heicg: 900px) {
66
- .dt-body {
67
- max-height: none !important;
68
- overflow-y: visible !important;
69
- overflow-x: auto !important;
70
- }
71
- }
72
-
73
- .dt-cell {
74
- padding: 10px 12px;
75
- min-height: 30px;
76
- border-bottom: 1px solid var(--xxs-light-gray);
77
- display: flex;
78
- align-items: center;
79
- gap: 8px;
80
- color: var(--black);
81
- }
82
-
83
- .dt-cell[data-align='left'] {
84
- justify-content: flex-start;
85
- text-align: left;
86
- }
87
-
88
- .dt-cell[data-align='center'] {
89
- justify-content: center;
90
- text-align: center;
91
- }
92
-
93
- .dt-cell[data-align='right'] {
94
- justify-content: flex-end;
95
- text-align: right;
96
- }
97
-
98
- .dt-cell--center {
99
- justify-content: center;
100
- }
101
-
102
- .dt-select-col {
103
- justify-content: center;
104
- }
105
-
106
- .dt-header-label {
107
- overflow: hidden;
108
- white-space: nowrap;
109
- text-overflow: ellipsis;
110
- }
111
-
112
- .dt-sort {
113
- margin-left: auto;
114
- font-size: 12px;
115
- opacity: 0.7;
116
- color: var(--xs-dark-gray);
117
- }
118
-
119
- .dt-data:hover {
120
- background: var(--gray);
121
- }
122
-
123
- .dt-text {
124
- overflow: hidden;
125
- white-space: nowrap;
126
- text-overflow: ellipsis;
127
- }
128
-
129
- .dt-img {
130
- width: 40px;
131
- height: 40px;
132
- object-fit: cover;
133
- border-radius: var(--radius-sm);
134
- border: 1px solid var(--xs-light-gray);
135
- cursor: pointer;
136
- }
137
-
138
- .dt-img--full {
139
- width: 100%;
140
- height: auto;
141
- }
142
-
143
- .dt-link {
144
- color: var(--blue);
145
- text-decoration: none;
146
- background: transparent;
147
- border: none;
148
- cursor: pointer;
149
- padding: 0;
150
- font: inherit;
151
- }
152
-
153
- .dt-link:hover {
154
- text-decoration: underline;
155
- }
156
-
157
- .dt-badge {
158
- padding: 4px 10px;
159
- border-radius: 999px;
160
- border: 1px solid var(--xs-light-gray);
161
- font-size: 12px;
162
- background: var(--xxs-light-gray);
163
- }
164
-
165
- .dt-badge[data-variant='success'] {
166
- background: rgba(32, 139, 106, 0.12);
167
- border-color: rgba(32, 139, 106, 0.35);
168
- }
169
-
170
- .dt-badge[data-variant='warn'] {
171
- background: rgba(255, 188, 87, 0.2);
172
- border-color: rgba(255, 188, 87, 0.45);
173
- }
174
-
175
- .dt-badge[data-variant='error'] {
176
- background: rgba(230, 0, 24, 0.12);
177
- border-color: rgba(230, 0, 24, 0.35);
178
- }
179
-
180
- .dt-badge[data-variant='info'] {
181
- background: rgba(115, 144, 236, 0.14);
182
- border-color: rgba(115, 144, 236, 0.35);
183
- }
184
-
185
- .dt-empty {
186
- padding: 18px 12px;
187
- color: var(--xs-dark-gray);
188
- }
189
-
190
- .dt-actions {
191
- display: inline-flex;
192
- align-items: center;
193
- gap: 6px;
194
- }
195
- .dt-action-svg {
196
- width: 24px;
197
- height: 24px;
198
- display: inline-flex;
199
- }
200
-
201
- .dt-action-svg svg {
202
- width: 24px;
203
- height: 24px;
204
- color: inherit;
205
- }
206
-
207
- /* Base del botón */
208
- .dt-action-btn {
209
- width: 32px;
210
- height: 32px;
211
- border: 1px solid var(--xs-light-gray);
212
- border-radius: var(--radius-sm);
213
- background: var(--white);
214
- cursor: pointer;
215
- display: inline-flex;
216
- align-items: center;
217
- justify-content: center;
218
-
219
- /* default icon color */
220
- color: var(--xs-dark-gray);
221
- }
222
-
223
- /* Hover general (NO tocar color aquí) */
224
- .dt-action-btn:hover:not(:disabled) {
225
- background: var(--gray-white);
226
- border-color: var(--dark-gray);
227
- }
228
-
229
- /* Edit */
230
- .dt-action-btn.dt-action--edit {
231
- color: var(--blue);
232
- }
233
- .dt-action-btn.dt-action--edit:hover:not(:disabled) {
234
- color: var(--white);
235
- background-color: var(--blue);
236
- }
237
-
238
- /* Open */
239
- .dt-action-btn.dt-action--open {
240
- color: var(--blue-medium);
241
- }
242
- .dt-action-btn.dt-action--open:hover:not(:disabled) {
243
- color: var(--blue-dark);
244
- }
245
-
246
- /* Copy */
247
- .dt-action-btn.dt-action--copy {
248
- color: var(--xs-dark-gray);
249
- }
250
- .dt-action-btn.dt-action--copy:hover:not(:disabled) {
251
- color: var(--white);
252
- background-color: var(--xs-dark-gray);
253
- }
254
-
255
- /* Delete */
256
- .dt-action-btn.dt-action--delete {
257
- color: var(--red);
258
- }
259
- .dt-action-btn.dt-action--delete:hover:not(:disabled) {
260
- color: var(--white);
261
- background-color: var(--red);
262
- }
263
-
264
- /* Disabled */
265
- .dt-action-btn:disabled {
266
- color: var(--disabled-text);
267
- background: var(--soft-white);
268
- cursor: not-allowed;
269
- }
270
-
271
- .dt-action-text {
272
- font-size: 24px;
273
- padding: 0 8px;
274
- }
@@ -1,168 +0,0 @@
1
- <div class="dt-grid">
2
- <div class="dt-xscroll">
3
- <!-- Header -->
4
- <div class="dt-row dt-header" [style.gridTemplateColumns]="gridTemplateColumns()">
5
- @if (showSelectionColumn()) {
6
- <div class="dt-cell dt-cell--header dt-cell--center dt-select-col">
7
- @if ((config().selectionMode ?? 'multiple') === 'multiple') {
8
- <input
9
- type="checkbox"
10
- [checked]="isAllSelectedOnPage()"
11
- (change)="onToggleAllOnPage()"
12
- aria-label="Seleccionar todo"
13
- />
14
- }
15
- </div>
16
- }
17
-
18
- @for (col of columns(); track col.key) {
19
- <div
20
- class="dt-cell dt-cell--header"
21
- [class.dt-cell--sortable]="!!col.sortable"
22
- [attr.data-align]="col.align ?? 'left'"
23
- (click)="onHeaderClickSort(col)"
24
- role="button"
25
- tabindex="0"
26
- >
27
- <span class="dt-header-label">{{ col.label }}</span>
28
- @if (col.sortable) {
29
- <span class="dt-sort">{{ getSortIcon(col.key) }}</span>
30
- }
31
- </div>
32
- }
33
- </div>
34
-
35
- <!-- Filters row (under header) -->
36
- @if (config().columnFilters) {
37
- <div class="dt-row dt-filters" [style.gridTemplateColumns]="gridTemplateColumns()">
38
- @if (showSelectionColumn()) {
39
- <div class="dt-cell dt-cell--filter dt-select-col"></div>
40
- }
41
-
42
- @for (col of columns(); track col.key) {
43
- <div class="dt-cell dt-cell--filter" [attr.data-align]="col.align ?? 'left'">
44
- @if (col.filterable) {
45
- <input
46
- type="text"
47
- [value]="columnQueries()[col.key] ?? null"
48
- (input)="onColumnQueryInput(col.key, $any($event.target).value)"
49
- [placeholder]="'Filtrar ' + col.label"
50
- />
51
- }
52
- </div>
53
- }
54
- </div>
55
- }
56
-
57
- <!-- Body -->
58
- <div
59
- class="dt-body"
60
- [style.maxHeight.px]="config().scroll?.heightPx ?? null"
61
- (scroll)="onBodyScroll($event)"
62
- >
63
- @if (rows().length === 0) {
64
- <div class="dt-empty">
65
- {{ config().emptyText ?? 'Sin resultados' }}
66
- </div>
67
- } @else {
68
- @for (row of rows(); track getRowId(row)) {
69
- <div class="dt-row dt-data" [style.gridTemplateColumns]="gridTemplateColumns()">
70
- @if (showSelectionColumn()) {
71
- <div class="dt-cell dt-cell--center dt-select-col">
72
- <input
73
- type="checkbox"
74
- [checked]="isSelected(row)"
75
- (change)="onToggleRow(row)"
76
- aria-label="Seleccionar fila"
77
- />
78
- </div>
79
- }
80
-
81
- @for (col of columns(); track col.key) {
82
- <div
83
- class="dt-cell"
84
- [attr.data-align]="col.align ?? 'left'"
85
- (click)="onRowClick(row)"
86
- >
87
- @switch (col.type) {
88
- @case ('image') {
89
- @if ((col.options?.image?.hidden ?? false) === true) {
90
- <button
91
- type="button"
92
- class="dt-link"
93
- (click)="onOpenImage(getImageSrc(row, col), getImageAlt(row, col), $event)"
94
- >
95
- Ver imagen
96
- </button>
97
- } @else {
98
- <img
99
- class="dt-img"
100
- [class.dt-img--full]="!!col.options?.image?.showFull"
101
- [src]="getImageSrc(row, col)"
102
- [alt]="getImageAlt(row, col)"
103
- (click)="
104
- (col.options?.image?.openInModal ?? true) &&
105
- onOpenImage(getImageSrc(row, col), getImageAlt(row, col), $event)
106
- "
107
- />
108
- }
109
- }
110
-
111
- @case ('status') {
112
- <span class="dt-badge" [attr.data-variant]="getStatusClass(row, col)">
113
- {{ getDisplayText(row, col) }}
114
- </span>
115
- }
116
-
117
- @case ('link') {
118
- <a
119
- class="dt-link"
120
- [href]="getLinkHref(row, col)"
121
- [target]="col.options?.link?.target ?? '_blank'"
122
- (click)="$event.stopPropagation()"
123
- >
124
- {{ getLinkLabel(row, col) }}
125
- </a>
126
- }
127
-
128
- @case ('actions') {
129
- <div class="dt-actions">
130
- @for (action of getColumnActions(col); track action.id) {
131
- @if (isActionVisible(action, row)) {
132
- <button
133
- type="button"
134
- class="dt-action-btn"
135
- [class.dt-action--edit]="action.id === 'edit'"
136
- [class.dt-action--delete]="action.id === 'delete'"
137
- [class.dt-action--open]="action.id === 'open'"
138
- [class.dt-action--copy]="action.id === 'copy'"
139
- [disabled]="isActionDisabled(action, row)"
140
- [title]="action.tooltip ?? action.label"
141
- (click)="emitAction(action, row, $event)"
142
- >
143
- @if ((action.render ?? 'icon') === 'text') {
144
- <span class="dt-action-text">{{ action.label }}</span>
145
- } @else {
146
- <span
147
- class="dt-action-svg"
148
- [innerHTML]="getActionSvg(action)"
149
- ></span>
150
- }
151
- </button>
152
- }
153
- }
154
- </div>
155
- }
156
-
157
- @default {
158
- <span class="dt-text">{{ getDisplayText(row, col) }}</span>
159
- }
160
- }
161
- </div>
162
- }
163
- </div>
164
- }
165
- }
166
- </div>
167
- </div>
168
- </div>
@@ -1,224 +0,0 @@
1
- import { CommonModule } from '@angular/common';
2
- import { ChangeDetectionStrategy, Component, computed, inject, input, output } from '@angular/core';
3
- import {
4
- TableColumn,
5
- TableConfig,
6
- TableSortState,
7
- RowId,
8
- TableAction,
9
- TableActionEvent,
10
- SVG_ICONS
11
- } from '../../types/table.types';
12
- import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
13
- import { TimeZoneInfo, TIME_ZONES } from '../../types/time-zone.types';
14
-
15
- @Component({
16
- selector: 'table-grid',
17
- standalone: true,
18
- imports: [CommonModule],
19
- templateUrl: './table-grid.component.html',
20
- styleUrls: ['./table-grid.component.css'],
21
- changeDetection: ChangeDetectionStrategy.OnPush,
22
- })
23
- export class TableGridComponent<T extends Record<string, any>> {
24
- private sanitizer = inject(DomSanitizer);
25
-
26
- // Inputs
27
- readonly config = input<TableConfig>({});
28
- readonly columns = input<TableColumn<T>[]>([]);
29
- readonly rows = input<T[]>([]);
30
- readonly gridTemplateColumns = input<string>('');
31
- readonly columnQueries = input<Record<string, string>>({});
32
- readonly sortState = input<TableSortState | null>(null);
33
- readonly selectedIdsSet = input<Set<RowId>>(new Set<RowId>());
34
- readonly timeZone = input<TimeZoneInfo>(TIME_ZONES.MEXICO_CITY);
35
-
36
- // Outputs
37
- readonly headerSort = output<TableColumn<T>>();
38
- readonly columnQueryChange = output<{ key: string; value: string }>();
39
- readonly rowClick = output<T>();
40
- readonly toggleRow = output<T>();
41
- readonly toggleAllOnPage = output<void>();
42
- readonly openImage = output<{ src: string; alt: string }>();
43
- readonly actionClick = output<TableActionEvent<T>>();
44
- readonly bodyScroll = output<Event>();
45
-
46
- // Derived
47
- readonly showSelectionColumn = computed(() => !!this.config().selectable);
48
-
49
- // Helpers
50
- private getRowIdKey(): string {
51
- return this.config().rowIdKey ?? 'id';
52
- }
53
-
54
- getRowId(row: T): RowId {
55
- const getter = this.config().rowIdGetter;
56
- if (getter) return getter(row);
57
- const key = this.getRowIdKey();
58
- return row?.[key];
59
- }
60
-
61
- isSelected(row: T): boolean {
62
- return this.selectedIdsSet().has(this.getRowId(row));
63
- }
64
-
65
- isAllSelectedOnPage(): boolean {
66
- const rows = this.rows();
67
- if (!rows.length) return false;
68
- const set = this.selectedIdsSet();
69
- return rows.every((r) => set.has(this.getRowId(r)));
70
- }
71
-
72
- getSortIcon(colKey: string): string {
73
- const sorted = this.sortState();
74
- if (!sorted || sorted.key !== colKey) return '↕';
75
- return sorted.dir === 'asc' ? '↑' : '↓';
76
- }
77
-
78
- getDisplayText(row: T, column: TableColumn<T>): string {
79
- const value = this.getCellValue(row, column);
80
-
81
- if (column.formatter) {
82
- try {
83
- return column.formatter(value, row);
84
- } catch {
85
- return '';
86
- }
87
- }
88
-
89
- switch (column.type) {
90
- case 'string':
91
- return value == null ? '' : String(value);
92
-
93
- case 'integer':
94
- case 'decimal':
95
- case 'currency': {
96
- const currencyValue = Number(value);
97
- if (!Number.isFinite(currencyValue)) return value == null ? '' : String(value);
98
- if (column.type === 'currency') {
99
- try {
100
- return new Intl.NumberFormat(this.timeZone().locale, {
101
- style: 'currency',
102
- currency: column.options?.currency ?? this.timeZone().currency,
103
- maximumFractionDigits: 2,
104
- }).format(currencyValue);
105
- } catch {
106
- return String(currencyValue);
107
- }
108
- }
109
- return String(currencyValue);
110
- }
111
-
112
- case 'date':
113
- case 'datetime': {
114
- const dateTime = value instanceof Date ? value : new Date(String(value));
115
- if (Number.isNaN(dateTime.getTime())) return value == null ? '' : String(value);
116
-
117
- const locale = this.timeZone().locale;
118
- return column.type === 'datetime'
119
- ? dateTime.toLocaleString(locale)
120
- : dateTime.toLocaleDateString(locale);
121
- }
122
-
123
- case 'boolean':
124
- return value ? 'Sí' : 'No';
125
-
126
- default:
127
- return value == null ? '' : String(value);
128
- }
129
- }
130
-
131
- getImageSrc(row: T, col: TableColumn<T>): string {
132
- return this.getCellString(row, col);
133
- }
134
-
135
- getImageAlt(row: T, col: TableColumn<T>): string {
136
- const altFn = col.options?.image?.alt;
137
- return altFn ? altFn(row) : col.label;
138
- }
139
-
140
- getStatusClass(row: T, col: TableColumn<T>): string {
141
- const raw = this.getCellString(row, col);
142
- return col.options?.status?.classMap?.[raw] ?? '';
143
- }
144
-
145
- getLinkHref(row: T, col: TableColumn<T>): string {
146
- const getter = col.options?.link?.hrefGetter;
147
- return getter ? getter(row) : this.getCellString(row, col);
148
- }
149
-
150
- getLinkLabel(row: T, col: TableColumn<T>): string {
151
- const getter = col.options?.link?.labelGetter;
152
- if (getter) return getter(row);
153
- const cellValue = this.getCellValue(row, col);
154
- return cellValue == null ? '' : String(cellValue);
155
- }
156
-
157
- getColumnActions(col: TableColumn<T>): TableAction<T>[] {
158
- return col.actions ?? [];
159
- }
160
-
161
- isActionVisible(action: TableAction<T>, row: T): boolean {
162
- return action.visible ? action.visible(row) : true;
163
- }
164
-
165
- isActionDisabled(action: TableAction<T>, row: T): boolean {
166
- return action.disabled ? action.disabled(row) : false;
167
- }
168
-
169
- emitAction(action: TableAction<T>, row: T, event: Event) {
170
- event.stopPropagation();
171
- this.actionClick.emit({ actionId: action.id, row });
172
- }
173
-
174
- getActionSvg(action: TableAction<T>): SafeHtml | string {
175
- const key = (action.icon ?? action.id).toLowerCase();
176
- return this.sanitizer.bypassSecurityTrustHtml(SVG_ICONS[key] ?? '*');
177
- }
178
-
179
- onHeaderClickSort(column: TableColumn<T>) {
180
- if (!column.sortable) return;
181
- this.headerSort.emit(column);
182
- }
183
-
184
- onColumnQueryInput(key: string, value: string) {
185
- this.columnQueryChange.emit({ key, value });
186
- }
187
-
188
- onRowClick(row: T) {
189
- this.rowClick.emit(row);
190
- }
191
-
192
- onToggleRow(row: T) {
193
- this.toggleRow.emit(row);
194
- }
195
-
196
- onToggleAllOnPage() {
197
- this.toggleAllOnPage.emit();
198
- }
199
-
200
- onOpenImage(src: string, alt: string, event: Event) {
201
- event.stopPropagation();
202
- this.openImage.emit({ src, alt });
203
- }
204
-
205
- onBodyScroll(event: Event) {
206
- this.bodyScroll.emit(event);
207
- }
208
-
209
- private getCellValue(row: T, col: TableColumn<T>): unknown {
210
- if (col.valueGetter) {
211
- try {
212
- return col.valueGetter(row);
213
- } catch {
214
- return null;
215
- }
216
- }
217
- return row?.[col.key];
218
- }
219
-
220
- private getCellString(row: T, col: TableColumn<T>): string {
221
- const value = this.getCellValue(row, col);
222
- return value == null ? '' : String(value);
223
- }
224
- }
@@ -1,49 +0,0 @@
1
- .dt-modal-backdrop {
2
- position: fixed;
3
- inset: 0;
4
- background: rgba(0, 0, 0, 0.55);
5
- display: flex;
6
- justify-content: center;
7
- align-items: center;
8
- padding: 18px;
9
- z-index: 9999;
10
- }
11
-
12
- .dt-modal {
13
- width: min(900px, 95vw);
14
- max-height: 90vh;
15
- background: var(--white);
16
- border-radius: var(--radius-md);
17
- border: var(--border);
18
- overflow: hidden;
19
- display: flex;
20
- flex-direction: column;
21
- }
22
-
23
- .dt-modal-header {
24
- padding: 12px;
25
- border-bottom: var(--border);
26
- display: flex;
27
- justify-content: space-between;
28
- align-items: center;
29
- background: var(--gray-white);
30
- }
31
-
32
- .dt-modal-title {
33
- font-weight: 600;
34
- color: var(--black);
35
- overflow: hidden;
36
- text-overflow: ellipsis;
37
- white-space: nowrap;
38
- }
39
-
40
- .dt-modal-body {
41
- padding: 12px;
42
- overflow: auto;
43
- }
44
-
45
- .dt-modal-img {
46
- width: 100%;
47
- height: auto;
48
- border-radius: var(--radius-sm);
49
- }