@dataloop-ai/components 0.13.19 → 0.14.4

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.
Files changed (94) hide show
  1. package/.nvmrc +1 -0
  2. package/README.md +3 -1
  3. package/package.json +19 -17
  4. package/src/assets/globals.scss +38 -3
  5. package/src/assets/grid.scss +9 -0
  6. package/src/components/DlAccordion/DlAccordion.vue +4 -4
  7. package/src/components/DlAlert.vue +6 -6
  8. package/src/components/DlChart/BrushThumb.vue +83 -0
  9. package/src/components/DlChart/DlBarChart.vue +545 -0
  10. package/src/components/DlChart/DlBrush.vue +475 -0
  11. package/src/components/DlChart/DlChartLabels.vue +279 -0
  12. package/src/components/DlChart/DlChartLegend.vue +141 -0
  13. package/src/components/DlChart/DlColumnChart.vue +555 -0
  14. package/src/components/DlChart/DlLineChart.vue +644 -0
  15. package/src/components/DlChart/DlScrollBar.vue +147 -0
  16. package/src/components/DlChart/Doughnut/DlDoughnutChart.vue +448 -0
  17. package/src/components/DlChart/Doughnut/DlDoughnutChartLegend.vue +281 -0
  18. package/src/components/DlChart/Doughnut/DlDoughnutChartWidget.vue +64 -0
  19. package/src/components/DlChart/Doughnut/types/TDoughnutChartAnimation.ts +4 -0
  20. package/src/components/DlChart/Doughnut/types/TDoughnutChartData.ts +16 -0
  21. package/src/components/DlChart/Doughnut/types/TDoughnutChartOptions.ts +11 -0
  22. package/src/components/DlChart/Doughnut/types/TDoughnutChartProps.ts +8 -0
  23. package/src/components/DlChart/Doughnut/types/TDoughnutWithOriginalColor.ts +13 -0
  24. package/src/components/DlChart/chart.ts +122 -0
  25. package/src/components/DlChart/index.ts +36 -0
  26. package/src/components/DlChart/props.ts +348 -0
  27. package/src/components/DlChart/typedCharts.ts +88 -0
  28. package/src/components/DlChart/types.ts +63 -0
  29. package/src/components/DlChart/utils.ts +153 -0
  30. package/src/components/DlChip/DlChip.vue +40 -13
  31. package/src/components/DlCounters.vue +31 -7
  32. package/src/components/DlDatePicker/DlCalendar.vue +22 -10
  33. package/src/components/DlDatePicker/DlDatePicker.vue +8 -5
  34. package/src/components/DlDateTimeRange/types.ts +2 -2
  35. package/src/components/DlDropdownButton.vue +5 -3
  36. package/src/components/DlMenu/DlMenu.vue +4 -2
  37. package/src/components/DlPagination/RowsSelector.vue +15 -2
  38. package/src/components/DlPopup/DlPopup.vue +0 -1
  39. package/src/components/DlRange/DlRange.vue +3 -2
  40. package/src/components/DlSearch.vue +1 -1
  41. package/src/components/DlSelect/DlSelect.vue +3 -2
  42. package/src/components/DlSlider/sliderStyles.scss +4 -0
  43. package/src/components/DlSlider/useSlider.ts +39 -12
  44. package/src/components/DlSmartSearch/DlSuggestionsDropdown.vue +1 -1
  45. package/src/components/DlSpinner.vue +259 -0
  46. package/src/components/DlTable/DlTable.vue +4 -1
  47. package/src/components/DlTable/hooks/tablePagination.ts +8 -2
  48. package/src/components/DlTextArea.vue +9 -0
  49. package/src/components/DlTextInput.vue +4 -2
  50. package/src/components/DlThemeProvider.vue +22 -13
  51. package/src/components/DlToastMessage/api/useToast.ts +23 -0
  52. package/src/components/DlToastMessage/components/ToastComponent.vue +279 -0
  53. package/src/components/DlToastMessage/index.ts +5 -0
  54. package/src/components/DlToastMessage/types.ts +4 -0
  55. package/src/components/DlToastMessage/utils/config.ts +17 -0
  56. package/src/components/DlToastMessage/utils/render.ts +56 -0
  57. package/src/components/DlTypography.vue +1 -1
  58. package/src/components/DlWidget/DlGrid.vue +33 -0
  59. package/src/components/DlWidget/DlGridRow.vue +32 -0
  60. package/src/components/DlWidget/DlWidget.vue +202 -11
  61. package/src/components/DlWidget/index.ts +2 -2
  62. package/src/components/DlWidget/utils.ts +26 -19
  63. package/src/components/index.ts +8 -3
  64. package/src/demo/BarChartDemo.vue +77 -0
  65. package/src/demo/ColumnChartDemo.vue +230 -0
  66. package/src/demo/DlButtonDemo.vue +1 -1
  67. package/src/demo/DlChartDoughnutDemo.vue +229 -0
  68. package/src/demo/DlChipDemo.vue +42 -18
  69. package/src/demo/DlDialogBoxDemo.vue +4 -4
  70. package/src/demo/DlDropdownButtonDemo.vue +1 -1
  71. package/src/demo/DlLineChartDemo.vue +375 -0
  72. package/src/demo/DlMenuDemo.vue +1 -1
  73. package/src/demo/DlOptionGroupDemo.vue +1 -1
  74. package/src/demo/DlSelectDemo.vue +1 -1
  75. package/src/demo/DlSpinnerDemo.vue +20 -0
  76. package/src/demo/DlTableDemo.vue +13 -94
  77. package/src/demo/DlToastMessageDemo.vue +143 -0
  78. package/src/demo/DlWidgetDemo.vue +105 -143
  79. package/src/demo/index.ts +20 -2
  80. package/src/hooks/use-theme.ts +19 -0
  81. package/src/utils/abbreviate-to-string.ts +14 -0
  82. package/src/utils/colors.ts +47 -0
  83. package/src/utils/getRootStyles.ts +1 -1
  84. package/src/utils/index.ts +1 -0
  85. package/src/utils/position-engine.ts +11 -2
  86. package/src/utils/swapNodes.ts +30 -0
  87. package/src/utils/update-key.ts +90 -0
  88. package/tsconfig.json +0 -1
  89. package/vite.config.ts +17 -0
  90. package/Dockerfile +0 -12
  91. package/jest.config.js +0 -16
  92. package/jest.setup.js +0 -59
  93. package/src/components/DlWidget/DlWidgetGrid.vue +0 -360
  94. package/storybook.js +0 -8
