@dataloop-ai/components 0.17.34 → 0.17.36
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/package.json +1 -1
- package/src/components/basic/DlButton/DlButton.vue +1 -1
- package/src/components/basic/DlGrid/DlGrid.vue +144 -0
- package/src/components/basic/DlGrid/index.ts +4 -0
- package/src/components/basic/DlGrid/types.ts +4 -0
- package/src/components/basic/DlWidget/DlWidget.vue +50 -41
- package/src/components/basic/DlWidget/index.ts +1 -3
- package/src/components/basic/DlWidget/utils.ts +63 -8
- package/src/components/basic/index.ts +1 -0
- package/src/components/compound/DlCharts/charts/DlBarChart/DlBarChart.vue +3 -0
- package/src/components/compound/DlCharts/charts/DlDoughnutChart/DlDoughnutChartWidget.vue +1 -2
- package/src/components/compound/DlTabs/DlTabs.vue +1 -1
- package/src/components/compound/DlTabs/components/DlTab.vue +7 -2
- package/src/demos/DlAlertDemo.vue +14 -0
- package/src/demos/DlGridDemo.vue +40 -0
- package/src/demos/DlTabsDemo.vue +2 -0
- package/src/demos/DlWidgetDemo.vue +217 -61
- package/src/demos/index.ts +2 -0
- package/src/components/basic/DlWidget/DlGrid.vue +0 -33
- package/src/components/basic/DlWidget/DlGridRow.vue +0 -32
- package/src/utils/swapNodes.ts +0 -30
package/package.json
CHANGED
|
@@ -383,7 +383,7 @@ export default defineComponent({
|
|
|
383
383
|
gap: var(--dl-button-content-gap, 7px);
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
-
.dl-
|
|
386
|
+
.dl-button-container.first-letter-capitalized {
|
|
387
387
|
&::first-letter,
|
|
388
388
|
& > *::first-letter {
|
|
389
389
|
text-transform: capitalize;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
ref="grid"
|
|
4
|
+
:style="gridStyles"
|
|
5
|
+
:class="gridClass"
|
|
6
|
+
>
|
|
7
|
+
<slot />
|
|
8
|
+
</div>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script lang="ts">
|
|
12
|
+
import { defineComponent, PropType } from 'vue-demi'
|
|
13
|
+
import {
|
|
14
|
+
getGridTemplate,
|
|
15
|
+
getElementAbove,
|
|
16
|
+
findIndexInMatrix,
|
|
17
|
+
swapElemensInMatrix,
|
|
18
|
+
isCustomEvent
|
|
19
|
+
} from '../DlWidget/utils'
|
|
20
|
+
|
|
21
|
+
export default defineComponent({
|
|
22
|
+
model: {
|
|
23
|
+
prop: 'modelValue',
|
|
24
|
+
event: 'update:modelValue'
|
|
25
|
+
},
|
|
26
|
+
props: {
|
|
27
|
+
modelValue: {
|
|
28
|
+
type: Array as PropType<number[][]>,
|
|
29
|
+
default: null
|
|
30
|
+
},
|
|
31
|
+
rowGap: {
|
|
32
|
+
type: String,
|
|
33
|
+
default: '10px'
|
|
34
|
+
},
|
|
35
|
+
columnGap: {
|
|
36
|
+
type: String,
|
|
37
|
+
default: '10px'
|
|
38
|
+
},
|
|
39
|
+
maxElementsPerRow: {
|
|
40
|
+
type: Number,
|
|
41
|
+
default: 3
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
emits: ['update:modelValue'],
|
|
45
|
+
computed: {
|
|
46
|
+
gridStyles(): object {
|
|
47
|
+
return {
|
|
48
|
+
'--row-gap': this.rowGap,
|
|
49
|
+
'--column-gap': this.columnGap
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
gridClass(): string {
|
|
53
|
+
return this.modelValue
|
|
54
|
+
? 'dl-grid-wrapper__grid'
|
|
55
|
+
: 'dl-grid-wrapper__flex'
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
watch: {
|
|
59
|
+
modelValue: {
|
|
60
|
+
handler(val) {
|
|
61
|
+
this.$nextTick(() => {
|
|
62
|
+
if (val) this.applyGridElementStyles()
|
|
63
|
+
})
|
|
64
|
+
},
|
|
65
|
+
immediate: true
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
mounted() {
|
|
69
|
+
Array.from((this.$refs.grid as HTMLElement).children).forEach(
|
|
70
|
+
(element: Element, index: number) => {
|
|
71
|
+
(element as HTMLElement).dataset.index = `${index}`
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
},
|
|
75
|
+
methods: {
|
|
76
|
+
applyGridElementStyles() {
|
|
77
|
+
if (!this.modelValue) return
|
|
78
|
+
const gridElements = Array.from(
|
|
79
|
+
(this.$refs.grid as HTMLElement).children
|
|
80
|
+
)
|
|
81
|
+
const gridTemplate = getGridTemplate(this.modelValue)
|
|
82
|
+
if (gridElements.length !== gridTemplate.length) return
|
|
83
|
+
|
|
84
|
+
const order = this.modelValue.flat()
|
|
85
|
+
gridElements.forEach((element: Element, index: number) => {
|
|
86
|
+
const orderIndex =
|
|
87
|
+
order.findIndex((nr: number) => nr === index + 1) + 1
|
|
88
|
+
const htmlElement = element as HTMLElement
|
|
89
|
+
htmlElement.style.order = `${orderIndex}`
|
|
90
|
+
htmlElement.style.gridColumn = gridTemplate[orderIndex - 1]
|
|
91
|
+
htmlElement.addEventListener('change-position', (e) => {
|
|
92
|
+
if (!isCustomEvent(e)) return
|
|
93
|
+
this.changePosition(e)
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
},
|
|
97
|
+
changePosition(e: CustomEvent) {
|
|
98
|
+
if (!this.modelValue) return
|
|
99
|
+
const side = e.detail.side
|
|
100
|
+
const className = (this.$refs.grid as HTMLElement).children[0]
|
|
101
|
+
.classList[0]
|
|
102
|
+
const sourceIndex =
|
|
103
|
+
parseInt(
|
|
104
|
+
getElementAbove(e.detail.source, className).dataset.index
|
|
105
|
+
) + 1
|
|
106
|
+
const targetIndex =
|
|
107
|
+
parseInt(
|
|
108
|
+
getElementAbove(e.detail.target, className).dataset.index
|
|
109
|
+
) + 1
|
|
110
|
+
const sourceMatrixIndex = findIndexInMatrix(
|
|
111
|
+
this.modelValue,
|
|
112
|
+
sourceIndex
|
|
113
|
+
)
|
|
114
|
+
const targetMatrixIndex = findIndexInMatrix(
|
|
115
|
+
this.modelValue,
|
|
116
|
+
targetIndex
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
const newLayout = swapElemensInMatrix(
|
|
120
|
+
this.modelValue,
|
|
121
|
+
sourceMatrixIndex,
|
|
122
|
+
targetMatrixIndex,
|
|
123
|
+
side,
|
|
124
|
+
this.maxElementsPerRow
|
|
125
|
+
)
|
|
126
|
+
this.$emit('update:modelValue', newLayout)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<style lang="scss" scoped>
|
|
133
|
+
.dl-grid-wrapper {
|
|
134
|
+
&__grid {
|
|
135
|
+
display: grid;
|
|
136
|
+
row-gap: var(--row-gap);
|
|
137
|
+
column-gap: var(--column-gap);
|
|
138
|
+
}
|
|
139
|
+
&__flex {
|
|
140
|
+
display: flex;
|
|
141
|
+
flex-wrap: wrap;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
</style>
|
|
@@ -7,18 +7,16 @@
|
|
|
7
7
|
:id="uuid"
|
|
8
8
|
ref="widget"
|
|
9
9
|
:class="widgetStyles"
|
|
10
|
+
@mouseenter="handleVisibleDragIcon(true)"
|
|
11
|
+
@mouseleave="handleVisibleDragIcon(false)"
|
|
10
12
|
>
|
|
11
|
-
<div
|
|
12
|
-
class="dl-widget__header"
|
|
13
|
-
@mouseenter="visibleDragIcon = true"
|
|
14
|
-
@mouseleave="visibleDragIcon = false"
|
|
15
|
-
>
|
|
13
|
+
<div class="dl-widget__header">
|
|
16
14
|
<div class="dl-widget__header--titles">
|
|
17
15
|
<slot name="header" />
|
|
18
16
|
</div>
|
|
19
17
|
<dl-icon
|
|
20
18
|
:style="`visibility: ${
|
|
21
|
-
visibleDragIcon ? 'visible' : 'hidden'
|
|
19
|
+
visibleDragIcon && !isDragging ? 'visible' : 'hidden'
|
|
22
20
|
}`"
|
|
23
21
|
class="dl-widget__header--drag-icon"
|
|
24
22
|
icon="icon-dl-drag"
|
|
@@ -47,14 +45,7 @@
|
|
|
47
45
|
import { v4 } from 'uuid'
|
|
48
46
|
import { defineComponent } from 'vue-demi'
|
|
49
47
|
import { DlIcon } from '../../essential'
|
|
50
|
-
import {
|
|
51
|
-
getElementAbove,
|
|
52
|
-
addMouseEnter,
|
|
53
|
-
removeMouseEnter,
|
|
54
|
-
setFlexBasis,
|
|
55
|
-
insertAfter
|
|
56
|
-
} from './utils'
|
|
57
|
-
import { swapNodes } from '../../../utils/swapNodes'
|
|
48
|
+
import { getElementAbove, addMouseEnter, removeMouseEnter } from './utils'
|
|
58
49
|
|
|
59
50
|
export default defineComponent({
|
|
60
51
|
name: 'DlWidget',
|
|
@@ -78,20 +69,20 @@ export default defineComponent({
|
|
|
78
69
|
return `${this.isDragging ? 'dl-widget__drag' : 'dl-widget'}`
|
|
79
70
|
}
|
|
80
71
|
},
|
|
81
|
-
mounted() {
|
|
82
|
-
setFlexBasis()
|
|
83
|
-
},
|
|
84
72
|
methods: {
|
|
85
73
|
startDragging(e: MouseEvent) {
|
|
86
74
|
this.isDragging = true
|
|
75
|
+
document.body.style.cursor = 'grabbing'
|
|
87
76
|
this.draggedWidget = getElementAbove(
|
|
88
77
|
e.target as HTMLElement,
|
|
89
78
|
'dl-widget'
|
|
90
79
|
)
|
|
91
80
|
if (this.draggedWidget) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
81
|
+
const clone = this.$refs.clone as HTMLElement
|
|
82
|
+
clone.appendChild(this.draggedWidget.cloneNode(true))
|
|
83
|
+
clone.style.visibility = 'visible'
|
|
84
|
+
clone.style.width = `${this.draggedWidget.offsetWidth}px`
|
|
85
|
+
clone.style.height = `${this.draggedWidget.offsetHeight}px`
|
|
95
86
|
}
|
|
96
87
|
|
|
97
88
|
const sourceCanvas = this.draggedWidget?.querySelector('canvas')
|
|
@@ -118,13 +109,20 @@ export default defineComponent({
|
|
|
118
109
|
},
|
|
119
110
|
stopDragging(e: MouseEvent) {
|
|
120
111
|
this.isDragging = false
|
|
121
|
-
|
|
112
|
+
document.body.style.cursor = 'default'
|
|
113
|
+
const clone = this.$refs.clone as HTMLElement
|
|
114
|
+
clone.style.visibility = 'hidden'
|
|
115
|
+
clone.innerHTML = ''
|
|
122
116
|
const target = getElementAbove(e.target as HTMLElement, 'dl-widget')
|
|
117
|
+
const change = {
|
|
118
|
+
source: this.draggedWidget,
|
|
119
|
+
target
|
|
120
|
+
}
|
|
123
121
|
if (target && this.draggedWidget) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
target
|
|
122
|
+
const event = new CustomEvent('change-position', {
|
|
123
|
+
detail: change
|
|
127
124
|
})
|
|
125
|
+
;(this.$refs.wrapper as HTMLElement).dispatchEvent(event)
|
|
128
126
|
}
|
|
129
127
|
window.removeEventListener('mousemove', this.moveClone)
|
|
130
128
|
window.removeEventListener('mouseup', this.stopDragging)
|
|
@@ -148,30 +146,26 @@ export default defineComponent({
|
|
|
148
146
|
this.handleMouseInsideWidget
|
|
149
147
|
)
|
|
150
148
|
})
|
|
151
|
-
this.timer = setTimeout(this.insertWidget,
|
|
149
|
+
this.timer = setTimeout(this.insertWidget, 200)
|
|
152
150
|
},
|
|
153
151
|
insertWidget() {
|
|
154
152
|
const targetWidget = getElementAbove(
|
|
155
153
|
this.hoveredWidget,
|
|
156
154
|
'widget-wrapper'
|
|
157
155
|
)
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
targetWidget
|
|
168
|
-
)
|
|
169
|
-
}
|
|
156
|
+
const event = new CustomEvent('change-position', {
|
|
157
|
+
detail: {
|
|
158
|
+
source: this.$refs.wrapper,
|
|
159
|
+
target: targetWidget,
|
|
160
|
+
side: this.isLeftSide ? 'left' : 'right'
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
;(this.$refs.wrapper as HTMLElement).dispatchEvent(event)
|
|
164
|
+
window.clearTimeout(this.timer)
|
|
170
165
|
this.hoveredWidget.removeEventListener(
|
|
171
166
|
'mousemove',
|
|
172
167
|
this.handleMouseInsideWidget
|
|
173
168
|
)
|
|
174
|
-
setFlexBasis()
|
|
175
169
|
},
|
|
176
170
|
handleMouseInsideWidget(e: MouseEvent) {
|
|
177
171
|
const mouseOffsetInside = e.clientX - this.hoveredWidget.offsetLeft
|
|
@@ -181,6 +175,11 @@ export default defineComponent({
|
|
|
181
175
|
clearTimeout(this.timer)
|
|
182
176
|
this.handleMouseEnter(e)
|
|
183
177
|
}
|
|
178
|
+
},
|
|
179
|
+
handleVisibleDragIcon(val: boolean) {
|
|
180
|
+
if (!document.querySelector('.drag-clone').innerHTML.toString()) {
|
|
181
|
+
this.visibleDragIcon = val
|
|
182
|
+
}
|
|
184
183
|
}
|
|
185
184
|
}
|
|
186
185
|
})
|
|
@@ -200,7 +199,7 @@ export default defineComponent({
|
|
|
200
199
|
|
|
201
200
|
&--drag-icon {
|
|
202
201
|
flex-grow: 1;
|
|
203
|
-
cursor:
|
|
202
|
+
cursor: grab;
|
|
204
203
|
|
|
205
204
|
&::v-deep .dl-icon {
|
|
206
205
|
transform: rotate(90deg) !important;
|
|
@@ -223,7 +222,17 @@ export default defineComponent({
|
|
|
223
222
|
}
|
|
224
223
|
|
|
225
224
|
&__drag {
|
|
226
|
-
|
|
225
|
+
position: relative;
|
|
226
|
+
&::after {
|
|
227
|
+
content: '';
|
|
228
|
+
position: absolute;
|
|
229
|
+
width: 100%;
|
|
230
|
+
height: 100%;
|
|
231
|
+
top: 0;
|
|
232
|
+
left: 0;
|
|
233
|
+
background: var(--dl-color-separator);
|
|
234
|
+
border-radius: 5px;
|
|
235
|
+
}
|
|
227
236
|
}
|
|
228
237
|
}
|
|
229
238
|
|
|
@@ -236,6 +245,6 @@ export default defineComponent({
|
|
|
236
245
|
.widget-wrapper {
|
|
237
246
|
flex-basis: var(--widget-flex-basis);
|
|
238
247
|
margin: var(--row-gap) var(--column-gap);
|
|
239
|
-
|
|
248
|
+
padding: 15px;
|
|
240
249
|
}
|
|
241
250
|
</style>
|
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
import { cloneDeep } from 'lodash'
|
|
2
|
+
|
|
3
|
+
export function leastCommonMultiple(arr: number[]) {
|
|
4
|
+
if (!arr) return
|
|
5
|
+
const gcd = (a: number, b: number): number => (a ? gcd(b % a, a) : b)
|
|
6
|
+
const lcm = (a: number, b: number): number => (a * b) / gcd(a, b)
|
|
7
|
+
return arr.reduce(lcm)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function getGridTemplate(layout: number[][]) {
|
|
11
|
+
if (!layout) return
|
|
12
|
+
const flatLayout = layout.map((el) => el.length)
|
|
13
|
+
const template = []
|
|
14
|
+
const lcm = leastCommonMultiple(flatLayout)
|
|
15
|
+
for (let i = 0; i < flatLayout.length; i++) {
|
|
16
|
+
const columns = flatLayout[i]
|
|
17
|
+
let columnTrack = 1
|
|
18
|
+
for (let j = 0; j < columns; j++) {
|
|
19
|
+
let gridSpan = lcm / columns
|
|
20
|
+
template.push(`${columnTrack} / ${gridSpan + columnTrack}`)
|
|
21
|
+
columnTrack += gridSpan
|
|
22
|
+
gridSpan += gridSpan
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return template
|
|
26
|
+
}
|
|
27
|
+
|
|
1
28
|
export function getElementAbove(el: HTMLElement, className: string) {
|
|
2
29
|
//@ts-ignore
|
|
3
30
|
for (; el && el !== document; el = el.parentNode) {
|
|
@@ -22,16 +49,44 @@ export function removeMouseEnter(
|
|
|
22
49
|
})
|
|
23
50
|
}
|
|
24
51
|
|
|
25
|
-
export function
|
|
26
|
-
|
|
27
|
-
(
|
|
28
|
-
|
|
29
|
-
widget.style.flexBasis = `${100 / row.children.length}%`
|
|
30
|
-
})
|
|
52
|
+
export function findIndexInMatrix(matrix: number[][], nr: number) {
|
|
53
|
+
for (let i = 0; i < matrix.length; i++) {
|
|
54
|
+
for (let j = 0; j < matrix[i].length; j++) {
|
|
55
|
+
if (matrix[i][j] === nr) return { row: i, column: j }
|
|
31
56
|
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function swapElemensInMatrix(
|
|
61
|
+
layout: number[][],
|
|
62
|
+
sourceIndex: any,
|
|
63
|
+
targetIndex: any,
|
|
64
|
+
side: string,
|
|
65
|
+
maxElements: number
|
|
66
|
+
) {
|
|
67
|
+
if (targetIndex.column === sourceIndex.column + 1 && side === 'left')
|
|
68
|
+
return layout
|
|
69
|
+
const newLayout = cloneDeep(layout)
|
|
70
|
+
|
|
71
|
+
const removedElement = newLayout[sourceIndex.row].splice(
|
|
72
|
+
sourceIndex.column,
|
|
73
|
+
1
|
|
32
74
|
)
|
|
75
|
+
newLayout[targetIndex.row].splice(
|
|
76
|
+
side === 'right' ? targetIndex.column + 1 : targetIndex.column,
|
|
77
|
+
0,
|
|
78
|
+
removedElement[0]
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
return isTooLarge(newLayout, maxElements) ? layout : newLayout
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function isTooLarge(layout: number[][], max: number) {
|
|
85
|
+
const lengths = layout.map((row) => row.length)
|
|
86
|
+
const highest = Math.max(...lengths)
|
|
87
|
+
return highest > max
|
|
33
88
|
}
|
|
34
89
|
|
|
35
|
-
export function
|
|
36
|
-
|
|
90
|
+
export function isCustomEvent(event: Event): event is CustomEvent {
|
|
91
|
+
return 'detail' in event
|
|
37
92
|
}
|
|
@@ -225,6 +225,9 @@ export default defineComponent({
|
|
|
225
225
|
if (event.type !== 'mousemove') {
|
|
226
226
|
return
|
|
227
227
|
}
|
|
228
|
+
const hover = !!document.querySelector('.drag-clone')
|
|
229
|
+
chartJS.options.plugins.tooltip.enabled = !hover
|
|
230
|
+
if (hover) return
|
|
228
231
|
if (
|
|
229
232
|
items.length === 0 ||
|
|
230
233
|
chartJS.getElementsAtEventForMode(
|
|
@@ -26,14 +26,13 @@
|
|
|
26
26
|
import { defineComponent, PropType } from 'vue-demi'
|
|
27
27
|
import DlDoughnutChart from './DlDoughnutChart.vue'
|
|
28
28
|
import { TDoughnutChartData } from './types/TDoughnutChartData'
|
|
29
|
-
import { DlWidget,
|
|
29
|
+
import { DlWidget, DlGrid } from '../../../../basic'
|
|
30
30
|
|
|
31
31
|
export default defineComponent({
|
|
32
32
|
name: 'DlDoughnutChartWidget',
|
|
33
33
|
components: {
|
|
34
34
|
DlDoughnutChart,
|
|
35
35
|
DlGrid,
|
|
36
|
-
DlGridRow,
|
|
37
36
|
DlWidget
|
|
38
37
|
},
|
|
39
38
|
props: {
|
|
@@ -68,7 +68,7 @@ export default defineComponent({
|
|
|
68
68
|
fullWidth: { type: Boolean, default: false },
|
|
69
69
|
disabled: { type: Boolean, default: false },
|
|
70
70
|
modelValue: { type: String, required: true },
|
|
71
|
-
fontSize: { type: String, default: '
|
|
71
|
+
fontSize: { type: String, default: '18px' },
|
|
72
72
|
gap: { type: String, default: '40px' }
|
|
73
73
|
},
|
|
74
74
|
emits: ['update:model-value'],
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
<span>
|
|
15
15
|
<dl-icon
|
|
16
16
|
v-if="showTooltip"
|
|
17
|
-
size="
|
|
17
|
+
:size="iconSize"
|
|
18
18
|
icon="icon-dl-info"
|
|
19
19
|
class="info-icon"
|
|
20
|
+
color="dl-color-darker"
|
|
20
21
|
/>
|
|
21
22
|
<dl-tooltip v-if="showTooltip === true">
|
|
22
23
|
{{ tooltip }}
|
|
@@ -46,7 +47,7 @@ export default defineComponent({
|
|
|
46
47
|
showTooltip: { type: Boolean, default: false },
|
|
47
48
|
tooltip: { type: String, default: null },
|
|
48
49
|
tabindex: { type: String, default: '0' },
|
|
49
|
-
fontSize: { type: String, default: '
|
|
50
|
+
fontSize: { type: String, default: '18px' }
|
|
50
51
|
},
|
|
51
52
|
emits: ['click'],
|
|
52
53
|
data() {
|
|
@@ -55,6 +56,10 @@ export default defineComponent({
|
|
|
55
56
|
}
|
|
56
57
|
},
|
|
57
58
|
computed: {
|
|
59
|
+
iconSize(): string {
|
|
60
|
+
const fontSize = Number(this.fontSize.replace('px', ''))
|
|
61
|
+
return `${fontSize - 2 < 0 ? 0 : fontSize - 2}px`
|
|
62
|
+
},
|
|
58
63
|
cssFontSize(): Record<string, string> {
|
|
59
64
|
return {
|
|
60
65
|
'--dl-tab-font-size': this.fontSize
|
|
@@ -59,6 +59,20 @@
|
|
|
59
59
|
>
|
|
60
60
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
|
|
61
61
|
</DlAlert>
|
|
62
|
+
<dl-alert
|
|
63
|
+
style="margin-top: 20px"
|
|
64
|
+
fluid
|
|
65
|
+
type="warning"
|
|
66
|
+
>
|
|
67
|
+
this is an annoying message with link, this is an annoying message
|
|
68
|
+
with linkthis is an annoying message with linkthis is an annoying
|
|
69
|
+
message with linkthis is an annoying message with linkthis is an
|
|
70
|
+
annoying message with linkthis is an annoying message with linkthis
|
|
71
|
+
is an annoying message with link
|
|
72
|
+
<span>
|
|
73
|
+
Please
|
|
74
|
+
<dl-link color="dl-color-link">Contact us</dl-link>.</span>
|
|
75
|
+
</dl-alert>
|
|
62
76
|
</div>
|
|
63
77
|
</template>
|
|
64
78
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="container">
|
|
3
|
+
<dl-grid>
|
|
4
|
+
<img
|
|
5
|
+
v-for="(a, index) in 10"
|
|
6
|
+
:key="index"
|
|
7
|
+
class="grid-image"
|
|
8
|
+
:src="getRandomImg()"
|
|
9
|
+
>
|
|
10
|
+
</dl-grid>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import { defineComponent } from 'vue-demi'
|
|
16
|
+
import { DlGrid } from '../components/'
|
|
17
|
+
|
|
18
|
+
const getRandomImg = () => {
|
|
19
|
+
const random = Math.floor(Math.random() * 3) + 1
|
|
20
|
+
const link = `https://picsum.photos/${random * 100}/${
|
|
21
|
+
random * 100
|
|
22
|
+
}?random=${random}`
|
|
23
|
+
return link
|
|
24
|
+
}
|
|
25
|
+
export default defineComponent({
|
|
26
|
+
components: {
|
|
27
|
+
DlGrid
|
|
28
|
+
},
|
|
29
|
+
setup() {
|
|
30
|
+
return { getRandomImg }
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<style lang="scss" scoped>
|
|
36
|
+
.grid-image {
|
|
37
|
+
border: 2px solid var(--dl-color-darker);
|
|
38
|
+
margin: 5px;
|
|
39
|
+
}
|
|
40
|
+
</style>
|
package/src/demos/DlTabsDemo.vue
CHANGED
|
@@ -61,10 +61,12 @@
|
|
|
61
61
|
</dl-tab-panel>
|
|
62
62
|
</dl-tab-panels>
|
|
63
63
|
|
|
64
|
+
With smaller font 14px
|
|
64
65
|
<dl-tabs
|
|
65
66
|
v-model="selectedTab"
|
|
66
67
|
:items="tabItems"
|
|
67
68
|
style="margin-top: 100px; max-width: 60%"
|
|
69
|
+
font-size="14px"
|
|
68
70
|
@update:model-value="handleModelValueUpdate"
|
|
69
71
|
>
|
|
70
72
|
<template #top-right="props">
|
|
@@ -1,11 +1,149 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div class="options">
|
|
4
|
+
<div class="select-layout">
|
|
5
|
+
<select
|
|
6
|
+
class="select-layout__input"
|
|
7
|
+
@change="selectLayout"
|
|
8
|
+
>
|
|
9
|
+
<option
|
|
10
|
+
v-for="(layout, index) in layouts"
|
|
11
|
+
:key="index"
|
|
12
|
+
:value="index"
|
|
13
|
+
>
|
|
14
|
+
{{ layout.name }}
|
|
15
|
+
</option>
|
|
16
|
+
</select>
|
|
17
|
+
<button
|
|
18
|
+
class="select-layout__button"
|
|
19
|
+
@mousedown="saveLayout"
|
|
20
|
+
>
|
|
21
|
+
Save
|
|
22
|
+
</button>
|
|
23
|
+
<span class="select-layout__info">{{ hasBeenSaved }}</span>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="widgets-per-row">
|
|
26
|
+
<span class="widgets-per-row__label"> Widgets per row: </span>
|
|
27
|
+
<input
|
|
28
|
+
v-model="widgetsPerRow"
|
|
29
|
+
class="widgets-per-row__input"
|
|
30
|
+
type="number"
|
|
31
|
+
>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
<dl-grid
|
|
35
|
+
v-model="layout"
|
|
36
|
+
:max-elements-per-row="widgetsPerRow"
|
|
37
|
+
>
|
|
38
|
+
<dl-widget>
|
|
39
|
+
<template #header>
|
|
40
|
+
<span>Widget 1</span>
|
|
41
|
+
<span style="font-size: 12px; color: gray">Subtitle</span>
|
|
42
|
+
</template>
|
|
43
|
+
<template #content>
|
|
44
|
+
<dl-bar-chart
|
|
45
|
+
:legend-props="legendProps"
|
|
46
|
+
:data="data"
|
|
47
|
+
:options="options"
|
|
48
|
+
:items-in-view="8"
|
|
49
|
+
/>
|
|
50
|
+
</template>
|
|
51
|
+
<template #menu>
|
|
52
|
+
<div class="menu-icons">
|
|
53
|
+
<dl-icon
|
|
54
|
+
size="m"
|
|
55
|
+
icon="icon-dl-settings"
|
|
56
|
+
/>
|
|
57
|
+
<dl-icon
|
|
58
|
+
size="m"
|
|
59
|
+
icon="icon-dl-download"
|
|
60
|
+
/>
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
63
|
+
<template #description>
|
|
64
|
+
<span>Lorem ipsum dolor sit amet consectetur adipisicing
|
|
65
|
+
elit. Libero eligendi dolore, similique possimus
|
|
66
|
+
veritatis in vitae quia praesentium fuga quibusdam
|
|
67
|
+
autem. Doloremque tenetur repudiandae a cupiditate modi
|
|
68
|
+
dicta eveniet veritatis?</span>
|
|
69
|
+
</template>
|
|
70
|
+
</dl-widget>
|
|
71
|
+
|
|
72
|
+
<dl-widget>
|
|
73
|
+
<template #header>
|
|
74
|
+
<span>Widget 2</span>
|
|
75
|
+
</template>
|
|
76
|
+
<template #content>
|
|
77
|
+
<dl-bar-chart
|
|
78
|
+
:legend-props="legendProps"
|
|
79
|
+
:data="data"
|
|
80
|
+
:options="options"
|
|
81
|
+
:items-in-view="6"
|
|
82
|
+
/>
|
|
83
|
+
</template>
|
|
84
|
+
</dl-widget>
|
|
85
|
+
|
|
86
|
+
<dl-widget>
|
|
87
|
+
<template #header>
|
|
88
|
+
<span>Widget 3</span>
|
|
89
|
+
</template>
|
|
90
|
+
<template #content>
|
|
91
|
+
<dl-bar-chart
|
|
92
|
+
:legend-props="legendProps"
|
|
93
|
+
:data="data"
|
|
94
|
+
:options="options"
|
|
95
|
+
:items-in-view="6"
|
|
96
|
+
/>
|
|
97
|
+
</template>
|
|
98
|
+
</dl-widget>
|
|
99
|
+
|
|
100
|
+
<dl-widget>
|
|
101
|
+
<template #header>
|
|
102
|
+
<span>Widget 4</span>
|
|
103
|
+
<span style="font-size: 12px; color: gray">Subtitle</span>
|
|
104
|
+
</template>
|
|
105
|
+
<template #content>
|
|
106
|
+
<dl-bar-chart
|
|
107
|
+
:legend-props="legendProps"
|
|
108
|
+
:data="data"
|
|
109
|
+
:options="options"
|
|
110
|
+
:items-in-view="8"
|
|
111
|
+
/>
|
|
112
|
+
</template>
|
|
113
|
+
<template #description>
|
|
114
|
+
<span>Lorem ipsum dolor sit amet consectetur adipisicing
|
|
115
|
+
elit. Libero eligendi dolore, similique possimus
|
|
116
|
+
veritatis in vitae quia praesentium fuga quibusdam
|
|
117
|
+
autem. Doloremque tenetur repudiandae a cupiditate modi
|
|
118
|
+
dicta eveniet veritatis?</span>
|
|
119
|
+
</template>
|
|
120
|
+
</dl-widget>
|
|
121
|
+
|
|
122
|
+
<dl-widget>
|
|
123
|
+
<template #header>
|
|
124
|
+
<span>Widget 5</span>
|
|
125
|
+
</template>
|
|
126
|
+
<template #content>
|
|
127
|
+
<dl-bar-chart
|
|
128
|
+
:legend-props="legendProps"
|
|
129
|
+
:data="data"
|
|
130
|
+
:options="options"
|
|
131
|
+
:items-in-view="6"
|
|
132
|
+
/>
|
|
133
|
+
</template>
|
|
134
|
+
</dl-widget>
|
|
135
|
+
</dl-grid>
|
|
136
|
+
</div>
|
|
137
|
+
</template>
|
|
138
|
+
|
|
1
139
|
<script lang="ts">
|
|
2
|
-
import { defineComponent } from 'vue-demi'
|
|
140
|
+
import { defineComponent, ref } from 'vue-demi'
|
|
3
141
|
import {
|
|
4
142
|
DlWidget,
|
|
5
|
-
DlGridRow,
|
|
6
143
|
DlGrid,
|
|
7
144
|
DlBarChart,
|
|
8
|
-
|
|
145
|
+
DlGridLayout,
|
|
146
|
+
DlIcon
|
|
9
147
|
} from '../components'
|
|
10
148
|
|
|
11
149
|
const labelsFn = () => {
|
|
@@ -65,67 +203,85 @@ export default defineComponent({
|
|
|
65
203
|
DlGrid,
|
|
66
204
|
DlWidget,
|
|
67
205
|
DlBarChart,
|
|
68
|
-
|
|
69
|
-
DlConfusionMatrix
|
|
206
|
+
DlIcon
|
|
70
207
|
},
|
|
71
208
|
setup() {
|
|
72
|
-
|
|
209
|
+
const layout = ref([
|
|
210
|
+
[1, 5, 2],
|
|
211
|
+
[3, 4]
|
|
212
|
+
])
|
|
213
|
+
|
|
214
|
+
const layouts = ref<DlGridLayout[]>([
|
|
215
|
+
{
|
|
216
|
+
name: 'Layout 1',
|
|
217
|
+
value: layout.value
|
|
218
|
+
}
|
|
219
|
+
])
|
|
220
|
+
|
|
221
|
+
const widgetsPerRow = ref(3)
|
|
222
|
+
const hasBeenSaved = ref('')
|
|
223
|
+
|
|
224
|
+
const saveLayout = () => {
|
|
225
|
+
const newLayout = {
|
|
226
|
+
name: `Layout ${layouts.value.length + 1}`,
|
|
227
|
+
value: layout.value
|
|
228
|
+
}
|
|
229
|
+
layouts.value.push(newLayout)
|
|
230
|
+
hasBeenSaved.value = `${newLayout.name} has been saved.`
|
|
231
|
+
setTimeout(() => {
|
|
232
|
+
hasBeenSaved.value = ''
|
|
233
|
+
}, 2000)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const selectLayout = (e: InputEvent) => {
|
|
237
|
+
const index = parseInt((e.target as HTMLInputElement).value)
|
|
238
|
+
layout.value = layouts.value[index].value
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return {
|
|
242
|
+
data,
|
|
243
|
+
layout,
|
|
244
|
+
layouts,
|
|
245
|
+
widgetsPerRow,
|
|
246
|
+
hasBeenSaved,
|
|
247
|
+
saveLayout,
|
|
248
|
+
selectLayout
|
|
249
|
+
}
|
|
73
250
|
}
|
|
74
251
|
})
|
|
75
252
|
</script>
|
|
76
253
|
|
|
77
|
-
<
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
/>
|
|
112
|
-
</template>
|
|
113
|
-
</dl-widget>
|
|
114
|
-
|
|
115
|
-
<dl-widget>
|
|
116
|
-
<template #header>
|
|
117
|
-
<span>Widget 3</span>
|
|
118
|
-
</template>
|
|
119
|
-
<template #content>
|
|
120
|
-
<dl-bar-chart
|
|
121
|
-
:legend-props="legendProps"
|
|
122
|
-
:data="data"
|
|
123
|
-
:options="options"
|
|
124
|
-
:items-in-view="6"
|
|
125
|
-
/>
|
|
126
|
-
</template>
|
|
127
|
-
</dl-widget>
|
|
128
|
-
</dl-grid-row>
|
|
129
|
-
</dl-grid>
|
|
130
|
-
</div>
|
|
131
|
-
</template>
|
|
254
|
+
<style lang="scss" scoped>
|
|
255
|
+
.options {
|
|
256
|
+
width: 100%;
|
|
257
|
+
display: flex;
|
|
258
|
+
justify-content: space-between;
|
|
259
|
+
}
|
|
260
|
+
.widgets-per-row {
|
|
261
|
+
&__input {
|
|
262
|
+
padding: 5px;
|
|
263
|
+
border-radius: 5px;
|
|
264
|
+
width: 50px;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
.select-layout {
|
|
268
|
+
&__input,
|
|
269
|
+
&__button {
|
|
270
|
+
padding: 5px;
|
|
271
|
+
border-radius: 5px;
|
|
272
|
+
margin: 0px 2px;
|
|
273
|
+
}
|
|
274
|
+
&__info {
|
|
275
|
+
font-size: 0.8em;
|
|
276
|
+
margin-left: 10px;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
.menu-icons {
|
|
280
|
+
display: flex;
|
|
281
|
+
align-items: center;
|
|
282
|
+
& > * {
|
|
283
|
+
cursor: pointer;
|
|
284
|
+
margin: 0px 5px;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
</style>
|
package/src/demos/index.ts
CHANGED
|
@@ -53,6 +53,7 @@ import DlKpiDemo from './DlKpiDemo.vue'
|
|
|
53
53
|
import DlEllipsisDemo from './DlEllipsisDemo.vue'
|
|
54
54
|
import DlSeparatorDemo from './DlSeparatorDemo.vue'
|
|
55
55
|
import DlCardDemo from './DlCardDemo.vue'
|
|
56
|
+
import DlGridDemo from './DlGridDemo.vue'
|
|
56
57
|
import DlMarkupTableDemo from './DlMarkupTableDemo.vue'
|
|
57
58
|
import DlVirtualScrollDemo from './DlVirtualScrollDemo.vue'
|
|
58
59
|
import DlJsonEditorDemo from './DlJsonEditorDemo.vue'
|
|
@@ -113,6 +114,7 @@ export default {
|
|
|
113
114
|
DlSeparatorDemo,
|
|
114
115
|
DlKpiDemo,
|
|
115
116
|
DlCardDemo,
|
|
117
|
+
DlGridDemo,
|
|
116
118
|
DlMarkupTableDemo,
|
|
117
119
|
DlVirtualScrollDemo,
|
|
118
120
|
DlJsonEditorDemo
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
:style="rowGap"
|
|
4
|
-
class="dl-grid"
|
|
5
|
-
>
|
|
6
|
-
<slot />
|
|
7
|
-
</div>
|
|
8
|
-
</template>
|
|
9
|
-
|
|
10
|
-
<script lang="ts">
|
|
11
|
-
import { defineComponent } from 'vue-demi'
|
|
12
|
-
|
|
13
|
-
export default defineComponent({
|
|
14
|
-
props: {
|
|
15
|
-
gap: {
|
|
16
|
-
type: String,
|
|
17
|
-
default: '30px'
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
computed: {
|
|
21
|
-
rowGap(): Record<string, string> {
|
|
22
|
-
return { '--row-gap': this.gap }
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
})
|
|
26
|
-
</script>
|
|
27
|
-
|
|
28
|
-
<style lang="scss" scoped>
|
|
29
|
-
.dl-grid {
|
|
30
|
-
display: flex;
|
|
31
|
-
flex-direction: column;
|
|
32
|
-
}
|
|
33
|
-
</style>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
:style="columnGap"
|
|
4
|
-
class="dl-grid-row"
|
|
5
|
-
>
|
|
6
|
-
<slot />
|
|
7
|
-
</div>
|
|
8
|
-
</template>
|
|
9
|
-
|
|
10
|
-
<script lang="ts">
|
|
11
|
-
import { defineComponent } from 'vue-demi'
|
|
12
|
-
|
|
13
|
-
export default defineComponent({
|
|
14
|
-
props: {
|
|
15
|
-
gap: {
|
|
16
|
-
type: String,
|
|
17
|
-
default: '30px'
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
computed: {
|
|
21
|
-
columnGap(): Record<string, string> {
|
|
22
|
-
return { '--column-gap': this.gap }
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
})
|
|
26
|
-
</script>
|
|
27
|
-
|
|
28
|
-
<style scoped>
|
|
29
|
-
.dl-grid-row {
|
|
30
|
-
display: flex;
|
|
31
|
-
}
|
|
32
|
-
</style>
|
package/src/utils/swapNodes.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export function swapNodes({ source, target }: NodeSwap) {
|
|
2
|
-
const p1 = source.parentNode
|
|
3
|
-
const p2 = target.parentNode
|
|
4
|
-
let i1
|
|
5
|
-
let i2
|
|
6
|
-
|
|
7
|
-
if (!p1 || !p2 || p1.isEqualNode(target) || p2.isEqualNode(source)) return
|
|
8
|
-
|
|
9
|
-
for (var i = 0; i < p1.children.length; i++) {
|
|
10
|
-
if (p1.children[i].isEqualNode(source)) {
|
|
11
|
-
i1 = i
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
for (var i = 0; i < p2.children.length; i++) {
|
|
15
|
-
if (p2.children[i].isEqualNode(target)) {
|
|
16
|
-
i2 = i
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (p1.isEqualNode(p2) && i1 < i2) {
|
|
21
|
-
i2++
|
|
22
|
-
}
|
|
23
|
-
p1.insertBefore(target, p1.children[i1])
|
|
24
|
-
p2.insertBefore(source, p2.children[i2])
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface NodeSwap {
|
|
28
|
-
source: HTMLElement
|
|
29
|
-
target: HTMLElement
|
|
30
|
-
}
|