@dataloop-ai/components 0.18.54 → 0.18.56

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.54",
3
+ "version": "0.18.56",
4
4
  "exports": {
5
5
  ".": "./index.ts",
6
6
  "./models": "./models.ts",
@@ -46,6 +46,12 @@ body {
46
46
  &--none{
47
47
  text-transform: none;
48
48
  }
49
+ &--default {
50
+ &,
51
+ & > * {
52
+ text-transform: capitalize;
53
+ }
54
+ }
49
55
  }
50
56
 
51
57
  /* Inserting a collapsed row between two flex items will make
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <div
3
3
  :id="uuid"
4
- class="dl-button-container"
4
+ :class="containerClasses"
5
5
  style="pointer-events: none"
6
- :style="[cssButtonVars, containerStyles, capitalizeFirst]"
6
+ :style="[cssButtonVars, containerStyles]"
7
7
  >
8
8
  <button
9
9
  v-if="hasContent || hasIcon"
@@ -73,7 +73,7 @@ import {
73
73
  setMaxHeight
74
74
  } from './utils'
75
75
  import type { ButtonSizes } from './utils'
76
- import { computed, defineComponent, PropType, ref } from 'vue-demi'
76
+ import { computed, defineComponent, PropType, ref, toRefs } from 'vue-demi'
77
77
  import { colorNames } from '../../../utils/css-color-names'
78
78
  import { useSizeObserver } from '../../../hooks/use-size-observer'
79
79
  import { v4 } from 'uuid'
@@ -179,11 +179,16 @@ export default defineComponent({
179
179
  },
180
180
  emits: ['click', 'mousedown', 'dblclick'],
181
181
  setup(props) {
182
+ const { active } = toRefs(props)
182
183
  const buttonLabelRef = ref(null)
183
184
  const { hasEllipsis } = useSizeObserver(buttonLabelRef)
184
185
 
185
186
  const buttonClass = computed(() => {
186
- return props.active ? 'dl-button active-class' : 'dl-button'
187
+ const classes = ['dl-button']
188
+ if (active.value) {
189
+ classes.push('active-class')
190
+ }
191
+ return classes
187
192
  })
188
193
 
189
194
  return {
@@ -194,6 +199,12 @@ export default defineComponent({
194
199
  }
195
200
  },
196
201
  computed: {
202
+ containerClasses(): string[] {
203
+ return [
204
+ 'dl-button-container',
205
+ `dl-text-transform--${this.transform}`
206
+ ]
207
+ },
197
208
  getIconColor(): string {
198
209
  if (this.iconColor) {
199
210
  return this.iconColor
@@ -203,12 +214,6 @@ export default defineComponent({
203
214
  return this.textColor
204
215
  }
205
216
 
206
- return 'dl-color-secondary'
207
- },
208
- capitalizeFirst(): string {
209
- if (this.transform === 'default') {
210
- return 'first-letter-capitalized'
211
- }
212
217
  return null
213
218
  },
214
219
  computedStyles(): Record<string, string> {
@@ -356,9 +361,6 @@ export default defineComponent({
356
361
  : setPadding(this.size),
357
362
  '--dl-button-margin': this.margin,
358
363
  '--dl-button-font-size': setFontSize(this.size),
359
- '--dl-button-text-transform': this.capitalizeFirst
360
- ? null
361
- : this.transform,
362
364
  '--dl-button-cursor': this.isActionable
363
365
  ? 'pointer'
364
366
  : 'not-allowed',
@@ -424,7 +426,6 @@ export default defineComponent({
424
426
  padding: var(--dl-button-padding);
425
427
  margin: var(--dl-button-margin);
426
428
  border-radius: var(--dl-button-border-radius);
427
- text-transform: var(--dl-button-text-transform);
428
429
  font-family: 'Roboto', sans-serif;
429
430
  font-size: var(--dl-button-font-size);
430
431
  cursor: var(--dl-button-cursor);
@@ -484,13 +485,6 @@ export default defineComponent({
484
485
  transition: var(--dl-button-text-transition-duration);
485
486
  }
486
487
 
487
- .dl-button-container.first-letter-capitalized {
488
- &::first-letter,
489
- & > *::first-letter {
490
- text-transform: capitalize;
491
- }
492
- }
493
-
494
488
  .dl-button-container {
495
489
  display: inline-block;
496
490
  width: var(--dl-button-container-width);
@@ -127,10 +127,7 @@ export default defineComponent({
127
127
  return this.iconColor
128
128
  },
129
129
  chipClass(): string {
130
- if (this.transform === 'default') {
131
- return 'first-letter-capitalized'
132
- }
133
- return null
130
+ return `dl-text-transform--${this.transform}`
134
131
  },
135
132
  cssChipVars(): Record<string, string | number> {
136
133
  return {
@@ -170,10 +167,7 @@ export default defineComponent({
170
167
  '--dl-chip-left-icon-hover-opacity': this.disabled ? 1 : 0.8,
171
168
  '--dl-chip-left-icon-cursor': this.disabled
172
169
  ? 'not-allowed'
173
- : 'pointer',
174
- '--dl-chip-text-transform': this.chipClass
175
- ? null
176
- : this.transform
170
+ : 'pointer'
177
171
  }
178
172
  }
179
173
  },
@@ -193,7 +187,6 @@ export default defineComponent({
193
187
  position: relative;
194
188
  display: flex;
195
189
  vertical-align: middle;
196
- text-transform: var(--dl-chip-text-transform);
197
190
  font-size: var(--dl-font-size-body);
198
191
  line-height: 12px;
199
192
  border-radius: 2px;
@@ -220,13 +213,6 @@ export default defineComponent({
220
213
  }
221
214
  }
222
215
 
223
- .dl-chip.first-letter-capitalized {
224
- &::first-letter,
225
- & > *::first-letter {
226
- text-transform: capitalize;
227
- }
228
- }
229
-
230
216
  .dl-chip-remove-icon-container {
231
217
  cursor: var(--dl-chip-left-icon-cursor);
232
218
  position: absolute;
@@ -9,14 +9,21 @@
9
9
  </template>
10
10
 
11
11
  <script lang="ts">
12
- import { defineComponent, PropType } from 'vue-demi'
12
+ import { Dictionary } from 'lodash'
13
13
  import {
14
- getGridTemplate,
15
- getElementAbove,
16
- findIndexInMatrix,
17
- swapElemensInMatrix,
18
- isCustomEvent
19
- } from '../DlWidget/utils'
14
+ computed,
15
+ defineComponent,
16
+ getCurrentInstance,
17
+ nextTick,
18
+ onMounted,
19
+ PropType,
20
+ ref,
21
+ toRefs,
22
+ watch
23
+ } from 'vue-demi'
24
+ import { getGridTemplate, swapElementsInMatrix } from './utils'
25
+ import { isCustomEvent, getElementAbove } from '../utils'
26
+ import { DlGridMode } from './types'
20
27
 
21
28
  export default defineComponent({
22
29
  model: {
@@ -25,7 +32,7 @@ export default defineComponent({
25
32
  },
26
33
  props: {
27
34
  modelValue: {
28
- type: Array as PropType<number[][]>,
35
+ type: Array as PropType<(string | number)[][]>,
29
36
  default: null
30
37
  },
31
38
  rowGap: {
@@ -39,111 +46,147 @@ export default defineComponent({
39
46
  maxElementsPerRow: {
40
47
  type: Number,
41
48
  default: 3
49
+ },
50
+ mode: {
51
+ type: String as PropType<DlGridMode>,
52
+ default: DlGridMode.LAYOUT
42
53
  }
43
54
  },
44
55
  emits: ['update:model-value', 'layout-changed'],
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
56
+ setup(props, { emit }) {
57
+ const vm = getCurrentInstance()
58
+ const grid = ref<HTMLElement | null>(null)
59
+ const { modelValue, mode, rowGap, columnGap, maxElementsPerRow } =
60
+ toRefs(props)
61
+
62
+ const isLayoutMode = computed(() => mode.value == DlGridMode.LAYOUT)
63
+ const isGridMode = computed(() => mode.value == DlGridMode.GRID)
64
+ const isFlexMode = computed(() => mode.value == DlGridMode.FLEX)
65
+
66
+ const gridClass = computed(() =>
67
+ modelValue.value || !isFlexMode.value
54
68
  ? 'dl-grid-wrapper__grid'
55
69
  : 'dl-grid-wrapper__flex'
70
+ )
71
+
72
+ const gridStyles = computed(() => {
73
+ const gridStyles: Dictionary<string | number> = {
74
+ '--row-gap': rowGap.value,
75
+ '--column-gap': columnGap.value
76
+ }
77
+
78
+ if (!isGridMode.value) {
79
+ gridStyles['--element-per-row'] = maxElementsPerRow.value
80
+ }
81
+
82
+ return gridStyles
83
+ })
84
+
85
+ const layoutChanged = () => {
86
+ emit('layout-changed', modelValue.value)
56
87
  }
57
- },
58
- watch: {
59
- modelValue: {
60
- handler(val, oldVal) {
61
- this.$nextTick(() => {
62
- if (val) {
63
- if (val.length !== oldVal?.length) {
64
- this.applyIndexesForChildren()
65
- }
66
- this.applyGridElementStyles()
67
- }
68
- })
69
- },
70
- immediate: true
71
- }
72
- },
73
- mounted() {
74
- this.applyIndexesForChildren()
75
- },
76
- methods: {
77
- applyGridElementStyles() {
78
- if (!this.modelValue) return
79
- const gridElements = Array.from(
80
- (this.$refs.grid as HTMLElement).children
88
+
89
+ const changePosition = (e: CustomEvent) => {
90
+ if (!modelValue.value) {
91
+ return
92
+ }
93
+ const className = grid.value.children[0].classList[0]
94
+ const sourceEl = getElementAbove(e.detail.source, className)
95
+ const targetEl = getElementAbove(e.detail.target, className)
96
+
97
+ const newLayout: (string | number)[][] = swapElementsInMatrix(
98
+ modelValue.value,
99
+ sourceEl,
100
+ targetEl
81
101
  )
82
- const gridTemplate = getGridTemplate(this.modelValue)
83
- if (gridElements.length > gridTemplate.length) return
102
+ // Update modelValue is required to trigger visualization of the changes
103
+ emit('update:model-value', newLayout)
84
104
 
85
- const order = this.modelValue.flat()
86
- gridElements.forEach((element: Element, index: number) => {
87
- const orderIndex =
88
- order.findIndex((nr: number) => nr === index + 1) + 1
105
+ // Force update is required to trigger the re-render of the grid
106
+ vm?.proxy?.$forceUpdate()
107
+
108
+ if (e.detail.endDragging) {
109
+ layoutChanged()
110
+ }
111
+ }
112
+
113
+ const applyGridElementStyles = () => {
114
+ const childrenElements = Array.from(grid.value.children)
115
+ const layoutOrder = modelValue.value?.flat() ?? []
116
+
117
+ // The check is needed to avoid errors and incorrect behavior
118
+ if (
119
+ !modelValue.value ||
120
+ childrenElements.length > layoutOrder.flat().length ||
121
+ isFlexMode.value
122
+ ) {
123
+ for (const element of childrenElements) {
124
+ const htmlElement = element as HTMLElement
125
+ htmlElement.style.flexGrow = '1'
126
+ }
127
+ return
128
+ }
129
+
130
+ let gridTemplate: string[]
131
+ if (isGridMode.value) {
132
+ gridTemplate = getGridTemplate(modelValue.value)
133
+ }
134
+ for (const element of childrenElements) {
89
135
  const htmlElement = element as HTMLElement
136
+ const orderIndex: number = layoutOrder
137
+ .flat()
138
+ .findIndex((w) => w === htmlElement.dataset.id)
139
+ if (isGridMode.value) {
140
+ htmlElement.style.gridColumn = gridTemplate[orderIndex]
141
+ }
90
142
  htmlElement.style.order = `${orderIndex}`
91
- htmlElement.style.gridColumn = gridTemplate[orderIndex - 1]
92
143
  htmlElement.addEventListener('position-changing', (e) => {
93
144
  if (!isCustomEvent(e)) return
94
- this.changePosition(e)
145
+ changePosition(e)
95
146
  })
96
- htmlElement.addEventListener(
97
- 'position-changed',
98
- this.layoutChanged.bind(this)
99
- )
100
- })
101
- },
102
- changePosition(e: CustomEvent) {
103
- if (!this.modelValue) return
104
- const side = e.detail.side
105
- const className = (this.$refs.grid as HTMLElement).children[0]
106
- .classList[0]
107
- const sourceIndex =
108
- parseInt(
109
- getElementAbove(e.detail.source, className).dataset.index
110
- ) + 1
111
- const targetIndex =
112
- parseInt(
113
- getElementAbove(e.detail.target, className).dataset.index
114
- ) + 1
115
- const sourceMatrixIndex = findIndexInMatrix(
116
- this.modelValue,
117
- sourceIndex
118
- )
119
- const targetMatrixIndex = findIndexInMatrix(
120
- this.modelValue,
121
- targetIndex
122
- )
147
+ htmlElement.addEventListener('position-changed', layoutChanged)
148
+ }
149
+ }
123
150
 
124
- const newLayout = swapElemensInMatrix(
125
- this.modelValue,
126
- sourceMatrixIndex,
127
- targetMatrixIndex,
128
- side,
129
- this.maxElementsPerRow
130
- )
131
- // Update modelValue is required to trigger visualization of the changes
132
- this.$emit('update:model-value', newLayout)
133
- if (e.detail.endDragging) {
134
- this.layoutChanged()
151
+ const applyIndexesForChildren = () => {
152
+ if (!modelValue.value) {
153
+ return
135
154
  }
136
- },
137
- layoutChanged() {
138
- this.$emit('layout-changed', this.modelValue)
139
- },
140
- applyIndexesForChildren() {
141
- Array.from((this.$refs.grid as HTMLElement).children).forEach(
155
+ Array.from(grid.value.children).forEach(
142
156
  (element: Element, index: number) => {
143
- (element as HTMLElement).dataset.index = `${index}`
157
+ const el = element as HTMLElement
158
+ el.dataset.id = `${modelValue.value.flat()[index]}`
144
159
  }
145
160
  )
146
161
  }
162
+
163
+ watch(
164
+ modelValue,
165
+ (val, old) => {
166
+ nextTick(() => {
167
+ if (val) {
168
+ if (val.flat().length !== old?.flat().length) {
169
+ applyIndexesForChildren()
170
+ }
171
+ applyGridElementStyles()
172
+ }
173
+ })
174
+ },
175
+ { immediate: true }
176
+ )
177
+
178
+ onMounted(() => {
179
+ applyGridElementStyles()
180
+ })
181
+
182
+ return {
183
+ isLayoutMode,
184
+ isGridMode,
185
+ isFlexMode,
186
+ gridClass,
187
+ gridStyles,
188
+ grid
189
+ }
147
190
  }
148
191
  })
149
192
  </script>
@@ -154,9 +197,11 @@ export default defineComponent({
154
197
  display: grid;
155
198
  row-gap: var(--row-gap);
156
199
  column-gap: var(--column-gap);
200
+ grid-template-columns: repeat(var(--element-per-row), 1fr);
157
201
  }
158
202
  &__flex {
159
203
  display: flex;
204
+ gap: var(--row-gap);
160
205
  flex-wrap: wrap;
161
206
  }
162
207
  }
@@ -1,5 +1,10 @@
1
1
  export interface DlGridLayout {
2
2
  name: string
3
- value: number[][]
3
+ value: (number | string)[][]
4
+ }
5
+
6
+ export enum DlGridMode {
7
+ GRID = 'grid',
8
+ FLEX = 'flex',
9
+ LAYOUT = 'layout'
4
10
  }
5
- export type DlGridSideType = 'left' | 'right'
@@ -0,0 +1,69 @@
1
+ import { cloneDeep } from 'lodash'
2
+
3
+ function leastCommonMultiple(arr: number[]) {
4
+ if (!arr || !arr.length) {
5
+ return
6
+ }
7
+
8
+ const gcd = (a: number, b: number): number => (a ? gcd(b % a, a) : b)
9
+ const lcm = (a: number, b: number): number => (a * b) / gcd(a, b)
10
+ return arr.reduce(lcm)
11
+ }
12
+
13
+ function buildNewLayoutOrder(
14
+ layout: (string | number)[],
15
+ matrix: (string | number)[][]
16
+ ) {
17
+ const template: (string | number)[][] = []
18
+ let index = 0
19
+
20
+ for (const row of matrix) {
21
+ const templateRow: (string | number)[] = []
22
+ for (const cell of row) {
23
+ templateRow.push(layout[index])
24
+ index++
25
+ }
26
+ template.push(templateRow)
27
+ }
28
+
29
+ return template
30
+ }
31
+
32
+ export function getGridTemplate(layout: (string | number)[][]) {
33
+ if (!layout) {
34
+ return
35
+ }
36
+
37
+ const flatLayout = layout.map((el) => el.length)
38
+ const template = []
39
+ const lcm = leastCommonMultiple(flatLayout)
40
+ for (let i = 0; i < flatLayout.length; i++) {
41
+ const columns = flatLayout[i]
42
+ let columnTrack = 1
43
+ for (let j = 0; j < columns; j++) {
44
+ let gridSpan = lcm / columns
45
+ template.push(`${columnTrack} / ${gridSpan + columnTrack}`)
46
+ columnTrack += gridSpan
47
+ gridSpan += gridSpan
48
+ }
49
+ }
50
+ return template
51
+ }
52
+
53
+ export function swapElementsInMatrix(
54
+ oldLayout: (string | number)[][],
55
+ sourceEl: HTMLElement,
56
+ targetEl: HTMLElement
57
+ ) {
58
+ if (!sourceEl || !targetEl) {
59
+ return oldLayout
60
+ }
61
+ const newLayout = cloneDeep(oldLayout).flat(1)
62
+
63
+ const sourceIndex = newLayout.indexOf(sourceEl.dataset.id)
64
+ const targetIndex = newLayout.indexOf(targetEl.dataset.id)
65
+ newLayout.splice(sourceIndex, 1)
66
+ newLayout.splice(targetIndex, 0, sourceEl.dataset.id)
67
+
68
+ return buildNewLayoutOrder(newLayout, oldLayout)
69
+ }
@@ -11,7 +11,8 @@
11
11
 
12
12
  <script lang="ts">
13
13
  import { v4 } from 'uuid'
14
- import { defineComponent, computed, ref } from 'vue-demi'
14
+ import { defineComponent, computed, ref, PropType, toRefs } from 'vue-demi'
15
+ import { DlTextTransformOptions } from '../../shared/types'
15
16
 
16
17
  const separatorValues = ['horizontal', 'vertical', 'cell', 'none']
17
18
 
@@ -22,7 +23,14 @@ export default defineComponent({
22
23
  flat: Boolean,
23
24
  bordered: Boolean,
24
25
  square: Boolean,
25
- wrapCells: Boolean,
26
+ /** wraps the cells */
27
+ wrap: Boolean,
28
+ transform: {
29
+ type: String as PropType<DlTextTransformOptions>,
30
+ default: 'default',
31
+ validator: (value: DlTextTransformOptions): boolean =>
32
+ Object.values(DlTextTransformOptions).includes(value)
33
+ },
26
34
 
27
35
  separator: {
28
36
  type: String,
@@ -32,17 +40,21 @@ export default defineComponent({
32
40
  }
33
41
  },
34
42
  setup(props) {
43
+ const { transform, dense, separator, flat, bordered, square, wrap } =
44
+ toRefs(props)
45
+
35
46
  const uuid = ref(`dl-markup-table-${v4()}`)
36
47
 
37
48
  const classes = computed(
38
49
  () =>
39
50
  'dl-markup-table dl-table__container dl-table__card' +
40
- ` dl-table--${props.separator}-separator` +
41
- (props.dense === true ? ' dl-table--dense' : '') +
42
- (props.flat === true ? ' dl-table--flat' : '') +
43
- (props.bordered === true ? ' dl-table--bordered' : '') +
44
- (props.square === true ? ' dl-table--square' : '') +
45
- (props.wrapCells === false ? ' dl-table--no-wrap' : '')
51
+ ` dl-table--${separator.value}-separator` +
52
+ (dense.value === true ? ' dl-table--dense' : '') +
53
+ (flat.value === true ? ' dl-table--flat' : '') +
54
+ (bordered.value === true ? ' dl-table--bordered' : '') +
55
+ (square.value === true ? ' dl-table--square' : '') +
56
+ (wrap.value === false ? ' dl-table--no-wrap' : '') +
57
+ ` dl-text-transform--${transform.value}`
46
58
  )
47
59
 
48
60
  return {
@@ -66,7 +66,7 @@
66
66
  import { v4 } from 'uuid'
67
67
  import { computed, defineComponent, ref, toRef, PropType } from 'vue-demi'
68
68
  import { DlIcon } from '../../essential'
69
- import { getElementAbove, addMouseEnter, removeMouseEnter } from './utils'
69
+ import { getElementAbove, addMouseEnter, removeMouseEnter } from '../utils'
70
70
  import { DlEmptyStateProps } from '../DlEmptyState/types'
71
71
  import DlEmptyState from '../DlEmptyState/DlEmptyState.vue'
72
72
 
@@ -77,7 +77,10 @@ export default defineComponent({
77
77
  DlEmptyState
78
78
  },
79
79
  props: {
80
- isEmpty: Boolean,
80
+ isEmpty: {
81
+ type: Boolean,
82
+ default: false
83
+ },
81
84
  emptyStateProps: {
82
85
  type: Object as PropType<DlEmptyStateProps>,
83
86
  default: null
@@ -126,6 +129,7 @@ export default defineComponent({
126
129
  if (draggedWidget.value && clone.value) {
127
130
  clone.value.appendChild(draggedWidget.value.cloneNode(true))
128
131
  clone.value.style.visibility = 'visible'
132
+ clone.value.style.position = 'fixed'
129
133
  clone.value.style.width = `${draggedWidget.value.offsetWidth}px`
130
134
  clone.value.style.height = `${draggedWidget.value.offsetHeight}px`
131
135
  clone.value.style.backgroundColor = `var(--dl-color-bg)`
@@ -0,0 +1,27 @@
1
+ export function getElementAbove(el: HTMLElement, className: string) {
2
+ //@ts-ignore
3
+ for (; el && el !== document; el = el.parentNode) {
4
+ if (el.classList.contains(className)) {
5
+ return el
6
+ }
7
+ }
8
+ }
9
+
10
+ export function addMouseEnter(className: string, method: EventListenerObject) {
11
+ Array.from(document.getElementsByClassName(className)).forEach((widget) => {
12
+ widget.addEventListener('mouseenter', method)
13
+ })
14
+ }
15
+
16
+ export function removeMouseEnter(
17
+ className: string,
18
+ method: EventListenerObject
19
+ ) {
20
+ Array.from(document.getElementsByClassName(className)).forEach((widget) => {
21
+ widget.removeEventListener('mouseenter', method)
22
+ })
23
+ }
24
+
25
+ export function isCustomEvent(event: Event): event is CustomEvent {
26
+ return 'detail' in event
27
+ }
@@ -409,7 +409,7 @@ export default defineComponent({
409
409
  return props.color
410
410
  }
411
411
 
412
- return 'dl-color-medium'
412
+ return 'dl-color-white'
413
413
  })
414
414
 
415
415
  return {