@dataloop-ai/components 0.18.7 → 0.18.9

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dataloop-ai/components",
3
- "version": "0.18.7",
3
+ "version": "0.18.9",
4
4
  "exports": {
5
5
  ".": "./index.ts",
6
6
  "./models": "./models.ts",
@@ -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
- <span
128
+ <div
122
129
  v-for="(label, index) in visibleLabels"
123
- :ref="`xAxis-${index}`"
124
130
  :key="index"
125
- class="x-axis__element"
126
- :style="`${
127
- !labelImages[0]
128
- ? `transform: rotate(${
129
- rotateXLabels ? '70' : '0'
130
- }deg); line-height: ${
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 class="x-axis__element--text">
137
- <img
138
- v-if="labelImages[0]"
139
- class="legend-avatar"
140
- :src="labelImages[index]"
141
- >
142
- <span v-else>
143
- {{ label }}
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
- <dl-tooltip
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
- :max-range="2"
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
@@ -272,6 +282,7 @@ export default defineComponent({
272
282
  const cellWidth = ref<number | null>(null)
273
283
  const rotateXLabels = ref(true)
274
284
  const resizeObserver = ref<ResizeObserver>(null)
285
+ const isDisposed = ref(false)
275
286
 
276
287
  const getCellBackground = (value: number = 1): string => {
277
288
  const object: { [key: string]: any } = {
@@ -290,6 +301,25 @@ export default defineComponent({
290
301
  return `var(--dl-color-text${value < 0.5 ? '-darker' : ''}-buttons)`
291
302
  }
292
303
 
304
+ const calculateXAxisElOffset = (index: number): number[] => {
305
+ let el = vm.refs[`xAxis-${index}`] as HTMLElement
306
+ if (!el) return null
307
+ if (Array.isArray(el)) {
308
+ el = el[0]
309
+ }
310
+ if (!el) {
311
+ return [0, 0]
312
+ }
313
+ const height = el.clientHeight
314
+ const offsetHeight = -1 * (height / 2)
315
+ return [0, offsetHeight]
316
+ }
317
+
318
+ const debouncedCalculateXAxisElOffset = debounce(
319
+ calculateXAxisElOffset,
320
+ 100
321
+ )
322
+
293
323
  return {
294
324
  resizeObserver,
295
325
  variables,
@@ -297,7 +327,10 @@ export default defineComponent({
297
327
  getCellTextColor,
298
328
  cellWidth,
299
329
  currentBrushState,
300
- rotateXLabels
330
+ rotateXLabels,
331
+ calculateXAxisElOffset,
332
+ debouncedCalculateXAxisElOffset,
333
+ isDisposed
301
334
  }
302
335
  },
303
336
  computed: {
@@ -343,41 +376,49 @@ export default defineComponent({
343
376
  watch: {
344
377
  matrix: {
345
378
  handler(value) {
346
- this.currentBrushState.max = value.length
347
- this.resizeMatrix()
379
+ this.currentBrushState.max = Math.min(10, value.length)
380
+ this.$nextTick(() => {
381
+ this.resizeMatrix()
382
+ })
348
383
  }
349
384
  },
350
385
  currentBrushState() {
351
- const longest = Math.max(
352
- ...this.visibleLabels.map(
353
- (el: DlConfusionMatrixLabel) =>
354
- (isObject(el) ? el.title : `${el}`).length
355
- )
356
- )
357
- this.rotateXLabels = longest * 12 > getCellWidth()
386
+ this.calculateRotatedXLabels()
358
387
  },
359
388
  isEmpty(val) {
360
389
  this.handleResizeObserver({ dispose: !val })
361
390
  }
362
391
  },
363
392
  mounted() {
393
+ this.isDisposed = false
364
394
  if (!this.isValidMatrix) return
365
395
  if (this.isEmpty) return
366
396
 
367
397
  this.handleResizeObserver()
398
+ this.$nextTick(() => {
399
+ setTimeout(() => {
400
+ if (this.isDisposed) return
401
+ this.calculateRotatedXLabels()
402
+ this.updateBrush(this, this.currentBrushState)
403
+ }, 300)
404
+ })
405
+ },
406
+ beforeUnmount() {
407
+ this.isDisposed = true
408
+ this.handleResizeObserver({ dispose: true })
368
409
  },
369
410
  methods: {
370
- calculateXAxisElOffset(index: number): number[] {
371
- let el = this.$refs[`xAxis-${index}`] as HTMLElement
372
- if (!el) return null
373
- if (Array.isArray(el)) {
374
- el = el[0]
375
- }
376
- const height = el.clientHeight
377
- const offsetHeight = -1 * (height / 2)
378
- return [0, offsetHeight]
411
+ calculateRotatedXLabels() {
412
+ const longest = Math.max(
413
+ ...this.visibleLabels.map(
414
+ (el: DlConfusionMatrixLabel) =>
415
+ (isObject(el) ? el.title : `${el}`).length
416
+ )
417
+ )
418
+ this.rotateXLabels = longest * 12 > getCellWidth()
379
419
  },
380
420
  handleResizeObserver(options: { dispose?: boolean } = {}) {
421
+ if (this.isDisposed) return
381
422
  const { dispose } = options
382
423
  if (dispose && this.resizeObserver) {
383
424
  this.resizeObserver.unobserve(this.$refs.wrapper as Element)
@@ -393,6 +434,7 @@ export default defineComponent({
393
434
  }
394
435
  },
395
436
  resizeMatrix() {
437
+ if (this.isDisposed) return
396
438
  const colorSpectrum = this.$refs.colorSpectrum as HTMLElement
397
439
  const verticalWrapper = this.$refs.verticalWrapper as HTMLElement
398
440
  const labelY = this.$refs.labelY as HTMLElement
@@ -481,6 +523,7 @@ export default defineComponent({
481
523
  max-height: 100px;
482
524
  &__element {
483
525
  width: var(--cell-dimensions);
526
+ max-width: 100px;
484
527
  overflow: hidden;
485
528
  text-overflow: ellipsis;
486
529
  &--text {
@@ -532,7 +575,7 @@ export default defineComponent({
532
575
  grid-template-columns: repeat(var(--matrix-rows), 1fr);
533
576
 
534
577
  &__cell {
535
- font-size: 12px;
578
+ font-size: max(calc(var(--cell-dimensions) * 0.1), 12px);
536
579
  cursor: pointer;
537
580
  border: 1px solid var(--dl-color-separator);
538
581
  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
- const model = ref({ min: 0, max: 0 })
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 < props.maxRange) return
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: number
4
- xLabel: string | DlConfusionMatrixLabel
5
- yLabel: string | DlConfusionMatrixLabel
6
- x: number
7
- y: number
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
 
@@ -155,6 +155,7 @@
155
155
  :disabled="disabled || readonly"
156
156
  :arrow-nav-items="options"
157
157
  :max-height="dropdownMaxHeight"
158
+ :trigger-percentage="triggerPercentage"
158
159
  @show="onMenuOpen"
159
160
  @hide="closeMenu"
160
161
  @highlightedIndex="setHighlightedIndex"
@@ -389,7 +390,14 @@ export default defineComponent({
389
390
  clearButtonTooltip: { type: Boolean, default: false },
390
391
  dropdownMaxHeight: { type: String, default: '30vh' },
391
392
  preserveSearch: { type: Boolean, default: false },
392
- disabledTooltip: { type: String, default: 'Disabled' }
393
+ disabledTooltip: { type: String, default: 'Disabled' },
394
+ /**
395
+ * the % of the select element to display the menu
396
+ */
397
+ triggerPercentage: {
398
+ type: Number,
399
+ default: 1
400
+ }
393
401
  },
394
402
  emits: [
395
403
  'search-focus',
@@ -37,7 +37,10 @@ import {
37
37
  } from 'vue-demi'
38
38
 
39
39
  import useWindowSize from '../../../hooks/use-window-size'
40
- import useAnchor, { useAnchorProps } from '../../../hooks/use-anchor'
40
+ import useAnchor, {
41
+ CheckAnchorElVisibility,
42
+ useAnchorProps
43
+ } from '../../../hooks/use-anchor'
41
44
  import useScrollTarget from '../../../hooks/use-scroll-target'
42
45
  import useModelToggle, {
43
46
  useModelToggleProps,
@@ -149,6 +152,13 @@ export default defineComponent({
149
152
  zIndex: {
150
153
  type: [Number, String],
151
154
  default: 'var(--dl-z-index-menu)'
155
+ },
156
+ /**
157
+ * the % of the parent element that triggers the tooltips visibility
158
+ */
159
+ triggerPercentage: {
160
+ type: Number,
161
+ default: 1
152
162
  }
153
163
  },
154
164
 
@@ -373,16 +383,6 @@ export default defineComponent({
373
383
  hide(evt)
374
384
  }
375
385
 
376
- function CheckAnchorElVisiblity(domElement: any) {
377
- return new Promise((resolve) => {
378
- const o = new IntersectionObserver(([entry]) => {
379
- resolve(entry.intersectionRatio === 1)
380
- o.disconnect()
381
- })
382
- o.observe(domElement)
383
- })
384
- }
385
-
386
386
  const updatePosition = async () => {
387
387
  const el = innerRef.value
388
388
 
@@ -390,8 +390,11 @@ export default defineComponent({
390
390
  return
391
391
  }
392
392
 
393
- const isAnchorElVisible = await CheckAnchorElVisiblity(
394
- anchorEl.value
393
+ const isAnchorElVisible = await CheckAnchorElVisibility(
394
+ anchorEl.value,
395
+ {
396
+ triggerPercentage: props.triggerPercentage
397
+ }
395
398
  )
396
399
 
397
400
  if (!isAnchorElVisible) {
@@ -34,7 +34,10 @@ import {
34
34
  PropType,
35
35
  onMounted
36
36
  } from 'vue-demi'
37
- import useAnchor, { useAnchorProps } from '../../../hooks/use-anchor'
37
+ import useAnchor, {
38
+ CheckAnchorElVisibility,
39
+ useAnchorProps
40
+ } from '../../../hooks/use-anchor'
38
41
  import useModelToggle, { AnchorEvent } from '../../../hooks/use-model-toggle'
39
42
  import usePortal from '../../../hooks/use-portal'
40
43
  import useScrollTarget from '../../../hooks/use-scroll-target'
@@ -272,17 +275,6 @@ export default defineComponent({
272
275
  cleanEvt(anchorEvents, 'tooltipTemp')
273
276
  }
274
277
 
275
- function CheckAnchorElVisiblity(domElement: any) {
276
- const intersectionRatio = props.triggerPercentage ?? 1
277
- return new Promise((resolve) => {
278
- const o = new IntersectionObserver(([entry]) => {
279
- resolve(entry.intersectionRatio >= intersectionRatio)
280
- o.disconnect()
281
- })
282
- o.observe(domElement)
283
- })
284
- }
285
-
286
278
  async function updatePosition() {
287
279
  const el = innerRef.value
288
280
 
@@ -290,8 +282,11 @@ export default defineComponent({
290
282
  return
291
283
  }
292
284
 
293
- const isAnchorElVisible = await CheckAnchorElVisiblity(
294
- anchorEl.value
285
+ const isAnchorElVisible = await CheckAnchorElVisibility(
286
+ anchorEl.value,
287
+ {
288
+ triggerPercentage: props.triggerPercentage
289
+ }
295
290
  )
296
291
  if (!isAnchorElVisible) {
297
292
  hide()
@@ -1,67 +1,89 @@
1
1
  <template>
2
2
  <div>
3
- <dl-confusion-matrix
4
- :matrix="matrix"
5
- :labels="labels"
6
- />
7
-
8
- <dl-confusion-matrix
9
- :matrix="matrix"
10
- :labels="labels"
11
- is-empty
12
- :empty-state-props="{
13
- responsive: true,
14
- style: 'min-height: 350px;',
15
- bgSize: '130px',
16
- bgImage: `url(https://raw.githubusercontent.com/dataloop-ai/icons/main/assets/usage.svg)`,
17
- title: 'Lorem ipsum',
18
- subtitle:
19
- 'Lorem ipsum dolor sit amet consectetur. Senectus condimentum dolor sit',
20
- info: 'To learn more about this analytics, read our documentation.'
21
- }"
22
- >
23
- <template #links="">
24
- <div style="display: flex; gap: 5px; padding: 0 20px">
25
- <dl-button
26
- padding="0px"
27
- icon="icon-dl-sdk-documentation"
28
- flat
29
- uppercase
30
- label="SDK"
31
- />
32
- <div class="break" />
33
- <dl-button
34
- padding="0px"
35
- icon="icon-dl-file"
36
- flat
37
- label="Documentation"
38
- />
39
- <div class="break" />
40
- <dl-button
41
- padding="0px"
42
- icon="icon-dl-youtube"
43
- flat
44
- label="Video"
45
- />
46
- </div>
47
- </template>
48
- </dl-confusion-matrix>
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
- return { matrix, labels, getLink }
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>
@@ -32,6 +32,21 @@ export const useAnchorProps = {
32
32
  contextMenu: Boolean
33
33
  }
34
34
 
35
+ export function CheckAnchorElVisibility(
36
+ domElement: any,
37
+ options: { triggerPercentage?: number } = {}
38
+ ) {
39
+ const { triggerPercentage } = options
40
+ const intersectionRatio = triggerPercentage ?? 1
41
+ return new Promise((resolve) => {
42
+ const o = new IntersectionObserver(([entry]) => {
43
+ resolve(entry.intersectionRatio >= intersectionRatio)
44
+ o.disconnect()
45
+ })
46
+ o.observe(domElement)
47
+ })
48
+ }
49
+
35
50
  export default function useAnchor({
36
51
  configureAnchorEl
37
52
  }: {