@@ -0,0 +1,545 @@
1
+ <template>
2
+ <div :class="chartWrapperClasses">
3
+ <div
4
+ class="canvas-container"
5
+ :style="`height: ${wrapperHeight}`"
6
+ >
7
+ <Bar
8
+ :id="id"
9
+ ref="barChart"
10
+ :class="chartClasses"
11
+ :style="chartStyles"
12
+ :data="chartData"
13
+ :options="chartOptions"
14
+ @mouseout="onChartLeave"
15
+ @wheel.native="handleChartScroll"
16
+ />
17
+ <dl-scroll-bar
18
+ v-if="maxItems > thisItemsInView"
19
+ :height="wrapperHeight"
20
+ :item-count="maxItems"
21
+ :items-in-view="thisItemsInView"
22
+ :position="scrollPosition"
23
+ @position-update="handleScrollUpdate"
24
+ />
25
+ </div>
26
+ <slot
27
+ v-bind="{ labels: xLabels, chartWidth }"
28
+ name="axe-x-labels"
29
+ />
30
+ <slot
31
+ v-bind="{
32
+ data: legendDatasets,
33
+ chartWidth,
34
+ onHide: hideData,
35
+ onHoverLegend,
36
+ onLeaveLegend,
37
+ ...legendProperties
38
+ }"
39
+ name="legend"
40
+ >
41
+ <dl-chart-legend
42
+ :datasets="legendDatasets"
43
+ :width="chartWidth"
44
+ :class="legendClasses"
45
+ :align-items="legendProperties.alignItems"
46
+ @hide="hideData"
47
+ @on-hover="onHoverLegend"
48
+ @on-leave="onLeaveLegend"
49
+ />
50
+ </slot>
51
+ </div>
52
+ </template>
53
+
54
+ <script lang="ts">
55
+ import { Bar } from './'
56
+ import { CommonProps, BarChartProps, defaultBarChartProps } from './props'
57
+ import { defineComponent, reactive, ref, watch, computed } from 'vue-demi'
58
+ import DlChartLegend from './DlChartLegend.vue'
59
+ import DlScrollBar from './DlScrollBar.vue'
60
+ import { updateKey } from '../../utils/update-key'
61
+ import {
62
+ Chart as ChartJS,
63
+ Title,
64
+ Tooltip,
65
+ Legend,
66
+ BarElement,
67
+ CategoryScale,
68
+ LinearScale,
69
+ PointElement,
70
+ LineElement,
71
+ BarControllerDatasetOptions
72
+ } from 'chart.js'
73
+ import type { Chart, ChartMeta, ChartDataset, ActiveElement } from 'chart.js'
74
+ import { isEqual, merge } from 'lodash'
75
+ import { rgba2hex, hexToRgbA, revertRGBAOpacity } from '../../utils'
76
+ import { useThemeVariables } from '../../hooks/use-theme'
77
+
78
+ ChartJS.register(
79
+ CategoryScale,
80
+ LinearScale,
81
+ BarElement,
82
+ Title,
83
+ Tooltip,
84
+ Legend,
85
+ PointElement,
86
+ LineElement
87
+ )
88
+ export default defineComponent({
89
+ name: 'DlBarChart',
90
+ components: {
91
+ Bar,
92
+ DlScrollBar,
93
+ DlChartLegend
94
+ },
95
+ props: {
96
+ ...CommonProps,
97
+ ...BarChartProps,
98
+ itemsInView: {
99
+ type: Number,
100
+ required: true
101
+ },
102
+ id: {
103
+ type: String,
104
+ default: null
105
+ }
106
+ },
107
+ setup(props) {
108
+ const { variables } = useThemeVariables()
109
+
110
+ const chartWidth = ref('100%')
111
+
112
+ const chartHoverDataset: { value: null | ChartMeta } = {
113
+ value: null
114
+ }
115
+
116
+ const thisItemsInView = computed(() => props.itemsInView - 1)
117
+
118
+ const onResize = (
119
+ chart: Chart,
120
+ size: { height: number; width: number }
121
+ ) => {
122
+ if (chart?.scales?.x?.width) {
123
+ chartWidth.value = `${parseInt(
124
+ chart.scales.x.width as unknown as string
125
+ )}px`
126
+ }
127
+ }
128
+
129
+ const replaceColor = (key: keyof typeof variables) =>
130
+ variables[key] || key
131
+
132
+ const chartData = ref(
133
+ updateKey(
134
+ updateKey(props.data, 'backgroundColor', replaceColor),
135
+ 'hoverBackgroundColor',
136
+ replaceColor
137
+ )
138
+ )
139
+
140
+ const barChart = ref()
141
+
142
+ const scrollPosition = ref(0)
143
+
144
+ const chart = computed(() => {
145
+ return barChart.value?.chart?.value || {}
146
+ })
147
+
148
+ let scroll: number = 0
149
+ let steps: number = 0
150
+
151
+ const chartWrapperClasses = computed(() => {
152
+ const classes = 'dl-bar-chart-wrapper'
153
+
154
+ if (props.rootClass) {
155
+ classes.concat(' ', props.rootClass)
156
+ }
157
+
158
+ return classes
159
+ })
160
+
161
+ const chartClasses = computed(() => {
162
+ const classes = 'dl-bar-chart'
163
+
164
+ if (props.chartClass) {
165
+ classes.concat(' ', props.chartClass)
166
+ }
167
+
168
+ return classes
169
+ })
170
+
171
+ const legendClasses = computed(() => {
172
+ const classes = 'dl-legend'
173
+
174
+ if (props.legendClass) {
175
+ classes.concat(' ', props.legendClass)
176
+ }
177
+
178
+ return classes
179
+ })
180
+
181
+ const legendProperties = computed(() => {
182
+ return merge(defaultBarChartProps.legendProps, props.legendProps)
183
+ })
184
+
185
+ const legendDatasets = ref(
186
+ props.legendProps?.datasets?.length > 0
187
+ ? props.legendProps.datasets
188
+ : chartData.value?.datasets || []
189
+ )
190
+
191
+ const onChartLeave = () => {
192
+ if (chartHoverDataset.value) {
193
+ const filteredItems = chart.value.data.datasets
194
+ .map((d: ChartDataset, i: number) => ({
195
+ ...d,
196
+ index: i
197
+ }))
198
+ .filter(
199
+ (dataset: ChartDataset) =>
200
+ dataset.label !== chartHoverDataset.value.label
201
+ )
202
+
203
+ for (const dataset of filteredItems) {
204
+ chart.value.data.datasets[dataset.index].backgroundColor =
205
+ rgba2hex(revertRGBAOpacity(dataset.backgroundColor))
206
+ }
207
+ chart.value.update()
208
+ chartHoverDataset.value = null
209
+ }
210
+ }
211
+
212
+ const onHover = (
213
+ event: Event,
214
+ items: ActiveElement[],
215
+ chartJS: Chart
216
+ ) => {
217
+ if (event.type !== 'mousemove') {
218
+ return
219
+ }
220
+ if (
221
+ items.length === 0 ||
222
+ chartJS.getElementsAtEventForMode(
223
+ event,
224
+ 'nearest',
225
+ {
226
+ intersect: true
227
+ },
228
+ true
229
+ ).length === 0
230
+ ) {
231
+ if (chartHoverDataset.value) {
232
+ const filteredItems = chartJS.data.datasets
233
+ .map((d: ChartDataset, i: number) => ({
234
+ ...(d as ChartDataset),
235
+ index: i
236
+ }))
237
+ .filter(
238
+ (dataset: ChartDataset) =>
239
+ dataset.label !== chartHoverDataset.value.label
240
+ )
241
+
242
+ for (const dataset of filteredItems) {
243
+ chartJS.data.datasets[dataset.index].backgroundColor =
244
+ rgba2hex(
245
+ revertRGBAOpacity(
246
+ dataset.backgroundColor as string
247
+ )
248
+ )
249
+ }
250
+ chartJS.update()
251
+
252
+ chartHoverDataset.value = null
253
+ }
254
+ return
255
+ } else {
256
+ const item = items[0]
257
+
258
+ const datasetItem = chartJS.getDatasetMeta(item.datasetIndex)
259
+
260
+ if (!chartHoverDataset.value) {
261
+ const filteredDatasets = chartJS.data.datasets
262
+ .map((d: ChartDataset, i: number) => ({
263
+ ...d,
264
+ index: i
265
+ }))
266
+ .filter(
267
+ (ds: ChartDataset) => ds.label !== datasetItem.label
268
+ )
269
+
270
+ for (const dataset of filteredDatasets) {
271
+ chartJS.data.datasets[dataset.index].backgroundColor =
272
+ hexToRgbA(dataset.backgroundColor as string, 0.2)
273
+ }
274
+
275
+ chartJS.update()
276
+
277
+ chartHoverDataset.value = datasetItem
278
+
279
+ return
280
+ }
281
+
282
+ if (!isEqual(chartHoverDataset.value, datasetItem)) {
283
+ const filteredItems = chartJS.data.datasets
284
+ .map((d: ChartDataset, i: number) => ({
285
+ ...d,
286
+ index: i
287
+ }))
288
+ .filter(
289
+ (dataset: ChartDataset) =>
290
+ dataset.label !== chartHoverDataset.value.label
291
+ )
292
+
293
+ for (const dataset of filteredItems) {
294
+ chartJS.data.datasets[dataset.index].backgroundColor =
295
+ rgba2hex(
296
+ revertRGBAOpacity(
297
+ dataset.backgroundColor as string
298
+ )
299
+ )
300
+ }
301
+
302
+ chartHoverDataset.value = datasetItem
303
+
304
+ const allFilteredItems = chartJS.data.datasets
305
+ .map((d: ChartDataset, i: number) => ({
306
+ ...d,
307
+ index: i
308
+ }))
309
+ .filter(
310
+ (dataset: ChartDataset) =>
311
+ dataset.label !== datasetItem.label
312
+ )
313
+
314
+ for (const dataset of allFilteredItems) {
315
+ chartJS.data.datasets[dataset.index].backgroundColor =
316
+ hexToRgbA(dataset.backgroundColor as string, 0.2)
317
+ }
318
+ chartJS.update()
319
+ }
320
+ }
321
+ }
322
+
323
+ const chartOptions = reactive(
324
+ updateKey(
325
+ merge(
326
+ {
327
+ onHover,
328
+ onResize,
329
+ scales: {
330
+ y: {
331
+ max: thisItemsInView.value
332
+ }
333
+ }
334
+ },
335
+ defaultBarChartProps.options,
336
+ props.options
337
+ ),
338
+ 'color',
339
+ replaceColor
340
+ )
341
+ )
342
+
343
+ watch(
344
+ () => chart.value?.scales?.x?.width,
345
+ (val: string) => {
346
+ if (val) {
347
+ chartWidth.value = `${parseInt(val as unknown as string)}px`
348
+ }
349
+ },
350
+ { deep: true }
351
+ )
352
+
353
+ const xLabels = ref(props.data?.labels)
354
+
355
+ const maxItems = computed(() => chartData.value?.labels.length)
356
+
357
+ const handleScrollUpdate = (position: number) => {
358
+ if (position >= maxItems.value - thisItemsInView.value) return
359
+ chart.value.options.scales.y.min = position
360
+ chart.value.options.scales.y.max = position + thisItemsInView.value
361
+
362
+ scrollPosition.value = position
363
+
364
+ chart.value.update()
365
+ }
366
+
367
+ const hideData = (item: BarControllerDatasetOptions, index: number) => {
368
+ onLeaveLegend(item, index)
369
+
370
+ chart.value.data.datasets[index].hidden = !!item.hidden
371
+
372
+ legendDatasets.value.splice(index, 1, {
373
+ ...legendDatasets.value[index],
374
+ hidden: !!item.hidden
375
+ })
376
+
377
+ chart.value.update()
378
+ }
379
+
380
+ const handleChartScroll = (e: WheelEvent) => {
381
+ e.preventDefault()
382
+ scroll += e.deltaY
383
+ const newSteps = Math.trunc(scroll / 1000)
384
+ const newStepsModule = Math.abs(newSteps)
385
+
386
+ if (newSteps !== steps) {
387
+ if (newSteps > steps) {
388
+ const diff =
389
+ chart.value.options.scales.y.max + newStepsModule
390
+ if (diff >= maxItems.value) {
391
+ scrollPosition.value =
392
+ maxItems.value - thisItemsInView.value
393
+ chart.value.options.scales.y.min =
394
+ maxItems.value - thisItemsInView.value - 1
395
+ chart.value.options.scales.y.max = maxItems.value
396
+ } else {
397
+ scrollPosition.value += newStepsModule
398
+ chart.value.options.scales.y.min += newStepsModule
399
+ chart.value.options.scales.y.max += newStepsModule
400
+ }
401
+ } else {
402
+ const diff =
403
+ chart.value.options.scales.y.min - newStepsModule
404
+ if (diff < 0) {
405
+ scrollPosition.value = 0
406
+ chart.value.options.scales.y.min = 0
407
+ chart.value.options.scales.y.max = thisItemsInView.value
408
+ } else {
409
+ scrollPosition.value -= newStepsModule
410
+ chart.value.options.scales.y.min -= newStepsModule
411
+ chart.value.options.scales.y.max -= newStepsModule
412
+ }
413
+ }
414
+ chart.value.update()
415
+
416
+ steps = newSteps
417
+ }
418
+ }
419
+
420
+ const onHoverLegend = (
421
+ item: BarControllerDatasetOptions,
422
+ index: number
423
+ ) => {
424
+ const filteredItems = chart.value.data.datasets
425
+ .map((d: ChartDataset, i: number) => ({
426
+ ...d,
427
+ index: i
428
+ }))
429
+ .filter(
430
+ (dataset: ChartDataset & { index: number }) =>
431
+ dataset.index! !== index
432
+ )
433
+
434
+ for (const dataset of filteredItems) {
435
+ chart.value.data.datasets[dataset.index].backgroundColor =
436
+ hexToRgbA(dataset.backgroundColor, 0.2)
437
+ }
438
+ chart.value.update()
439
+ }
440
+
441
+ const onLeaveLegend = (
442
+ item: BarControllerDatasetOptions,
443
+ index: number
444
+ ) => {
445
+ const filteredItems = chart.value.data.datasets
446
+ .map((d: ChartDataset, i: number) => ({
447
+ ...d,
448
+ index: i
449
+ }))
450
+ .filter(
451
+ (dataset: ChartDataset & { index: number }) =>
452
+ dataset.index !== index
453
+ )
454
+
455
+ for (const dataset of filteredItems) {
456
+ chart.value.data.datasets[dataset.index].backgroundColor =
457
+ rgba2hex(revertRGBAOpacity(dataset.backgroundColor))
458
+ }
459
+ chart.value.update()
460
+ }
461
+
462
+ watch(variables, () => {
463
+ merge(
464
+ chart.value.data,
465
+ updateKey(
466
+ updateKey(props.data, 'backgroundColor', replaceColor),
467
+ 'hoverBackgroundColor',
468
+ replaceColor
469
+ )
470
+ )
471
+
472
+ merge(
473
+ chart.value.options,
474
+ updateKey(
475
+ merge(
476
+ {
477
+ onHover,
478
+ onResize,
479
+ scales: {
480
+ y: {
481
+ max: thisItemsInView.value
482
+ }
483
+ }
484
+ },
485
+ defaultBarChartProps.options,
486
+ props.options
487
+ ),
488
+ 'color',
489
+ replaceColor
490
+ )
491
+ )
492
+
493
+ chart.value.update()
494
+ })
495
+
496
+ return {
497
+ variables,
498
+ chartData,
499
+ chartOptions,
500
+ xLabels,
501
+ barChart,
502
+ maxItems,
503
+ chartWrapperClasses,
504
+ chartClasses,
505
+ legendClasses,
506
+ legendDatasets,
507
+ legendProperties,
508
+ handleChartScroll,
509
+ handleScrollUpdate,
510
+ chartWidth,
511
+ hideData,
512
+ onHoverLegend,
513
+ onLeaveLegend,
514
+ onChartLeave,
515
+ scrollPosition,
516
+ thisItemsInView
517
+ }
518
+ },
519
+ data() {
520
+ return {}
521
+ }
522
+ })
523
+ </script>
524
+
525
+ <style scoped lang="scss">
526
+ .dl-bar-chart-wrapper {
527
+ display: flex;
528
+ flex-direction: column;
529
+ flex-grow: 1;
530
+ }
531
+
532
+ .dl-bar-chart {
533
+ width: 99% !important;
534
+ }
535
+
536
+ .canvas-container {
537
+ height: 100%;
538
+ width: 100%;
539
+ display: flex;
540
+ }
541
+
542
+ .dl-legend {
543
+ align-self: flex-end;
544
+ }
545
+ </style>