sprintify-ui 0.11.16 → 0.11.19
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/sprintify-ui.es.js +4245 -4193
- package/dist/types/components/BaseGantt.vue.d.ts +6 -1
- package/dist/types/components/BaseTooltip.vue.d.ts +5 -5
- package/dist/types/services/gantt/types.d.ts +4 -0
- package/package.json +1 -1
- package/src/components/BaseGantt.mdx +76 -41
- package/src/components/BaseGantt.stories.js +75 -1
- package/src/components/BaseGantt.vue +94 -2
- package/src/components/BaseTooltip.stories.js +1 -1
- package/src/components/BaseTooltip.vue +35 -45
- package/src/services/gantt/types.ts +5 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GanttRow, GanttRowFormatted, GanttItemFormatted } from '@/services/gantt/types';
|
|
1
|
+
import { GanttRow, GanttRowFormatted, GanttItemFormatted, GanttRelationship } from '@/services/gantt/types';
|
|
2
2
|
import { VNode } from 'vue';
|
|
3
3
|
interface Props {
|
|
4
4
|
/**
|
|
@@ -25,6 +25,10 @@ interface Props {
|
|
|
25
25
|
* Flatten the Gantt chart by removing the hierarchy of rows and displaying all items in a single list. This is useful when there's only one level of rows and you want to maximize the vertical space.
|
|
26
26
|
*/
|
|
27
27
|
flatten?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Relationships between items, drawn as arrows from one item to another.
|
|
30
|
+
*/
|
|
31
|
+
relationships?: GanttRelationship[];
|
|
28
32
|
}
|
|
29
33
|
type __VLS_Slots = {
|
|
30
34
|
sidebarRow: (props: {
|
|
@@ -51,6 +55,7 @@ declare const __VLS_component: import("vue").DefineComponent<Props, {}, {}, {},
|
|
|
51
55
|
sidebarWidth: number;
|
|
52
56
|
rowHeight: number;
|
|
53
57
|
includeToday: boolean;
|
|
58
|
+
relationships: GanttRelationship[];
|
|
54
59
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
55
60
|
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
56
61
|
export default _default;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { UseFloatingOptions } from '@floating-ui/vue';
|
|
2
2
|
type __VLS_Props = {
|
|
3
|
+
as?: string;
|
|
3
4
|
visible?: boolean;
|
|
4
5
|
text?: string | null | undefined;
|
|
5
|
-
class?: string[] | string | null | undefined;
|
|
6
6
|
floatingOptions?: UseFloatingOptions;
|
|
7
7
|
/**
|
|
8
8
|
* Whether the tooltip content is interactive or not.
|
|
@@ -13,16 +13,16 @@ type __VLS_Props = {
|
|
|
13
13
|
dark?: boolean;
|
|
14
14
|
offset?: number;
|
|
15
15
|
};
|
|
16
|
-
declare var
|
|
16
|
+
declare var __VLS_7: {}, __VLS_17: {};
|
|
17
17
|
type __VLS_Slots = {} & {
|
|
18
|
-
default?: (props: typeof
|
|
18
|
+
default?: (props: typeof __VLS_7) => any;
|
|
19
19
|
} & {
|
|
20
|
-
tooltip?: (props: typeof
|
|
20
|
+
tooltip?: (props: typeof __VLS_17) => any;
|
|
21
21
|
};
|
|
22
22
|
declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
23
23
|
dark: boolean;
|
|
24
|
-
class: string | string[] | null;
|
|
25
24
|
text: string | null;
|
|
25
|
+
as: string;
|
|
26
26
|
visible: boolean;
|
|
27
27
|
floatingOptions: UseFloatingOptions;
|
|
28
28
|
interactive: boolean;
|
package/package.json
CHANGED
|
@@ -1,20 +1,53 @@
|
|
|
1
1
|
import { Canvas, Meta, Primary, Controls, Story } from '@storybook/addon-docs/blocks';
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import * as BaseGanttStories from './BaseGantt.stories';
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
<Meta of={BaseGanttStories} />
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
# BaseGantt
|
|
8
8
|
|
|
9
9
|
## Introduction
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
|
|
11
|
+
A Gantt chart component for visualizing tasks and events over a timeline. Supports hierarchical rows with nested items, relationship arrows between items, a resizable sidebar, a "now" line, and fully customizable rendering via slots.
|
|
12
12
|
|
|
13
13
|
<Primary />
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Relationships
|
|
16
|
+
|
|
17
|
+
Use the `relationships` prop to draw arrows between items. Each relationship connects a source item to a target item by their IDs.
|
|
18
|
+
|
|
19
|
+
<Canvas of={BaseGanttStories.Relationships} />
|
|
20
|
+
|
|
21
|
+
## Slots
|
|
22
|
+
|
|
23
|
+
| Slot | Props | Description |
|
|
24
|
+
|---------------|------------------------------------|--------------------------------------------------------------|
|
|
25
|
+
| row | `{ row: GanttRowFormatted }` | Custom rendering for a row bar on the chart |
|
|
26
|
+
| item | `{ item: GanttItemFormatted }` | Custom rendering for an item bar on the chart |
|
|
27
|
+
| sidebarRow | `{ row: GanttRowFormatted }` | Custom rendering for a row entry in the sidebar |
|
|
28
|
+
| sidebarItem | `{ item: GanttItemFormatted }` | Custom rendering for an item entry in the sidebar |
|
|
29
|
+
|
|
30
|
+
<Canvas of={BaseGanttStories.SlotItem} />
|
|
31
|
+
<Canvas of={BaseGanttStories.SlotSidebarSlots} />
|
|
32
|
+
|
|
33
|
+
## Events
|
|
34
|
+
|
|
35
|
+
| Event | Payload | Description |
|
|
36
|
+
|--------------|------------------------|--------------------------------------|
|
|
37
|
+
| row:click | `GanttRowFormatted` | Emitted when a row bar is clicked |
|
|
38
|
+
| item:click | `GanttItemFormatted` | Emitted when an item bar is clicked |
|
|
39
|
+
|
|
40
|
+
## Props
|
|
41
|
+
|
|
42
|
+
<Controls />
|
|
16
43
|
|
|
17
|
-
|
|
44
|
+
## Types
|
|
45
|
+
|
|
46
|
+
### Input types
|
|
47
|
+
|
|
48
|
+
These types are used when passing data to the component.
|
|
49
|
+
|
|
50
|
+
#### GanttRow
|
|
18
51
|
|
|
19
52
|
| Prop | Type | Description |
|
|
20
53
|
|-----------|-----------------------------|--------------------------------------------------|
|
|
@@ -22,58 +55,60 @@ This is the BaseGantt component used to display Gantt charts. It allows you to v
|
|
|
22
55
|
| name | string | Name of the row |
|
|
23
56
|
| meta | Object? | Optional metadata for the row |
|
|
24
57
|
| items | GanttItem[] | Array of items (tasks/events) in the row |
|
|
25
|
-
| height | number? | Optional custom height for the row. If not provided,
|
|
58
|
+
| height | number? | Optional custom height for the row. If not provided, `rowHeight` prop will be used. |
|
|
26
59
|
|
|
27
|
-
|
|
60
|
+
#### GanttItem
|
|
28
61
|
|
|
29
62
|
| Prop | Type | Description |
|
|
30
63
|
|-----------|-----------------------------|--------------------------------------------------|
|
|
31
64
|
| id | number \| string | Unique identifier for the item |
|
|
32
65
|
| start | string | Start date/time (ISO string) |
|
|
33
66
|
| end | string | End date/time (ISO string) |
|
|
34
|
-
| height | number? | Optional custom height for the item. If not provided,
|
|
67
|
+
| height | number? | Optional custom height for the item. If not provided, `rowHeight` prop will be used. |
|
|
35
68
|
| name | string | Name of the item |
|
|
36
69
|
| meta | Object? | Optional metadata for the item |
|
|
37
70
|
| color | string | Color used to display the item |
|
|
38
71
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Once the rows have been formatted for rendering, the GanttRowFormatted type is used.
|
|
72
|
+
#### GanttRelationship
|
|
42
73
|
|
|
43
74
|
| Prop | Type | Description |
|
|
44
75
|
|-----------|-----------------------------|--------------------------------------------------|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
| items | GanttItemFormatted[] | Array of formatted items (tasks/events) in the row |
|
|
48
|
-
| height | number | The rendered height of the row |
|
|
49
|
-
| barHeight | number | The height of the bars in the row |
|
|
50
|
-
| width | number | The width of the bar in pixels |
|
|
51
|
-
| start | DateTime | The DateTime start of the bar |
|
|
52
|
-
| end | DateTime | The DateTime end of the bar |
|
|
53
|
-
| x | number | The x position of the bar in pixels |
|
|
54
|
-
| y | number | The y position of the bar in pixels |
|
|
55
|
-
| meta | Object? | Optional metadata for the row |
|
|
76
|
+
| fromId | number \| string | ID of the source item (where the arrow starts) |
|
|
77
|
+
| toId | number \| string | ID of the target item (where the arrow ends) |
|
|
56
78
|
|
|
57
|
-
###
|
|
79
|
+
### Formatted types
|
|
58
80
|
|
|
59
|
-
|
|
81
|
+
These types are provided to slot consumers and event handlers after the component has processed the input data for rendering.
|
|
82
|
+
|
|
83
|
+
#### GanttRowFormatted
|
|
60
84
|
|
|
61
85
|
| Prop | Type | Description |
|
|
62
86
|
|-----------|-----------------------------|--------------------------------------------------|
|
|
63
|
-
| id | number \| string | Unique identifier for the
|
|
64
|
-
| name
|
|
65
|
-
|
|
|
66
|
-
| height
|
|
67
|
-
| barHeight | number
|
|
68
|
-
| width
|
|
69
|
-
| start | DateTime
|
|
70
|
-
| end | DateTime
|
|
71
|
-
| x
|
|
72
|
-
| y
|
|
73
|
-
|
|
|
74
|
-
| meta | Object? | Optional metadata for the item |
|
|
87
|
+
| id | number \| string | Unique identifier for the row |
|
|
88
|
+
| name | string | Name of the row |
|
|
89
|
+
| items | GanttItemFormatted[] | Array of formatted items in the row |
|
|
90
|
+
| height | number | The rendered height of the row |
|
|
91
|
+
| barHeight | number | The height of the bars in the row |
|
|
92
|
+
| width | number | The width of the bar in pixels |
|
|
93
|
+
| start | DateTime | The DateTime start of the bar |
|
|
94
|
+
| end | DateTime | The DateTime end of the bar |
|
|
95
|
+
| x | number | The x position of the bar in pixels |
|
|
96
|
+
| y | number | The y position of the bar in pixels |
|
|
97
|
+
| meta | Object? | Optional metadata for the row |
|
|
75
98
|
|
|
99
|
+
#### GanttItemFormatted
|
|
76
100
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
| Prop | Type | Description |
|
|
102
|
+
|--------------|--------------------------|--------------------------------------------------|
|
|
103
|
+
| id | number \| string | Unique identifier for the item |
|
|
104
|
+
| name | string | Name of the item |
|
|
105
|
+
| color | string | The color of the item |
|
|
106
|
+
| height | number | The rendered height of the item |
|
|
107
|
+
| barHeight | number | The height of the bar in the item |
|
|
108
|
+
| width | number | The width of the item in pixels |
|
|
109
|
+
| start | DateTime | The DateTime start of the item |
|
|
110
|
+
| end | DateTime | The DateTime end of the item |
|
|
111
|
+
| x | number | The x position of the item in pixels |
|
|
112
|
+
| y | number | The y position of the item in pixels |
|
|
113
|
+
| milliseconds | number | The duration of the item in milliseconds |
|
|
114
|
+
| meta | Object? | Optional metadata for the item |
|
|
@@ -157,4 +157,78 @@ const SlotSidebarSlotsTemplate = (args) => ({
|
|
|
157
157
|
});
|
|
158
158
|
|
|
159
159
|
export const SlotSidebarSlots = SlotSidebarSlotsTemplate.bind({});
|
|
160
|
-
SlotSidebarSlots.args = {};
|
|
160
|
+
SlotSidebarSlots.args = {};
|
|
161
|
+
|
|
162
|
+
// Relationships story with unique item IDs
|
|
163
|
+
|
|
164
|
+
const relationshipRows = [];
|
|
165
|
+
|
|
166
|
+
let itemId = 1;
|
|
167
|
+
|
|
168
|
+
for (let i = 0; i < 5; i++) {
|
|
169
|
+
const items = [];
|
|
170
|
+
|
|
171
|
+
for (let j = 0; j < 2; j++) {
|
|
172
|
+
const start = DateTime.now()
|
|
173
|
+
.minus({ days: 30 })
|
|
174
|
+
.plus({ days: (i * 15) + (j * 20) });
|
|
175
|
+
|
|
176
|
+
const end = start.plus({ days: 15 });
|
|
177
|
+
|
|
178
|
+
const colors = ["blue", "green", "red", "indigo", "purple"];
|
|
179
|
+
const color = defaultColors[colors[i % colors.length]][500];
|
|
180
|
+
|
|
181
|
+
items.push({
|
|
182
|
+
id: itemId++,
|
|
183
|
+
name: `Task ${items.length + 1} of Project ${i + 1}`,
|
|
184
|
+
start: start.toISO(),
|
|
185
|
+
end: end.toISO(),
|
|
186
|
+
color: color,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
relationshipRows.push({
|
|
191
|
+
id: i + 1,
|
|
192
|
+
name: `Project ${i + 1}`,
|
|
193
|
+
items: items,
|
|
194
|
+
height: 30,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const relationships = [
|
|
199
|
+
{ fromId: 1, toId: 3 },
|
|
200
|
+
{ fromId: 3, toId: 5 },
|
|
201
|
+
{ fromId: 2, toId: 6 },
|
|
202
|
+
{ fromId: 5, toId: 9 },
|
|
203
|
+
];
|
|
204
|
+
|
|
205
|
+
const RelationshipsTemplate = (args) => ({
|
|
206
|
+
components: {
|
|
207
|
+
BaseCard,
|
|
208
|
+
BaseGantt,
|
|
209
|
+
},
|
|
210
|
+
setup() {
|
|
211
|
+
function onItemClick(item) {
|
|
212
|
+
alert(`Item "${item.name}" clicked`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function onRowClick(item) {
|
|
216
|
+
alert(`Row "${item.name}" clicked`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return { args, onItemClick, onRowClick };
|
|
220
|
+
},
|
|
221
|
+
template: `
|
|
222
|
+
<BaseCard clipped>
|
|
223
|
+
<BaseGantt v-bind="args" @item:click="onItemClick" @row:click="onRowClick">
|
|
224
|
+
</BaseGantt>
|
|
225
|
+
</BaseCard>
|
|
226
|
+
`,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
export const Relationships = RelationshipsTemplate.bind({});
|
|
230
|
+
Relationships.args = {
|
|
231
|
+
rows: relationshipRows,
|
|
232
|
+
relationships,
|
|
233
|
+
maxHeight: 500,
|
|
234
|
+
};
|
|
@@ -276,6 +276,45 @@
|
|
|
276
276
|
</div>
|
|
277
277
|
</div>
|
|
278
278
|
</li>
|
|
279
|
+
|
|
280
|
+
<!-- Relationship arrows -->
|
|
281
|
+
|
|
282
|
+
<svg
|
|
283
|
+
v-if="relationshipPaths.length"
|
|
284
|
+
class="absolute top-0 left-0 pointer-events-none"
|
|
285
|
+
:viewBox="`0 0 ${width} ${height}`"
|
|
286
|
+
:width="width"
|
|
287
|
+
:height="height"
|
|
288
|
+
>
|
|
289
|
+
<defs>
|
|
290
|
+
<marker
|
|
291
|
+
id="gantt-arrowhead"
|
|
292
|
+
markerWidth="8"
|
|
293
|
+
markerHeight="6"
|
|
294
|
+
refX="8"
|
|
295
|
+
refY="3"
|
|
296
|
+
orient="auto"
|
|
297
|
+
>
|
|
298
|
+
<polygon
|
|
299
|
+
points="0 0, 8 3, 0 6"
|
|
300
|
+
fill="black"
|
|
301
|
+
></polygon>
|
|
302
|
+
</marker>
|
|
303
|
+
</defs>
|
|
304
|
+
<g
|
|
305
|
+
v-for="rel in relationshipPaths"
|
|
306
|
+
:key="rel.id"
|
|
307
|
+
opacity="0.3"
|
|
308
|
+
>
|
|
309
|
+
<path
|
|
310
|
+
:d="rel.path"
|
|
311
|
+
fill="none"
|
|
312
|
+
stroke="black"
|
|
313
|
+
stroke-width="1.5"
|
|
314
|
+
marker-end="url(#gantt-arrowhead)"
|
|
315
|
+
></path>
|
|
316
|
+
</g>
|
|
317
|
+
</svg>
|
|
279
318
|
</ul>
|
|
280
319
|
|
|
281
320
|
<!-- Vertical lines -->
|
|
@@ -346,7 +385,7 @@
|
|
|
346
385
|
y1="0"
|
|
347
386
|
:y2="height"
|
|
348
387
|
stroke="red"
|
|
349
|
-
stroke-width="
|
|
388
|
+
stroke-width="1.5"
|
|
350
389
|
style="filter: drop-shadow(0px 0px 2px rgb(0 0 0 / 0.1));"
|
|
351
390
|
></line>
|
|
352
391
|
</svg>
|
|
@@ -358,7 +397,7 @@
|
|
|
358
397
|
<script lang="ts" setup>
|
|
359
398
|
import { useElementSize, useScroll } from '@vueuse/core';
|
|
360
399
|
import { Format } from '@/services/gantt/format';
|
|
361
|
-
import { FormatConfig, GanttRow, GanttRowFormatted, Group, Tick, NowLine, GanttItemFormatted } from '@/services/gantt/types';
|
|
400
|
+
import { FormatConfig, GanttRow, GanttRowFormatted, Group, Tick, NowLine, GanttItemFormatted, GanttRelationship } from '@/services/gantt/types';
|
|
362
401
|
import { cloneDeep, debounce } from 'lodash';
|
|
363
402
|
import { slate } from 'tailwindcss/colors';
|
|
364
403
|
import { VNode } from 'vue';
|
|
@@ -388,6 +427,10 @@ interface Props {
|
|
|
388
427
|
* Flatten the Gantt chart by removing the hierarchy of rows and displaying all items in a single list. This is useful when there's only one level of rows and you want to maximize the vertical space.
|
|
389
428
|
*/
|
|
390
429
|
flatten?: boolean;
|
|
430
|
+
/**
|
|
431
|
+
* Relationships between items, drawn as arrows from one item to another.
|
|
432
|
+
*/
|
|
433
|
+
relationships?: GanttRelationship[];
|
|
391
434
|
}
|
|
392
435
|
|
|
393
436
|
const props = withDefaults(defineProps<Props>(), {
|
|
@@ -395,6 +438,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
395
438
|
rowHeight: 40,
|
|
396
439
|
maxHeight: undefined,
|
|
397
440
|
includeToday: true,
|
|
441
|
+
relationships: () => [],
|
|
398
442
|
});
|
|
399
443
|
|
|
400
444
|
defineEmits<{
|
|
@@ -521,4 +565,52 @@ function isRowExpanded(rowId: string | number): boolean {
|
|
|
521
565
|
return expandedRows.value.has(rowId);
|
|
522
566
|
}
|
|
523
567
|
|
|
568
|
+
// Relationship arrows
|
|
569
|
+
|
|
570
|
+
const relationshipPaths = computed(() => {
|
|
571
|
+
if (!props.relationships.length || !rowsInternal.value.length) return [];
|
|
572
|
+
|
|
573
|
+
const positions = new Map<string | number, { x: number; centerY: number; width: number }>();
|
|
574
|
+
let cumulativeY = 0;
|
|
575
|
+
|
|
576
|
+
for (const row of rowsInternal.value) {
|
|
577
|
+
if (!props.flatten) {
|
|
578
|
+
cumulativeY += row.height;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
if (isRowExpanded(row.id)) {
|
|
582
|
+
for (const item of row.items) {
|
|
583
|
+
positions.set(item.id, {
|
|
584
|
+
x: item.x,
|
|
585
|
+
centerY: cumulativeY + item.y + item.barHeight / 2,
|
|
586
|
+
width: item.width,
|
|
587
|
+
});
|
|
588
|
+
cumulativeY += item.height;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
return props.relationships
|
|
594
|
+
.map((rel) => {
|
|
595
|
+
const from = positions.get(rel.fromId);
|
|
596
|
+
const to = positions.get(rel.toId);
|
|
597
|
+
if (!from || !to) return null;
|
|
598
|
+
|
|
599
|
+
const startX = from.x + from.width;
|
|
600
|
+
const startY = from.centerY;
|
|
601
|
+
const endX = to.x;
|
|
602
|
+
const endY = to.centerY;
|
|
603
|
+
|
|
604
|
+
const TAIL_LENGTH = 20;
|
|
605
|
+
const curveEndX = endX - TAIL_LENGTH;
|
|
606
|
+
const dx = Math.abs(curveEndX - startX);
|
|
607
|
+
const offset = Math.max(20, dx * 0.3);
|
|
608
|
+
|
|
609
|
+
const path = `M ${startX} ${startY} C ${startX + offset} ${startY}, ${curveEndX - offset} ${endY}, ${curveEndX} ${endY} L ${endX} ${endY}`;
|
|
610
|
+
|
|
611
|
+
return { path, id: `${rel.fromId}-${rel.toId}` };
|
|
612
|
+
})
|
|
613
|
+
.filter((r): r is { path: string; id: string } => r !== null);
|
|
614
|
+
});
|
|
615
|
+
|
|
524
616
|
</script>
|
|
@@ -22,7 +22,7 @@ const Template = (args) => ({
|
|
|
22
22
|
template: `
|
|
23
23
|
<BaseCard>
|
|
24
24
|
<BaseCardRow size=sm>
|
|
25
|
-
<BaseTooltip class="inline-block" v-bind="args">
|
|
25
|
+
<BaseTooltip class="inline-block" title="test" v-bind="args">
|
|
26
26
|
<div>Hover me, the tooltip show appear outside the BaseCard</div>
|
|
27
27
|
</BaseTooltip>
|
|
28
28
|
</BaseCardRow>
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<component
|
|
3
|
+
:is="as"
|
|
3
4
|
ref="targetRef"
|
|
4
|
-
:class="classInternal"
|
|
5
5
|
>
|
|
6
6
|
<slot />
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
to="body"
|
|
11
|
-
>
|
|
12
|
-
<div
|
|
13
|
-
ref="tooltipRef"
|
|
14
|
-
class="fixed top-0 left-0 z-tooltip"
|
|
15
|
-
:class="[!interactive ? 'pointer-events-none' : '']"
|
|
16
|
-
:style="floatingStyles"
|
|
7
|
+
<Teleport
|
|
8
|
+
v-if="visible"
|
|
9
|
+
to="body"
|
|
17
10
|
>
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
leave-from-class="transform scale-100 opacity-100"
|
|
24
|
-
leave-to-class="transform scale-90 opacity-0"
|
|
11
|
+
<div
|
|
12
|
+
ref="tooltipRef"
|
|
13
|
+
class="fixed top-0 left-0 z-tooltip"
|
|
14
|
+
:class="[!interactive ? 'pointer-events-none' : '']"
|
|
15
|
+
:style="floatingStyles"
|
|
25
16
|
>
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
17
|
+
<transition
|
|
18
|
+
enter-active-class="transition duration-200 ease-out"
|
|
19
|
+
enter-from-class="transform scale-90 opacity-0"
|
|
20
|
+
enter-to-class="transform scale-100 opacity-100"
|
|
21
|
+
leave-active-class="transition duration-75 ease-in"
|
|
22
|
+
leave-from-class="transform scale-100 opacity-100"
|
|
23
|
+
leave-to-class="transform scale-90 opacity-0"
|
|
29
24
|
>
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
25
|
+
<slot
|
|
26
|
+
v-if="showTooltip"
|
|
27
|
+
name="tooltip"
|
|
28
|
+
>
|
|
29
|
+
<div
|
|
30
|
+
class="text-xs max-w-xs leading-snug rounded-md pt-1.5 pb-2 px-3"
|
|
31
|
+
:class="[
|
|
32
|
+
dark ? 'bg-slate-900 text-white' : 'bg-white text-slate-900 ring-1 ring-black ring-opacity-10 shadow-md',
|
|
33
|
+
]"
|
|
34
|
+
v-html="text"
|
|
35
|
+
/>
|
|
36
|
+
</slot>
|
|
37
|
+
</transition>
|
|
38
|
+
</div>
|
|
39
|
+
</Teleport>
|
|
40
|
+
</component>
|
|
41
41
|
</template>
|
|
42
42
|
|
|
43
43
|
<script lang="ts" setup>
|
|
@@ -45,14 +45,10 @@ import { useTooltip } from '@/composables/tooltip';
|
|
|
45
45
|
import { unrefElement } from '@vueuse/core';
|
|
46
46
|
import { UseFloatingOptions } from '@floating-ui/vue';
|
|
47
47
|
|
|
48
|
-
defineOptions({
|
|
49
|
-
inheritAttrs: false,
|
|
50
|
-
});
|
|
51
|
-
|
|
52
48
|
const props = withDefaults(defineProps<{
|
|
49
|
+
as?: string,
|
|
53
50
|
visible?: boolean,
|
|
54
51
|
text?: string | null | undefined;
|
|
55
|
-
class?: string[] | string | null | undefined;
|
|
56
52
|
floatingOptions?: UseFloatingOptions,
|
|
57
53
|
/**
|
|
58
54
|
* Whether the tooltip content is interactive or not.
|
|
@@ -63,9 +59,9 @@ const props = withDefaults(defineProps<{
|
|
|
63
59
|
dark?: boolean,
|
|
64
60
|
offset?: number,
|
|
65
61
|
}>(), {
|
|
62
|
+
as: 'div',
|
|
66
63
|
visible: true,
|
|
67
64
|
text: null,
|
|
68
|
-
class: null,
|
|
69
65
|
floatingOptions() {
|
|
70
66
|
return {
|
|
71
67
|
placement: 'top-start',
|
|
@@ -85,10 +81,4 @@ const tooltipRef = ref<HTMLElement | null>(null)
|
|
|
85
81
|
|
|
86
82
|
const { floatingStyles, showTooltip } = useTooltip(targetInternal, tooltipRef, props.interactive, props.delay, props.floatingOptions, props.offset);
|
|
87
83
|
|
|
88
|
-
const classInternal = computed(() => {
|
|
89
|
-
return [
|
|
90
|
-
props.class,
|
|
91
|
-
];
|
|
92
|
-
});
|
|
93
|
-
|
|
94
84
|
</script>
|