b2b-tools 0.0.3 → 0.1.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.
Files changed (39) hide show
  1. package/LICENCE +21 -0
  2. package/README.md +120 -25
  3. package/ng-package.json +7 -0
  4. package/package.json +13 -24
  5. package/src/lib/b2b-tools.spec.ts +23 -0
  6. package/src/lib/b2b-tools.ts +15 -0
  7. package/src/lib/components/advanced-card/advanced-card.css +265 -0
  8. package/src/lib/components/advanced-card/advanced-card.html +117 -0
  9. package/src/lib/components/advanced-card/advanced-card.ts +75 -0
  10. package/src/lib/components/advanced-card/index.ts +2 -0
  11. package/src/lib/components/advanced-card/types/card.types.ts +37 -0
  12. package/src/lib/components/advanced-card/types/index.ts +1 -0
  13. package/src/lib/components/advanced-table/advanced-table.component.css +81 -0
  14. package/src/lib/components/advanced-table/advanced-table.component.html +56 -0
  15. package/src/lib/components/advanced-table/advanced-table.component.ts +469 -0
  16. package/src/lib/components/advanced-table/index.ts +2 -0
  17. package/src/lib/components/advanced-table/parts/table-grid/table-grid.component.css +274 -0
  18. package/src/lib/components/advanced-table/parts/table-grid/table-grid.component.html +168 -0
  19. package/src/lib/components/advanced-table/parts/table-grid/table-grid.component.ts +224 -0
  20. package/src/lib/components/advanced-table/parts/table-modal-image/table-modal-image.component.css +49 -0
  21. package/src/lib/components/advanced-table/parts/table-modal-image/table-modal-image.component.html +14 -0
  22. package/src/lib/components/advanced-table/parts/table-modal-image/table-modal-image.component.ts +22 -0
  23. package/src/lib/components/advanced-table/parts/table-pagination/table-pagination.component.css +147 -0
  24. package/src/lib/components/advanced-table/parts/table-pagination/table-pagination.component.html +95 -0
  25. package/src/lib/components/advanced-table/parts/table-pagination/table-pagination.component.ts +61 -0
  26. package/src/lib/components/advanced-table/parts/table-toolbar/table-toolbar.component.css +32 -0
  27. package/src/lib/components/advanced-table/parts/table-toolbar/table-toolbar.component.html +17 -0
  28. package/src/lib/components/advanced-table/parts/table-toolbar/table-toolbar.component.ts +30 -0
  29. package/src/lib/components/advanced-table/types/index.ts +2 -0
  30. package/src/lib/components/advanced-table/types/table.types.ts +101 -0
  31. package/src/lib/components/advanced-table/types/time-zone.types.ts +91 -0
  32. package/src/lib/components/index.ts +2 -0
  33. package/src/public-api.ts +4 -0
  34. package/tsconfig.lib.json +17 -0
  35. package/tsconfig.lib.prod.json +11 -0
  36. package/tsconfig.spec.json +15 -0
  37. package/fesm2022/b2b-tools.mjs +0 -761
  38. package/fesm2022/b2b-tools.mjs.map +0 -1
  39. package/types/b2b-tools.d.ts +0 -431
