@dataloop-ai/components 0.18.7 → 0.18.8
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/compound/DlCharts/charts/DlConfusionMatrix/DlConfusionMatrix.vue +90 -57
- package/src/components/compound/DlCharts/components/DlBrush.vue +24 -4
- package/src/components/compound/DlCharts/types/DlConfusionMatrix.types.ts +5 -5
- package/src/demos/DlConfusionMatrixDemo.vue +93 -51
package/package.json
CHANGED
|
@@ -36,11 +36,18 @@
|
|
|
36
36
|
<div
|
|
37
37
|
ref="yAxis"
|
|
38
38
|
class="y-axis"
|
|
39
|
+
style="min-height: 100%"
|
|
39
40
|
>
|
|
40
41
|
<div
|
|
41
42
|
v-for="(label, index) in labels"
|
|
42
43
|
:key="index"
|
|
43
44
|
class="y-axis__element"
|
|
45
|
+
style="
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-grow: 1;
|
|
48
|
+
align-items: center;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
"
|
|
44
51
|
>
|
|
45
52
|
<img
|
|
46
53
|
v-if="labelImages[0]"
|
|
@@ -118,43 +125,54 @@
|
|
|
118
125
|
class="x-axis"
|
|
119
126
|
style="margin-top: 10px"
|
|
120
127
|
>
|
|
121
|
-
<
|
|
128
|
+
<div
|
|
122
129
|
v-for="(label, index) in visibleLabels"
|
|
123
|
-
:ref="`xAxis-${index}`"
|
|
124
130
|
:key="index"
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
rotateXLabels ? 100 : 10
|
|
132
|
-
}px`
|
|
133
|
-
: ''
|
|
134
|
-
}`"
|
|
131
|
+
style="
|
|
132
|
+
display: flex;
|
|
133
|
+
flex-grow: 100;
|
|
134
|
+
width: 100%;
|
|
135
|
+
justify-content: center;
|
|
136
|
+
"
|
|
135
137
|
>
|
|
136
|
-
<span
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
<span
|
|
139
|
+
:ref="`xAxis-${index}`"
|
|
140
|
+
class="x-axis__element"
|
|
141
|
+
:style="`
|
|
142
|
+
justify-content: center;
|
|
143
|
+
display: flex;${
|
|
144
|
+
!labelImages[0]
|
|
145
|
+
? `transform: rotate(${
|
|
146
|
+
rotateXLabels ? '70' : '0'
|
|
147
|
+
}deg); line-height: ${
|
|
148
|
+
rotateXLabels ? 100 : 10
|
|
149
|
+
}px`
|
|
150
|
+
: ''
|
|
151
|
+
};`"
|
|
152
|
+
>
|
|
153
|
+
<span class="x-axis__element--text">
|
|
154
|
+
<img
|
|
155
|
+
v-if="labelImages[0]"
|
|
156
|
+
class="legend-avatar"
|
|
157
|
+
:src="labelImages[index]"
|
|
158
|
+
>
|
|
159
|
+
<span v-else>
|
|
160
|
+
{{ label }}
|
|
161
|
+
</span>
|
|
144
162
|
</span>
|
|
163
|
+
<dl-tooltip
|
|
164
|
+
self="top middle"
|
|
165
|
+
:offset="debouncedCalculateXAxisElOffset(index)"
|
|
166
|
+
>
|
|
167
|
+
{{ labelStrings[index] }}</dl-tooltip>
|
|
145
168
|
</span>
|
|
146
|
-
|
|
147
|
-
self="top middle"
|
|
148
|
-
:offset="calculateXAxisElOffset(index)"
|
|
149
|
-
>
|
|
150
|
-
{{ labelStrings[index] }}</dl-tooltip>
|
|
151
|
-
</span>
|
|
169
|
+
</div>
|
|
152
170
|
</div>
|
|
153
171
|
<dl-brush
|
|
154
172
|
track-size="18px"
|
|
155
173
|
thumb-size="20px"
|
|
156
174
|
:max="matrix.length"
|
|
157
|
-
:
|
|
175
|
+
:min-range="2"
|
|
158
176
|
:selection-color="getCellBackground(0.1)"
|
|
159
177
|
:color="getCellBackground()"
|
|
160
178
|
:step="1"
|
|
@@ -190,7 +208,7 @@
|
|
|
190
208
|
</template>
|
|
191
209
|
|
|
192
210
|
<script lang="ts">
|
|
193
|
-
import { defineComponent, PropType, ref } from 'vue-demi'
|
|
211
|
+
import { defineComponent, getCurrentInstance, PropType, ref } from 'vue-demi'
|
|
194
212
|
import DlBrush from '../../components/DlBrush.vue'
|
|
195
213
|
import { DlTooltip } from '../../../../shared'
|
|
196
214
|
import {
|
|
@@ -255,16 +273,8 @@ export default defineComponent({
|
|
|
255
273
|
}
|
|
256
274
|
},
|
|
257
275
|
setup(props) {
|
|
276
|
+
const vm = getCurrentInstance()
|
|
258
277
|
const { variables } = useThemeVariables()
|
|
259
|
-
|
|
260
|
-
const tooltipState = ref<{
|
|
261
|
-
value?: number
|
|
262
|
-
xLabel?: string
|
|
263
|
-
yLabel?: string
|
|
264
|
-
x?: number
|
|
265
|
-
y?: number
|
|
266
|
-
visible?: boolean
|
|
267
|
-
} | null>(null)
|
|
268
278
|
const currentBrushState = ref<{ min: number; max: number }>({
|
|
269
279
|
min: 0,
|
|
270
280
|
max: props.matrix.length
|
|
@@ -290,6 +300,22 @@ export default defineComponent({
|
|
|
290
300
|
return `var(--dl-color-text${value < 0.5 ? '-darker' : ''}-buttons)`
|
|
291
301
|
}
|
|
292
302
|
|
|
303
|
+
const calculateXAxisElOffset = (index: number): number[] => {
|
|
304
|
+
let el = vm.refs[`xAxis-${index}`] as HTMLElement
|
|
305
|
+
if (!el) return null
|
|
306
|
+
if (Array.isArray(el)) {
|
|
307
|
+
el = el[0]
|
|
308
|
+
}
|
|
309
|
+
const height = el.clientHeight
|
|
310
|
+
const offsetHeight = -1 * (height / 2)
|
|
311
|
+
return [0, offsetHeight]
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const debouncedCalculateXAxisElOffset = debounce(
|
|
315
|
+
calculateXAxisElOffset,
|
|
316
|
+
100
|
|
317
|
+
)
|
|
318
|
+
|
|
293
319
|
return {
|
|
294
320
|
resizeObserver,
|
|
295
321
|
variables,
|
|
@@ -297,7 +323,9 @@ export default defineComponent({
|
|
|
297
323
|
getCellTextColor,
|
|
298
324
|
cellWidth,
|
|
299
325
|
currentBrushState,
|
|
300
|
-
rotateXLabels
|
|
326
|
+
rotateXLabels,
|
|
327
|
+
calculateXAxisElOffset,
|
|
328
|
+
debouncedCalculateXAxisElOffset
|
|
301
329
|
}
|
|
302
330
|
},
|
|
303
331
|
computed: {
|
|
@@ -343,18 +371,14 @@ export default defineComponent({
|
|
|
343
371
|
watch: {
|
|
344
372
|
matrix: {
|
|
345
373
|
handler(value) {
|
|
346
|
-
this.currentBrushState.max = value.length
|
|
347
|
-
this
|
|
374
|
+
this.currentBrushState.max = Math.min(10, value.length)
|
|
375
|
+
this.$nextTick(() => {
|
|
376
|
+
this.resizeMatrix()
|
|
377
|
+
})
|
|
348
378
|
}
|
|
349
379
|
},
|
|
350
380
|
currentBrushState() {
|
|
351
|
-
|
|
352
|
-
...this.visibleLabels.map(
|
|
353
|
-
(el: DlConfusionMatrixLabel) =>
|
|
354
|
-
(isObject(el) ? el.title : `${el}`).length
|
|
355
|
-
)
|
|
356
|
-
)
|
|
357
|
-
this.rotateXLabels = longest * 12 > getCellWidth()
|
|
381
|
+
this.calculateRotatedXLabels()
|
|
358
382
|
},
|
|
359
383
|
isEmpty(val) {
|
|
360
384
|
this.handleResizeObserver({ dispose: !val })
|
|
@@ -365,17 +389,25 @@ export default defineComponent({
|
|
|
365
389
|
if (this.isEmpty) return
|
|
366
390
|
|
|
367
391
|
this.handleResizeObserver()
|
|
392
|
+
this.$nextTick(() => {
|
|
393
|
+
setTimeout(() => {
|
|
394
|
+
this.calculateRotatedXLabels()
|
|
395
|
+
this.updateBrush(this, this.currentBrushState)
|
|
396
|
+
}, 300)
|
|
397
|
+
})
|
|
398
|
+
},
|
|
399
|
+
beforeUnmount() {
|
|
400
|
+
this.handleResizeObserver({ dispose: true })
|
|
368
401
|
},
|
|
369
402
|
methods: {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
return [0, offsetHeight]
|
|
403
|
+
calculateRotatedXLabels() {
|
|
404
|
+
const longest = Math.max(
|
|
405
|
+
...this.visibleLabels.map(
|
|
406
|
+
(el: DlConfusionMatrixLabel) =>
|
|
407
|
+
(isObject(el) ? el.title : `${el}`).length
|
|
408
|
+
)
|
|
409
|
+
)
|
|
410
|
+
this.rotateXLabels = longest * 12 > getCellWidth()
|
|
379
411
|
},
|
|
380
412
|
handleResizeObserver(options: { dispose?: boolean } = {}) {
|
|
381
413
|
const { dispose } = options
|
|
@@ -481,6 +513,7 @@ export default defineComponent({
|
|
|
481
513
|
max-height: 100px;
|
|
482
514
|
&__element {
|
|
483
515
|
width: var(--cell-dimensions);
|
|
516
|
+
max-width: 100px;
|
|
484
517
|
overflow: hidden;
|
|
485
518
|
text-overflow: ellipsis;
|
|
486
519
|
&--text {
|
|
@@ -532,7 +565,7 @@ export default defineComponent({
|
|
|
532
565
|
grid-template-columns: repeat(var(--matrix-rows), 1fr);
|
|
533
566
|
|
|
534
567
|
&__cell {
|
|
535
|
-
font-size: 12px;
|
|
568
|
+
font-size: max(calc(var(--cell-dimensions) * 0.1), 12px);
|
|
536
569
|
cursor: pointer;
|
|
537
570
|
border: 1px solid var(--dl-color-separator);
|
|
538
571
|
box-sizing: border-box;
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
</template>
|
|
56
56
|
|
|
57
57
|
<script lang="ts">
|
|
58
|
-
import { ref, computed, watch, defineComponent } from 'vue-demi'
|
|
58
|
+
import { ref, computed, watch, defineComponent, PropType } from 'vue-demi'
|
|
59
59
|
|
|
60
60
|
import useSlider, {
|
|
61
61
|
useSliderProps,
|
|
@@ -91,7 +91,12 @@ export default defineComponent({
|
|
|
91
91
|
}),
|
|
92
92
|
validator: (v: Object) => 'min' in v && 'max' in v
|
|
93
93
|
},
|
|
94
|
-
|
|
94
|
+
value: {
|
|
95
|
+
type: Object as PropType<{ min: number; max: number }>,
|
|
96
|
+
default: null,
|
|
97
|
+
required: false,
|
|
98
|
+
validator: (v: Object) => 'min' in v && 'max' in v
|
|
99
|
+
},
|
|
95
100
|
dragRange: Boolean,
|
|
96
101
|
dragOnlyRange: Boolean,
|
|
97
102
|
trackColor: {
|
|
@@ -102,6 +107,10 @@ export default defineComponent({
|
|
|
102
107
|
type: Number,
|
|
103
108
|
default: null
|
|
104
109
|
},
|
|
110
|
+
minRange: {
|
|
111
|
+
type: Number,
|
|
112
|
+
default: null
|
|
113
|
+
},
|
|
105
114
|
selectionColor: {
|
|
106
115
|
type: String,
|
|
107
116
|
default: 'dl-color-chart-brush'
|
|
@@ -120,7 +129,8 @@ export default defineComponent({
|
|
|
120
129
|
const rootRef = ref(null)
|
|
121
130
|
const curMinRatio = ref(0)
|
|
122
131
|
const curMaxRatio = ref(0)
|
|
123
|
-
|
|
132
|
+
|
|
133
|
+
const model = ref(props.value ?? { min: 0, max: 0 })
|
|
124
134
|
|
|
125
135
|
function normalizeModel() {
|
|
126
136
|
model.value.min =
|
|
@@ -152,6 +162,15 @@ export default defineComponent({
|
|
|
152
162
|
normalizeModel
|
|
153
163
|
)
|
|
154
164
|
|
|
165
|
+
watch(
|
|
166
|
+
() => props.value,
|
|
167
|
+
(v) => {
|
|
168
|
+
if (v !== null) {
|
|
169
|
+
model.value = v
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
)
|
|
173
|
+
|
|
155
174
|
normalizeModel()
|
|
156
175
|
|
|
157
176
|
const isMobile = computed(() => isMobileOrTablet())
|
|
@@ -392,7 +411,8 @@ export default defineComponent({
|
|
|
392
411
|
break
|
|
393
412
|
}
|
|
394
413
|
|
|
395
|
-
if (pos.max - pos.min
|
|
414
|
+
if (props.maxRange && pos.max - pos.min > props.maxRange) return
|
|
415
|
+
if (props.minRange && pos.max - pos.min < props.minRange) return
|
|
396
416
|
|
|
397
417
|
model.value =
|
|
398
418
|
model.value.min === null || model.value.max === null
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export interface DlConfusionMatrixCell {
|
|
2
2
|
value: number
|
|
3
|
-
unnormalizedValue
|
|
4
|
-
xLabel
|
|
5
|
-
yLabel
|
|
6
|
-
x
|
|
7
|
-
y
|
|
3
|
+
unnormalizedValue?: number
|
|
4
|
+
xLabel?: string | DlConfusionMatrixLabel
|
|
5
|
+
yLabel?: string | DlConfusionMatrixLabel
|
|
6
|
+
x?: number
|
|
7
|
+
y?: number
|
|
8
8
|
link?: string
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -1,67 +1,89 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<dl-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
3
|
+
<dl-accordion title="Matrix">
|
|
4
|
+
<dl-confusion-matrix
|
|
5
|
+
:matrix="matrix"
|
|
6
|
+
:labels="labels"
|
|
7
|
+
/>
|
|
8
|
+
</dl-accordion>
|
|
9
|
+
<dl-accordion title="one label matrix">
|
|
10
|
+
<dl-confusion-matrix
|
|
11
|
+
:matrix="oneLabelMatrix"
|
|
12
|
+
:labels="oneLabelLabels"
|
|
13
|
+
/>
|
|
14
|
+
</dl-accordion>
|
|
15
|
+
<dl-accordion title="two label matrix">
|
|
16
|
+
<dl-confusion-matrix
|
|
17
|
+
:matrix="twoLabelMatrix"
|
|
18
|
+
:labels="twoLabelLabels"
|
|
19
|
+
/>
|
|
20
|
+
</dl-accordion>
|
|
21
|
+
<dl-accordion title="a hundred label matrix">
|
|
22
|
+
<dl-confusion-matrix
|
|
23
|
+
:matrix="aHundredLabelMatrix"
|
|
24
|
+
:labels="aHundredLabelLabels"
|
|
25
|
+
/>
|
|
26
|
+
</dl-accordion>
|
|
27
|
+
<dl-accordion title="empty state">
|
|
28
|
+
<dl-confusion-matrix
|
|
29
|
+
:matrix="matrix"
|
|
30
|
+
:labels="labels"
|
|
31
|
+
is-empty
|
|
32
|
+
:empty-state-props="{
|
|
33
|
+
responsive: true,
|
|
34
|
+
style: 'min-height: 350px;',
|
|
35
|
+
bgSize: '130px',
|
|
36
|
+
bgImage: `url(https://raw.githubusercontent.com/dataloop-ai/icons/main/assets/usage.svg)`,
|
|
37
|
+
title: 'Lorem ipsum',
|
|
38
|
+
subtitle:
|
|
39
|
+
'Lorem ipsum dolor sit amet consectetur. Senectus condimentum dolor sit',
|
|
40
|
+
info: 'To learn more about this analytics, read our documentation.'
|
|
41
|
+
}"
|
|
42
|
+
>
|
|
43
|
+
<template #links="">
|
|
44
|
+
<div style="display: flex; gap: 5px; padding: 0 20px">
|
|
45
|
+
<dl-button
|
|
46
|
+
padding="0px"
|
|
47
|
+
icon="icon-dl-sdk-documentation"
|
|
48
|
+
flat
|
|
49
|
+
uppercase
|
|
50
|
+
label="SDK"
|
|
51
|
+
/>
|
|
52
|
+
<div class="break" />
|
|
53
|
+
<dl-button
|
|
54
|
+
padding="0px"
|
|
55
|
+
icon="icon-dl-file"
|
|
56
|
+
flat
|
|
57
|
+
label="Documentation"
|
|
58
|
+
/>
|
|
59
|
+
<div class="break" />
|
|
60
|
+
<dl-button
|
|
61
|
+
padding="0px"
|
|
62
|
+
icon="icon-dl-youtube"
|
|
63
|
+
flat
|
|
64
|
+
label="Video"
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
</template>
|
|
68
|
+
</dl-confusion-matrix>
|
|
69
|
+
</dl-accordion>
|
|
49
70
|
</div>
|
|
50
71
|
</template>
|
|
51
72
|
|
|
52
73
|
<script lang="ts">
|
|
53
74
|
import { defineComponent } from 'vue-demi'
|
|
54
|
-
import { DlConfusionMatrix, DlButton } from '../components'
|
|
75
|
+
import { DlConfusionMatrix, DlButton, DlAccordion } from '../components'
|
|
76
|
+
import { DlConfusionMatrixCell } from '../types'
|
|
55
77
|
|
|
56
78
|
const getLink = (number: number) => {
|
|
57
79
|
return `www.confusion-matrix.com/cell-${number}`
|
|
58
80
|
}
|
|
59
81
|
|
|
60
82
|
const getMatrix = (size: number) => {
|
|
61
|
-
const newMatrix = []
|
|
83
|
+
const newMatrix: DlConfusionMatrixCell[][] = []
|
|
62
84
|
|
|
63
85
|
for (let i = 0; i < size; i++) {
|
|
64
|
-
const row = []
|
|
86
|
+
const row: DlConfusionMatrixCell[] = []
|
|
65
87
|
for (let j = 0; j < size; j++) {
|
|
66
88
|
const value = Math.floor(Math.random() * 10)
|
|
67
89
|
row.push({
|
|
@@ -96,14 +118,34 @@ const getLabels = (size: number) => {
|
|
|
96
118
|
export default defineComponent({
|
|
97
119
|
components: {
|
|
98
120
|
DlConfusionMatrix,
|
|
99
|
-
DlButton
|
|
121
|
+
DlButton,
|
|
122
|
+
DlAccordion
|
|
100
123
|
},
|
|
101
124
|
setup() {
|
|
102
125
|
const SIZE = 10
|
|
103
126
|
const matrix = getMatrix(SIZE)
|
|
104
127
|
const labels = getLabels(SIZE)
|
|
105
128
|
|
|
106
|
-
|
|
129
|
+
const oneLabelMatrix = getMatrix(1)
|
|
130
|
+
const oneLabelLabels = getLabels(1)
|
|
131
|
+
|
|
132
|
+
const twoLabelMatrix = getMatrix(2)
|
|
133
|
+
const twoLabelLabels = getLabels(2)
|
|
134
|
+
|
|
135
|
+
const aHundredLabelMatrix = getMatrix(100)
|
|
136
|
+
const aHundredLabelLabels = getLabels(100)
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
matrix,
|
|
140
|
+
labels,
|
|
141
|
+
getLink,
|
|
142
|
+
oneLabelMatrix,
|
|
143
|
+
oneLabelLabels,
|
|
144
|
+
aHundredLabelMatrix,
|
|
145
|
+
aHundredLabelLabels,
|
|
146
|
+
twoLabelMatrix,
|
|
147
|
+
twoLabelLabels
|
|
148
|
+
}
|
|
107
149
|
}
|
|
108
150
|
})
|
|
109
151
|
</script>
|