@farm-investimentos/front-mfe-components 15.13.0 → 15.13.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.
- package/dist/front-mfe-components.common.js +176 -121
- package/dist/front-mfe-components.common.js.map +1 -1
- package/dist/front-mfe-components.css +1 -1
- package/dist/front-mfe-components.umd.js +176 -121
- package/dist/front-mfe-components.umd.js.map +1 -1
- package/dist/front-mfe-components.umd.min.js +1 -1
- package/dist/front-mfe-components.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/GanttChart/GanttChart.scss +24 -47
- package/src/components/GanttChart/GanttChart.vue +71 -26
- package/src/components/GanttChart/composition/buildBarPositioning.ts +0 -1
- package/src/components/GanttChart/types/index.ts +7 -6
package/package.json
CHANGED
|
@@ -6,16 +6,15 @@
|
|
|
6
6
|
|
|
7
7
|
.farm-gantt-chart {
|
|
8
8
|
width: 100%;
|
|
9
|
-
height: 100%;
|
|
10
9
|
min-height: 500px;
|
|
11
10
|
position: relative;
|
|
12
11
|
overflow-x: auto;
|
|
13
|
-
overflow-y:
|
|
12
|
+
overflow-y: visible;
|
|
14
13
|
|
|
15
14
|
&__header {
|
|
16
15
|
display: flex;
|
|
17
|
-
width: fit-content;
|
|
18
|
-
min-width: 100%;
|
|
16
|
+
width: fit-content;
|
|
17
|
+
min-width: 100%;
|
|
19
18
|
margin-bottom: gutter('sm');
|
|
20
19
|
position: relative;
|
|
21
20
|
z-index: 2;
|
|
@@ -37,14 +36,14 @@
|
|
|
37
36
|
&__month-header {
|
|
38
37
|
display: flex;
|
|
39
38
|
align-items: center;
|
|
40
|
-
justify-content: flex-start;
|
|
39
|
+
justify-content: flex-start;
|
|
41
40
|
padding-right: 8px;
|
|
42
41
|
height: fit-content;
|
|
43
42
|
position: relative;
|
|
44
|
-
min-width: 0;
|
|
43
|
+
min-width: 0;
|
|
45
44
|
|
|
46
45
|
.farm-typography {
|
|
47
|
-
white-space: nowrap;
|
|
46
|
+
white-space: nowrap;
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
&::after {
|
|
@@ -68,11 +67,10 @@
|
|
|
68
67
|
|
|
69
68
|
&__content {
|
|
70
69
|
position: relative;
|
|
71
|
-
width: fit-content;
|
|
72
|
-
min-width: 100%;
|
|
70
|
+
width: fit-content;
|
|
71
|
+
min-width: 100%;
|
|
73
72
|
display: flex;
|
|
74
73
|
flex-direction: column;
|
|
75
|
-
/* overflow: hidden; // Remove this to allow content to scroll with parent */
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
&__group {
|
|
@@ -130,22 +128,6 @@
|
|
|
130
128
|
transform: translateY(-2px);
|
|
131
129
|
}
|
|
132
130
|
|
|
133
|
-
// Bar types using library theme colors blended with white (matching Figma approach)
|
|
134
|
-
&--campaign {
|
|
135
|
-
background-color: #7BC4F7; // Info blended with white (73% + 27% white) - Vigência da Campanha
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
&--product {
|
|
139
|
-
background-color: #8BB455; // Primary blended with white (73% + 27% white) - Vigência do Produto Comercial
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
&--disbursement {
|
|
143
|
-
background-color: #FFB84D; // Warning blended with white (73% + 27% white) - Período de Desembolso
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
&--maturity {
|
|
147
|
-
background-color: #F7857F; // Error blended with white (73% + 27% white) - Intervalo Vencimento
|
|
148
|
-
}
|
|
149
131
|
}
|
|
150
132
|
|
|
151
133
|
&__legend {
|
|
@@ -169,8 +151,8 @@
|
|
|
169
151
|
margin-bottom: gutter('xs');
|
|
170
152
|
position: relative;
|
|
171
153
|
padding: 0 12px;
|
|
172
|
-
flex-shrink: 0;
|
|
173
|
-
white-space: nowrap;
|
|
154
|
+
flex-shrink: 0;
|
|
155
|
+
white-space: nowrap;
|
|
174
156
|
|
|
175
157
|
&:not(:last-child)::after {
|
|
176
158
|
content: '';
|
|
@@ -197,7 +179,6 @@
|
|
|
197
179
|
align-items: center;
|
|
198
180
|
}
|
|
199
181
|
|
|
200
|
-
// NEW: Tooltip container styles - specific to GanttChart positioning
|
|
201
182
|
&__tooltip-container {
|
|
202
183
|
position: absolute;
|
|
203
184
|
z-index: 999;
|
|
@@ -207,40 +188,36 @@
|
|
|
207
188
|
}
|
|
208
189
|
|
|
209
190
|
&__tooltip {
|
|
210
|
-
// Reutiliza estilos base do farm-tooltip__popup mas com customizações específicas
|
|
211
191
|
@extend .farm-tooltip__popup;
|
|
212
192
|
@extend .farm-tooltip__popup--visible;
|
|
213
193
|
@extend .farm-tooltip__popup--fluid;
|
|
214
|
-
|
|
215
|
-
// Customizações específicas para GanttChart
|
|
194
|
+
|
|
216
195
|
pointer-events: auto;
|
|
217
196
|
position: relative;
|
|
218
|
-
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
197
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
198
|
+
|
|
199
|
+
width: auto !important;
|
|
200
|
+
max-width: 400px !important;
|
|
201
|
+
|
|
202
|
+
.farm-tooltip__content {
|
|
203
|
+
white-space: nowrap;
|
|
204
|
+
}
|
|
219
205
|
|
|
220
|
-
// NEW: Structured tooltip data styling - específico para dados estruturados
|
|
221
206
|
.tooltip-data-row {
|
|
222
207
|
display: flex;
|
|
223
|
-
justify-content:
|
|
208
|
+
justify-content: flex-start;
|
|
224
209
|
align-items: center;
|
|
225
210
|
margin-bottom: 4px;
|
|
226
|
-
|
|
211
|
+
|
|
227
212
|
&:last-child {
|
|
228
213
|
margin-bottom: 0;
|
|
229
214
|
}
|
|
230
215
|
}
|
|
231
|
-
|
|
232
|
-
.tooltip-
|
|
216
|
+
|
|
217
|
+
.tooltip-text {
|
|
233
218
|
font-weight: 500;
|
|
234
|
-
margin-right: 8px;
|
|
235
|
-
color: #f5f5f5;
|
|
236
|
-
opacity: 0.9;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
.tooltip-value {
|
|
240
|
-
font-weight: 600;
|
|
241
219
|
color: #ffffff;
|
|
242
|
-
|
|
243
|
-
flex-shrink: 0;
|
|
220
|
+
white-space: nowrap;
|
|
244
221
|
}
|
|
245
222
|
}
|
|
246
223
|
}
|
|
@@ -29,7 +29,10 @@
|
|
|
29
29
|
class="farm-gantt-chart__group"
|
|
30
30
|
>
|
|
31
31
|
<div class="farm-gantt-chart__group-label">
|
|
32
|
-
<farm-typography :weight="
|
|
32
|
+
<farm-typography v-if="group.subtitle" size="md" :weight="600" color="black" color-variation="50" class="mb-1">
|
|
33
|
+
{{ group.subtitle }}
|
|
34
|
+
</farm-typography>
|
|
35
|
+
<farm-typography size ="md" :weight="500" color="black" color-variation="50">
|
|
33
36
|
{{ group.title }}
|
|
34
37
|
</farm-typography>
|
|
35
38
|
</div>
|
|
@@ -50,7 +53,7 @@
|
|
|
50
53
|
</div>
|
|
51
54
|
</div>
|
|
52
55
|
</div>
|
|
53
|
-
|
|
56
|
+
|
|
54
57
|
</div>
|
|
55
58
|
|
|
56
59
|
<div class="farm-gantt-chart__legend" v-if="autoGeneratedLegend.length > 0" :style="legendStyle">
|
|
@@ -80,6 +83,7 @@
|
|
|
80
83
|
v-if="tooltipState.visible"
|
|
81
84
|
class="farm-gantt-chart__tooltip-container"
|
|
82
85
|
:style="tooltipPositionStyle"
|
|
86
|
+
ref="tooltipElement"
|
|
83
87
|
>
|
|
84
88
|
<div v-if="$slots.tooltip" class="farm-gantt-chart__tooltip">
|
|
85
89
|
<slot
|
|
@@ -88,7 +92,7 @@
|
|
|
88
92
|
:tooltipData="tooltipState.barData && tooltipState.barData.tooltipData"
|
|
89
93
|
/>
|
|
90
94
|
</div>
|
|
91
|
-
|
|
95
|
+
|
|
92
96
|
<div
|
|
93
97
|
v-else-if="tooltipState.barData && tooltipState.barData.tooltipData"
|
|
94
98
|
class="farm-gantt-chart__tooltip farm-tooltip__popup farm-tooltip__popup--visible"
|
|
@@ -109,7 +113,7 @@
|
|
|
109
113
|
</div>
|
|
110
114
|
</div>
|
|
111
115
|
</div>
|
|
112
|
-
|
|
116
|
+
|
|
113
117
|
<div
|
|
114
118
|
v-else
|
|
115
119
|
class="farm-gantt-chart__tooltip farm-tooltip__popup farm-tooltip__popup--visible"
|
|
@@ -128,7 +132,7 @@
|
|
|
128
132
|
</template>
|
|
129
133
|
|
|
130
134
|
<script lang="ts">
|
|
131
|
-
import { defineComponent, PropType, computed, reactive, ref } from 'vue';
|
|
135
|
+
import { defineComponent, PropType, computed, reactive, ref, onMounted, onUnmounted, nextTick } from 'vue';
|
|
132
136
|
import type { GanttData, TooltipState, GanttBar } from './types';
|
|
133
137
|
import { getMonthsBetween, formatMonth, isCurrentMonth, getColumnForDate, formatDateRange } from './utils/dateUtils';
|
|
134
138
|
import { buildGanttData, buildBarPositioning } from './composition';
|
|
@@ -144,21 +148,21 @@ export default defineComponent({
|
|
|
144
148
|
console.warn('GanttChart: prop "data" deve ser um objeto.');
|
|
145
149
|
return false;
|
|
146
150
|
}
|
|
147
|
-
|
|
151
|
+
|
|
148
152
|
if (!Array.isArray(value.groups)) {
|
|
149
153
|
console.warn('GanttChart: prop "data.groups" deve ser um array.');
|
|
150
154
|
return false;
|
|
151
155
|
}
|
|
152
|
-
|
|
156
|
+
|
|
153
157
|
return value.groups.every((group: any) => {
|
|
154
158
|
const hasValidTitle = typeof group.title === 'string';
|
|
155
159
|
const hasValidBars = Array.isArray(group.bars);
|
|
156
|
-
|
|
160
|
+
|
|
157
161
|
if (!hasValidTitle || !hasValidBars) {
|
|
158
162
|
console.warn('GanttChart: cada grupo deve ter título (string) e barras (array).');
|
|
159
163
|
return false;
|
|
160
164
|
}
|
|
161
|
-
|
|
165
|
+
|
|
162
166
|
return true;
|
|
163
167
|
});
|
|
164
168
|
}
|
|
@@ -229,11 +233,17 @@ export default defineComponent({
|
|
|
229
233
|
};
|
|
230
234
|
});
|
|
231
235
|
|
|
236
|
+
const tooltipElement = ref<HTMLElement>();
|
|
237
|
+
const lastMousePosition = ref<{ eventX: number; eventY: number } | null>(null);
|
|
238
|
+
|
|
232
239
|
const onBarMouseEnter = (bar: GanttBar, event: MouseEvent) => {
|
|
233
240
|
tooltipState.visible = true;
|
|
234
|
-
tooltipState.title = bar.label;
|
|
241
|
+
tooltipState.title = bar.tooltipTitle || bar.label;
|
|
235
242
|
tooltipState.barData = bar;
|
|
236
|
-
|
|
243
|
+
|
|
244
|
+
nextTick(() => {
|
|
245
|
+
updateTooltipPosition(event);
|
|
246
|
+
});
|
|
237
247
|
};
|
|
238
248
|
|
|
239
249
|
const onBarMouseMove = (bar: GanttBar, event: MouseEvent) => {
|
|
@@ -247,30 +257,50 @@ export default defineComponent({
|
|
|
247
257
|
tooltipState.barData = null;
|
|
248
258
|
};
|
|
249
259
|
|
|
250
|
-
const updateTooltipPosition = (event
|
|
251
|
-
|
|
260
|
+
const updateTooltipPosition = (event?: MouseEvent) => {
|
|
261
|
+
const container = chartContainer.value;
|
|
262
|
+
const tooltipEl = tooltipElement.value;
|
|
263
|
+
if (!container || !tooltipEl) return;
|
|
264
|
+
|
|
265
|
+
const { left, top } = container.getBoundingClientRect();
|
|
252
266
|
|
|
253
|
-
const
|
|
254
|
-
const
|
|
255
|
-
const y = event.clientY - containerRect.top;
|
|
267
|
+
const scrollLeft = container.scrollLeft;
|
|
268
|
+
const scrollTop = container.scrollTop;
|
|
256
269
|
|
|
257
|
-
const tooltipWidth = 300;
|
|
258
|
-
const tooltipHeight = 100;
|
|
270
|
+
const tooltipWidth = tooltipEl.offsetWidth || 300;
|
|
271
|
+
const tooltipHeight = tooltipEl.offsetHeight || 100;
|
|
259
272
|
const margin = 15;
|
|
260
273
|
|
|
261
|
-
let
|
|
262
|
-
let
|
|
274
|
+
let contentX: number;
|
|
275
|
+
let contentY: number;
|
|
276
|
+
|
|
277
|
+
if (event) {
|
|
278
|
+
lastMousePosition.value = { eventX: event.clientX, eventY: event.clientY };
|
|
279
|
+
contentX = event.clientX - left + scrollLeft;
|
|
280
|
+
contentY = event.clientY - top + scrollTop;
|
|
281
|
+
} else if (lastMousePosition.value) {
|
|
282
|
+
contentX = lastMousePosition.value.eventX - left + scrollLeft;
|
|
283
|
+
contentY = lastMousePosition.value.eventY - top + scrollTop;
|
|
284
|
+
} else {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
let tooltipX = contentX + margin;
|
|
289
|
+
let tooltipY = contentY + margin;
|
|
290
|
+
|
|
291
|
+
const maxVisibleX = scrollLeft + container.clientWidth - tooltipWidth - 10;
|
|
292
|
+
const maxVisibleY = scrollTop + container.clientHeight - tooltipHeight - 10;
|
|
263
293
|
|
|
264
|
-
if (tooltipX
|
|
265
|
-
tooltipX =
|
|
294
|
+
if (tooltipX > maxVisibleX) {
|
|
295
|
+
tooltipX = maxVisibleX;
|
|
266
296
|
}
|
|
267
297
|
|
|
268
|
-
if (tooltipY
|
|
269
|
-
tooltipY = Math.max(10,
|
|
298
|
+
if (tooltipY > maxVisibleY) {
|
|
299
|
+
tooltipY = Math.max(scrollTop + 10, contentY - tooltipHeight - margin);
|
|
270
300
|
}
|
|
271
301
|
|
|
272
|
-
tooltipX = Math.max(10, tooltipX);
|
|
273
|
-
tooltipY = Math.max(10, tooltipY);
|
|
302
|
+
tooltipX = Math.max(scrollLeft + 10, tooltipX);
|
|
303
|
+
tooltipY = Math.max(scrollTop + 10, tooltipY);
|
|
274
304
|
|
|
275
305
|
tooltipState.x = tooltipX;
|
|
276
306
|
tooltipState.y = tooltipY;
|
|
@@ -281,6 +311,20 @@ export default defineComponent({
|
|
|
281
311
|
zIndex: 999
|
|
282
312
|
}));
|
|
283
313
|
|
|
314
|
+
onMounted(() => {
|
|
315
|
+
if (!chartContainer.value) return;
|
|
316
|
+
const container = chartContainer.value;
|
|
317
|
+
const handleScroll = () => {
|
|
318
|
+
if (tooltipState.visible) {
|
|
319
|
+
updateTooltipPosition();
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
container.addEventListener('scroll', handleScroll);
|
|
323
|
+
onUnmounted(() => {
|
|
324
|
+
container.removeEventListener('scroll', handleScroll);
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
|
|
284
328
|
return {
|
|
285
329
|
monthColumns,
|
|
286
330
|
timelineGridStyle,
|
|
@@ -294,6 +338,7 @@ export default defineComponent({
|
|
|
294
338
|
tooltipState,
|
|
295
339
|
tooltipPositionStyle,
|
|
296
340
|
chartContainer,
|
|
341
|
+
tooltipElement,
|
|
297
342
|
onBarMouseEnter,
|
|
298
343
|
onBarMouseMove,
|
|
299
344
|
onBarMouseLeave,
|
|
@@ -128,7 +128,6 @@ export default function buildBarPositioning(dateRange, monthColumns) {
|
|
|
128
128
|
|
|
129
129
|
const positionedBars = JSON.parse(JSON.stringify(bars));
|
|
130
130
|
|
|
131
|
-
// Assign each bar to its own unique row position in the original order
|
|
132
131
|
positionedBars.forEach((bar: GanttBar, index: number) => {
|
|
133
132
|
bar.rowPosition = index;
|
|
134
133
|
});
|
|
@@ -3,19 +3,20 @@ export interface GanttData {
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
export interface GanttGroup {
|
|
6
|
-
title: string;
|
|
6
|
+
title: string;
|
|
7
|
+
subtitle?: string;
|
|
7
8
|
bars: GanttBar[];
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
export interface GanttBar {
|
|
11
12
|
id: string | number;
|
|
12
|
-
label: string;
|
|
13
|
-
start: Date | string;
|
|
14
|
-
end: Date | string;
|
|
15
|
-
color: string;
|
|
13
|
+
label: string;
|
|
14
|
+
start: Date | string;
|
|
15
|
+
end: Date | string;
|
|
16
|
+
color: string;
|
|
16
17
|
rowPosition?: number;
|
|
17
18
|
tooltipData?: TooltipData;
|
|
18
|
-
|
|
19
|
+
|
|
19
20
|
[key: string]: any;
|
|
20
21
|
}
|
|
21
22
|
|