package/LICENCE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Luis Emiliano Cortes
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,4 +1,7 @@
1
- # 📦 b2b-tools
1
+ [![Angular](https://img.shields.io/badge/Angular-21-red?logo=angular)](https://angular.io/)
2
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
3
+ [![npm version](https://img.shields.io/npm/v/b2b-tools.svg)](https://www.npmjs.com/package/b2b-tools)
4
+ [![Build Status](https://img.shields.io/badge/build-passing-brightgreen)](#)
2
5
 
3
6
  `b2b-tools` is a reusable Angular 21 standalone component library
4
7
  designed to provide modular, scalable, and production-ready UI
@@ -6,54 +9,146 @@ components.
6
9
 
7
10
  ---
8
11
 
12
+ ## 🔗 Repository
13
+
14
+ The source code for this library is hosted on GitHub:
15
+
16
+ 👉 **https://github.com/LuisEmilianoCortes/b2b-tools**
17
+
18
+ ---
19
+
9
20
  ## 🏗️ Technology Stack
10
21
 
11
22
  - Angular 21
12
23
  - Standalone Components
13
- - CSS styling
14
24
  - Signals-based state management
15
- - Strict TypeScript configuration
25
+ - Strict TypeScript
26
+ - CSS variable theming
16
27
 
17
28
  ---
18
29
 
19
- ## 📥 Installation (After npm publication)
30
+ # 📚 Index
20
31
 
21
- ```bash
22
- npm install b2b-tools
23
- ```
32
+ - [Components](#-components)
33
+ - [AdvancedTableComponent](#-advancedtablecomponent)
34
+ - [AdvancedCardComponent](#-advancedcardcomponent)
35
+ - [Theming](#-theming)
36
+ - [Design Principles](#-design-principles)
37
+ - [Future Enhancements](#-future-enhancements)
38
+
39
+ ---
40
+
41
+ # 🧩 Components
42
+
43
+ The library currently provides the following core components:
24
44
 
25
- Then import components directly:
45
+ ---
46
+
47
+ ## 🔹 AdvancedTableComponent
48
+
49
+ A modular and extensible data table component designed for structured
50
+ data visualization.
51
+
52
+ ### Features
53
+
54
+ - Strongly typed column configuration
55
+ - Sorting support
56
+ - Pagination support
57
+ - Flexible cell rendering
58
+ - Standalone usage
59
+ - Domain-agnostic design
60
+
61
+ ### Basic Usage
26
62
 
27
63
  ```ts
28
64
  import { AdvancedTableComponent } from 'b2b-tools';
29
65
  ```
30
66
 
67
+ ```html
68
+ <advanced-table [columns]="columns" [rows]="rows"></advanced-table>
69
+ ```
70
+
31
71
  ---
32
72
 
33
- ## 🚀 Basic Usage Example
73
+ ## 🔹 AdvancedCardComponent
74
+
75
+ A highly configurable, domain-agnostic card component designed to
76
+ display summary information and expandable detailed content.
77
+
78
+ ### Features
79
+
80
+ - Compact and expanded modes
81
+ - Inline / Drawer / Modal expansion
82
+ - Highlight metrics
83
+ - Summary blocks
84
+ - Header actions
85
+ - Tab system
86
+ - Template projection
87
+ - CSS variable theming
88
+ - Signals-based internal state
89
+
90
+ ---
91
+
92
+ ### Basic Usage
34
93
 
35
94
  ```ts
36
- import { Component } from '@angular/core';
37
- import { AdvancedTableComponent } from 'b2b-tools';
95
+ import { AdvancedCardComponent } from 'b2b-tools';
96
+ ```
38
97
 
39
- @Component({
40
- standalone: true,
41
- imports: [AdvancedTableComponent],
42
- template: ` <b2b-advanced-table></b2b-advanced-table> `,
43
- })
44
- export class ExampleComponent {}
98
+ ```html
99
+ <advanced-card
100
+ [config]="cardConfig"
101
+ (action)="onHeaderAction($event)"
102
+ (tabChanged)="onTabChanged($event)"
103
+ (tabAction)="onTabAction($event)"
104
+ >
105
+ <ng-template advancedCardTemplate="example" let-cardId="cardId" let-tabId="tabId">
106
+ <div>Example content for {{ cardId }} (tab: {{ tabId }})</div>
107
+ </ng-template>
108
+ </advanced-card>
45
109
  ```
46
110
 
47
111
  ---
48
112
 
49
- ## 🧩 Available Components
113
+ # 🎨 Theming
50
114
 
51
- ### AdvancedTableComponent
115
+ Both components support CSS variables for styling customization.
52
116
 
53
- A modular and extensible data table component supporting:
117
+ Example:
54
118
 
55
- - Configurable columns
56
- - Sorting
57
- - Pagination
58
- - Strong typing
59
- - Standalone usage
119
+ ```html
120
+ <advanced-card
121
+ [config]="cardConfig"
122
+ style="--ac-primary: #f58026; --ac-radius: 18px; --ac-overlay: rgba(0,0,0,.55)"
123
+ ></advanced-card>
124
+ ```
125
+
126
+ Common tokens:
127
+
128
+ - --ac-primary
129
+ - --ac-radius
130
+ - --ac-overlay
131
+ - --ac-surface
132
+ - --ac-border
133
+ - --ac-text
134
+
135
+ ---
136
+
137
+ # 📐 Design Principles
138
+
139
+ - Domain-agnostic
140
+ - Strongly typed configuration
141
+ - Projection-based extensibility
142
+ - Composable architecture
143
+ - Enterprise-ready scalability
144
+ - Minimal coupling
145
+
146
+ ---
147
+
148
+ # 🔮 Future Enhancements
149
+
150
+ - Animation support
151
+ - Accessibility improvements
152
+ - Storybook documentation
153
+ - Public API documentation
154
+ - Context generics support
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/b2b-tools",
4
+ "lib": {
5
+ "entryFile": "src/public-api.ts"
6
+ }
7
+ }
package/package.json CHANGED
@@ -1,24 +1,13 @@
1
- {
2
- "name": "b2b-tools",
3
- "version": "0.0.3",
4
- "license": "MIT",
5
- "peerDependencies": {
6
- "@angular/common": "^21.1.0",
7
- "@angular/core": "^21.1.0"
8
- },
9
- "dependencies": {
10
- "tslib": "^2.3.0"
11
- },
12
- "sideEffects": false,
13
- "module": "fesm2022/b2b-tools.mjs",
14
- "typings": "types/b2b-tools.d.ts",
15
- "exports": {
16
- "./package.json": {
17
- "default": "./package.json"
18
- },
19
- ".": {
20
- "types": "./types/b2b-tools.d.ts",
21
- "default": "./fesm2022/b2b-tools.mjs"
22
- }
23
- }
24
- }
1
+ {
2
+ "name": "b2b-tools",
3
+ "version": "0.1.1",
4
+ "license": "MIT",
5
+ "peerDependencies": {
6
+ "@angular/common": "^21.1.0",
7
+ "@angular/core": "^21.1.0"
8
+ },
9
+ "dependencies": {
10
+ "tslib": "^2.3.0"
11
+ },
12
+ "sideEffects": false
13
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { B2bTools } from './b2b-tools';
4
+
5
+ describe('B2bTools', () => {
6
+ let component: B2bTools;
7
+ let fixture: ComponentFixture<B2bTools>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [B2bTools]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(B2bTools);
16
+ component = fixture.componentInstance;
17
+ await fixture.whenStable();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,15 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'lib-b2b-tools',
5
+ imports: [],
6
+ template: `
7
+ <p>
8
+ b2b-tools works!
9
+ </p>
10
+ `,
11
+ styles: ``,
12
+ })
13
+ export class B2bTools {
14
+
15
+ }
@@ -0,0 +1,265 @@
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
+ }
@@ -0,0 +1,117 @@
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>