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,265 +0,0 @@
1
- :host {
2
- display: block;
3
- }
4
-
5
- .ac {
6
- border: 1px solid #e5e7eb;
7
- border-radius: 12px;
8
- background: #fff;
9
- box-shadow: 0 6px 18px rgba(17, 24, 39, 0.06);
10
- }
11
-
12
- .ac--hidden {
13
- display: none;
14
- }
15
-
16
- /* Compact */
17
- .ac--compact {
18
- padding: 14px 14px 12px;
19
- cursor: pointer;
20
- transition:
21
- transform 0.12s ease,
22
- box-shadow 0.12s ease;
23
- }
24
- .ac--compact:hover {
25
- transform: translateY(-1px);
26
- box-shadow: 0 10px 24px rgba(17, 24, 39, 0.1);
27
- }
28
-
29
- .ac__header {
30
- display: flex;
31
- align-items: flex-start;
32
- justify-content: space-between;
33
- gap: 12px;
34
- }
35
- .ac__title {
36
- margin: 0;
37
- font-size: 18px;
38
- font-weight: 700;
39
- color: #111827;
40
- }
41
- .ac__subtitle {
42
- margin: 2px 0 0;
43
- font-size: 13px;
44
- color: #6b7280;
45
- }
46
-
47
- .ac__highlights {
48
- display: grid;
49
- grid-template-columns: repeat(3, minmax(0, 1fr));
50
- gap: 10px;
51
- margin-top: 12px;
52
- }
53
- .ac__hl {
54
- border-top: 1px solid #f3f4f6;
55
- padding-top: 10px;
56
- }
57
- .ac__hl-value {
58
- font-size: 18px;
59
- font-weight: 700;
60
- color: #111827;
61
- }
62
- .ac__hl-label {
63
- font-size: 12px;
64
- color: #6b7280;
65
- }
66
- .ac__hl-hint {
67
- color: #9ca3af;
68
- }
69
-
70
- .ac__footer {
71
- margin-top: 12px;
72
- display: flex;
73
- justify-content: flex-end;
74
- }
75
-
76
- /* Expanded */
77
- .ac--expanded {
78
- overflow: hidden;
79
- }
80
- .ac--full {
81
- width: 100%;
82
- }
83
-
84
- .acx__header {
85
- display: flex;
86
- align-items: center;
87
- justify-content: space-between;
88
- gap: 12px;
89
- padding: 12px 14px;
90
- border-bottom: 1px solid #eef2f7;
91
- background: #fff;
92
- }
93
- .acx__header--sticky {
94
- position: sticky;
95
- top: 0;
96
- z-index: 5;
97
- }
98
-
99
- .acx__title {
100
- display: flex;
101
- align-items: center;
102
- gap: 10px;
103
- }
104
- .acx__title-text {
105
- margin: 0;
106
- font-size: 18px;
107
- font-weight: 800;
108
- color: #111827;
109
- }
110
-
111
- .acx__actions {
112
- display: flex;
113
- align-items: center;
114
- gap: 8px;
115
- flex-wrap: wrap;
116
- }
117
-
118
- .acx__body {
119
- padding: 14px;
120
- display: grid;
121
- gap: 12px;
122
- }
123
-
124
- .acx__summary {
125
- display: grid;
126
- grid-template-columns: repeat(4, minmax(0, 1fr));
127
- gap: 10px;
128
- }
129
-
130
- .block {
131
- border: 1px solid #eef2f7;
132
- border-radius: 10px;
133
- padding: 10px;
134
- background: #fafafa;
135
- }
136
- .block__title {
137
- font-size: 13px;
138
- font-weight: 700;
139
- color: #111827;
140
- margin-bottom: 8px;
141
- }
142
- .block__row {
143
- display: flex;
144
- justify-content: space-between;
145
- gap: 10px;
146
- padding: 4px 0;
147
- }
148
- .block__label {
149
- font-size: 12px;
150
- color: #6b7280;
151
- }
152
- .block__value {
153
- font-size: 12px;
154
- font-weight: 700;
155
- color: #111827;
156
- }
157
-
158
- .acx__content {
159
- border: 1px solid #eef2f7;
160
- border-radius: 12px;
161
- padding: 12px;
162
- background: #fff;
163
- min-height: 160px;
164
- }
165
- .acx__content-title {
166
- font-size: 13px;
167
- font-weight: 800;
168
- color: #111827;
169
- margin-bottom: 10px;
170
- }
171
-
172
- .badge {
173
- font-size: 12px;
174
- padding: 3px 10px;
175
- border-radius: 999px;
176
- border: 1px solid transparent;
177
- font-weight: 700;
178
- white-space: nowrap;
179
- }
180
- .badge--success {
181
- background: #e8f7f2;
182
- color: #0f766e;
183
- border-color: #b7f0df;
184
- }
185
- .badge--warning {
186
- background: #fff7ed;
187
- color: #b45309;
188
- border-color: #fed7aa;
189
- }
190
- .badge--danger {
191
- background: #fef2f2;
192
- color: #b91c1c;
193
- border-color: #fecaca;
194
- }
195
- .badge--primary {
196
- background: #eff6ff;
197
- color: #1d4ed8;
198
- border-color: #bfdbfe;
199
- }
200
- .badge--neutral {
201
- background: #f3f4f6;
202
- color: #374151;
203
- border-color: #e5e7eb;
204
- }
205
-
206
- .btn {
207
- border: 1px solid #d1d5db;
208
- background: #fff;
209
- color: #111827;
210
- padding: 8px 12px;
211
- border-radius: 10px;
212
- font-weight: 700;
213
- cursor: pointer;
214
- }
215
- .btn--primary {
216
- border-color: #1d4ed8;
217
- background: #1d4ed8;
218
- color: #fff;
219
- }
220
- .btn--secondary {
221
- background: #fff;
222
- }
223
- .btn--danger {
224
- border-color: #dc2626;
225
- background: #dc2626;
226
- color: #fff;
227
- }
228
- .btn:disabled {
229
- opacity: 0.55;
230
- cursor: not-allowed;
231
- }
232
-
233
- .btn__chev {
234
- margin-left: 8px;
235
- font-size: 16px;
236
- line-height: 0;
237
- }
238
-
239
- .icon-btn {
240
- border: 1px solid #e5e7eb;
241
- background: #fff;
242
- width: 36px;
243
- height: 36px;
244
- border-radius: 10px;
245
- cursor: pointer;
246
- font-weight: 900;
247
- }
248
-
249
- /* Responsive */
250
- @media (max-width: 1100px) {
251
- .acx__summary {
252
- grid-template-columns: repeat(2, minmax(0, 1fr));
253
- }
254
- .ac__highlights {
255
- grid-template-columns: repeat(2, minmax(0, 1fr));
256
- }
257
- }
258
- @media (max-width: 640px) {
259
- .ac__highlights {
260
- grid-template-columns: 1fr;
261
- }
262
- .acx__actions {
263
- justify-content: flex-end;
264
- }
265
- }
@@ -1,117 +0,0 @@
1
- <!-- COMPACT -->
2
- <section
3
- class="ac ac--compact"
4
- [class.ac--hidden]="expanded()"
5
- tabindex="0"
6
- role="button"
7
- (click)="expand()"
8
- (keydown.enter)="expand()"
9
- >
10
- <header class="ac__header">
11
- <div class="ac__title-wrap">
12
- <h3 class="ac__title">{{ config().title }}</h3>
13
- @if (config().subtitle) {
14
- <p class="ac__subtitle">{{ config().subtitle }}</p>
15
- }
16
- </div>
17
-
18
- @if (config().badge) {
19
- <span [class]="badgeClass(config().badge?.tone)">
20
- {{ config().badge?.label }}
21
- </span>
22
- }
23
- </header>
24
-
25
- @if (hasHighlights()) {
26
- <div class="ac__highlights">
27
- @for (highlight of config().highlights; track $index) {
28
- <div class="ac__hl">
29
- <div class="ac__hl-value">{{ highlight.value }}</div>
30
- <div class="ac__hl-label">
31
- {{ highlight.label }}
32
- @if (highlight.hint) {
33
- <span class="ac__hl-hint">· {{ highlight.hint }}</span>
34
- }
35
- </div>
36
- </div>
37
- }
38
- </div>
39
- }
40
-
41
- <footer class="ac__footer">
42
- <button type="button" class="btn btn--primary" (click)="expand(); $event.stopPropagation()">
43
- {{ config().primaryCta?.label ?? 'Ver detalle' }}
44
- <span class="btn__chev">›</span>
45
- </button>
46
- </footer>
47
- </section>
48
-
49
- <!-- EXPANDED (FULL WIDTH ROW) -->
50
- <section
51
- class="ac ac--expanded"
52
- [class.ac--full]="fullWidthOnExpand()"
53
- [class.ac--hidden]="!expanded()"
54
- aria-expanded="true"
55
- >
56
- <!-- Sticky header -->
57
- <header class="acx__header" [class.acx__header--sticky]="stickyHeader()">
58
- <div class="acx__title">
59
- <h3 class="acx__title-text">{{ config().title }}</h3>
60
- @if (config().badge) {
61
- <span [class]="badgeClass(config().badge?.tone)">
62
- {{ config().badge?.label }}
63
- </span>
64
- }
65
- </div>
66
-
67
- <div class="acx__actions">
68
- @for (action of config().actions; track action) {
69
- <button
70
- type="button"
71
- class="btn"
72
- [class.btn--primary]="action.tone === 'primary'"
73
- [class.btn--danger]="action.tone === 'danger'"
74
- [class.btn--secondary]="!action.tone || action.tone === 'secondary'"
75
- [disabled]="action.disabled"
76
- (click)="onActionClick(action)"
77
- >
78
- {{ action.label }}
79
- </button>
80
- }
81
-
82
- <button type="button" class="icon-btn" (click)="collapse()" aria-label="Cerrar">✕</button>
83
- </div>
84
- </header>
85
-
86
- <div class="acx__body">
87
- <!-- Summary blocks row -->
88
- @if (hasSummaryBlocks()) {
89
- <div class="acx__summary">
90
- @for (summaryBlock of config().summaryBlocks; track summaryBlock) {
91
- <div class="block">
92
- <div class="block__title">{{ summaryBlock.title }}</div>
93
- @for (row of summaryBlock.rows; track $index) {
94
- <div class="block__row">
95
- <span class="block__label">{{ row.label }}</span>
96
- <span class="block__value">{{ row.value }}</span>
97
- </div>
98
- }
99
- </div>
100
- }
101
- </div>
102
- }
103
-
104
- <!-- Placeholder “tabs/content area” (Fase 2 lo convertimos en tabs reales) -->
105
- <div class="acx__content">
106
- <div class="acx__content-title">Detalle</div>
107
-
108
- <!-- Slot genérico para que metas tablas / cualquier cosa -->
109
- <ng-content></ng-content>
110
-
111
- <!-- Si no mandas contenido, muestra empty state -->
112
- @if (false) {
113
- <div class="empty">Sin contenido.</div>
114
- }
115
- </div>
116
- </div>
117
- </section>
@@ -1,75 +0,0 @@
1
- import { Component, computed, effect, HostListener, input, output, signal } from '@angular/core';
2
- import { AdvancedAction, AdvancedCardConfig, AdvancedTone } from './types';
3
-
4
- @Component({
5
- selector: 'advanced-card',
6
- imports: [],
7
- templateUrl: './advanced-card.html',
8
- styleUrl: './advanced-card.css',
9
- })
10
- export class AdvancedCard {
11
- // Inputs (signals)
12
- config = input.required<AdvancedCardConfig>();
13
-
14
- // Controls (Fase 1)
15
- fullWidthOnExpand = input(true);
16
- stickyHeader = input(true);
17
- closeOnEsc = input(true);
18
-
19
- // Outputs
20
- expandedChange = output<boolean>();
21
- action = output<{ actionId: string; cardId: string }>();
22
-
23
- // State (signals)
24
- readonly expanded = signal(false);
25
-
26
- // Computeds
27
- readonly cardId = computed(() => this.config().id);
28
- readonly hasHighlights = computed(() => (this.config().highlights?.length ?? 0) > 0);
29
- readonly hasSummaryBlocks = computed(() => (this.config().summaryBlocks?.length ?? 0) > 0);
30
-
31
- constructor() {
32
- effect(() => {
33
- // Notifica al exterior
34
- this.expandedChange.emit(this.expanded());
35
- });
36
- }
37
-
38
- toggleExpand(): void {
39
- this.expanded.update((v) => !v);
40
- }
41
-
42
- expand(): void {
43
- if (!this.expanded()) this.expanded.set(true);
44
- }
45
-
46
- collapse(): void {
47
- if (this.expanded()) this.expanded.set(false);
48
- }
49
-
50
- onActionClick(a: AdvancedAction): void {
51
- if (a.disabled) return;
52
- this.action.emit({ actionId: a.id, cardId: this.cardId() });
53
- }
54
-
55
- badgeClass(tone: AdvancedTone | undefined): string {
56
- switch (tone) {
57
- case 'success':
58
- return 'badge badge--success';
59
- case 'warning':
60
- return 'badge badge--warning';
61
- case 'danger':
62
- return 'badge badge--danger';
63
- case 'primary':
64
- return 'badge badge--primary';
65
- default:
66
- return 'badge badge--neutral';
67
- }
68
- }
69
-
70
- @HostListener('document:keydown', ['$event'])
71
- onKeydown(ev: KeyboardEvent): void {
72
- if (!this.closeOnEsc()) return;
73
- if (ev.key === 'Escape') this.collapse();
74
- }
75
- }
@@ -1,2 +0,0 @@
1
- export * from './advanced-card';
2
- export * from './types';
@@ -1,37 +0,0 @@
1
- export type AdvancedTone = 'primary' | 'success' | 'warning' | 'danger' | 'neutral';
2
-
3
- export interface AdvancedBadge {
4
- label: string;
5
- tone?: AdvancedTone;
6
- }
7
-
8
- export interface AdvancedHighlight {
9
- label: string;
10
- value: string;
11
- hint?: string;
12
- }
13
-
14
- export interface AdvancedAction {
15
- id: string;
16
- label: string;
17
- tone?: 'primary' | 'secondary' | 'danger';
18
- disabled?: boolean;
19
- }
20
-
21
- export interface AdvancedCardConfig {
22
- id: string;
23
- title: string;
24
- subtitle?: string;
25
- badge?: AdvancedBadge;
26
-
27
- highlights?: AdvancedHighlight[]; // compact key info
28
- summaryBlocks?: AdvancedSummaryBlock[]; // expanded top row blocks
29
-
30
- primaryCta?: { label: string }; // compact CTA
31
- actions?: AdvancedAction[]; // expanded header actions
32
- }
33
-
34
- export interface AdvancedSummaryBlock {
35
- title: string;
36
- rows: { label: string; value: string }[];
37
- }
@@ -1 +0,0 @@
1
- export * from './card.types';
@@ -1,81 +0,0 @@
1
- :host {
2
- display: block;
3
- font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
4
-
5
- --black: #171717;
6
- --black-light: #343434;
7
- --black-dark: #000000;
8
- --black-navy: #191a21;
9
-
10
- --xs-dark-gray: #5A5A5A;
11
- --dark-gray: #9E9E9E;
12
- --medium-gray: #D5D5D5;
13
- --gray: #F8F8F8;
14
- --light-gray: #C6C6C6;
15
- --xs-light-gray: #DFDFDF;
16
- --gray-white: #F5F4F4;
17
- --xxs-light-gray: #F2F2F2;
18
- --soft-white: #EEEEEE;
19
-
20
- --green-success: #208B6A;
21
-
22
- --blue: #3360fa;
23
- --blue-info: #7390EC;
24
-
25
- --orange: #F77C00;
26
- --yellow-warning: #FFBC57;
27
-
28
- --red: #E60018;
29
-
30
- --white: #FFFFFF;
31
-
32
- --disabled: #C6C6C6;
33
- --disabled-text: #9E9E9E;
34
-
35
- --radius-sm: 4px;
36
- --radius-md: 6px;
37
- --border: 1px solid var(--xs-light-gray);
38
- --focus-ring: 0 0 0 3px rgba(51, 96, 250, 0.18);
39
- }
40
-
41
- .dt-container {
42
- border: var(--border);
43
- border-radius: var(--radius-md);
44
- background: var(--white);
45
- overflow: hidden;
46
- }
47
-
48
- .dt-toolbar {
49
- display: flex;
50
- justify-content: space-between;
51
- align-items: center;
52
- gap: 12px;
53
- /* padding: 12px; */
54
- border-bottom: var(--border);
55
- background: var(--xxs-light-gray);
56
- }
57
-
58
- .dt-empty {
59
- padding: 18px 12px;
60
- color: var(--xs-dark-gray);
61
- }
62
-
63
- @media (max-width: 900px) {
64
- .dt-toolbar {
65
- flex-wrap: wrap;
66
- align-items: flex-start;
67
- row-gap: 10px;
68
- padding: 10px 12px;
69
- }
70
-
71
- .dt-toolbar > b2b-table-toolbar {
72
- flex: 1 1 100%;
73
- }
74
-
75
- .dt-toolbar > b2b-table-pagination {
76
- flex: 1 1 100%;
77
- display: flex;
78
- justify-content: center;
79
- }
80
- }
81
-
@@ -1,56 +0,0 @@
1
- <div class="dt-container">
2
- <div class="dt-toolbar">
3
- <!-- Search and Clean -->
4
- <table-toolbar
5
- [enabled]="config().globalSearch ?? true"
6
- [query]="globalQuery()"
7
- placeholder="Buscar..."
8
- [showClear]="true"
9
- (queryChange)="setGlobalQuery($event)"
10
- (clear)="clearFilters()"
11
- />
12
-
13
- <!-- Pagination -->
14
- @if (config().pagination?.enabled) {
15
- <table-pagination
16
- [page]="page()"
17
- [pageSize]="pageSize()"
18
- [pageCount]="pageCount()"
19
- [totalCount]="totalCount()"
20
- [pagerItems]="pagerItems()"
21
- [pageSizeOptions]="config().pagination!.pageSizeOptions ?? [10, 25, 50]"
22
- (pageChange)="goToPage($event)"
23
- (pageSizeChange)="onPageSizeChange($event)"
24
- />
25
- }
26
- </div>
27
-
28
- <div class="dt-grid">
29
- <!-- Data Table -->
30
- <table-grid
31
- [config]="config()"
32
- [columns]="visibleColumns()"
33
- [rows]="pagedData()"
34
- [gridTemplateColumns]="gridTemplateColumns()"
35
- [columnQueries]="columnQueries()"
36
- [sortState]="sortState()"
37
- [selectedIdsSet]="selectedIdsSet()"
38
- (headerSort)="onHeaderClickSort($event)"
39
- (columnQueryChange)="setColumnQuery($event.key, $event.value)"
40
- (rowClick)="onRowClick($event)"
41
- (toggleRow)="toggleRowSelection($event)"
42
- (toggleAllOnPage)="toggleSelectAllOnPage()"
43
- (openImage)="openImageModal($event.src, $event.alt)"
44
- (actionClick)="actionClick.emit($event)"
45
- (bodyScroll)="onBodyScroll($event)"
46
- />
47
- </div>
48
-
49
- <!-- Image Modal -->
50
- <table-modal-image
51
- [open]="modalOpen()"
52
- [src]="modalImageSrc()"
53
- [alt]="modalImageAlt()"
54
- (close)="closeModal()"
55
- />
56
- </div>