@dataloop-ai/components 0.17.35 → 0.17.37

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.17.35",
3
+ "version": "0.17.37",
4
4
  "exports": {
5
5
  ".": "./index.ts",
6
6
  "./models": "./models.ts",
@@ -12,7 +12,7 @@
12
12
  :disabled="disabled"
13
13
  :style="[computedStyles]"
14
14
  style="pointer-events: auto"
15
- class="dl-button"
15
+ :class="buttonClass"
16
16
  @click="onClick"
17
17
  @mousedown="onMouseDown"
18
18
  >
@@ -74,6 +74,7 @@ import { v4 } from 'uuid'
74
74
  import { ButtonColors } from './types'
75
75
  import { transformOptions } from '../../shared/types'
76
76
  import { stringStyleToRecord } from '../../../utils'
77
+ import { textTransform } from '../../../utils/string'
77
78
  import { isString } from 'lodash'
78
79
 
79
80
  export default defineComponent({
@@ -84,27 +85,66 @@ export default defineComponent({
84
85
  },
85
86
 
86
87
  props: {
88
+ /**
89
+ * The user will not be able to press on the button
90
+ */
87
91
  disabled: Boolean,
92
+ /**
93
+ * The color of the button
94
+ */
88
95
  color: {
89
96
  type: String! as PropType<keyof typeof colorNames>,
90
97
  default: ''
91
98
  },
99
+ /**
100
+ * The button's padding is lowered and the white space shrinks
101
+ */
92
102
  dense: { type: Boolean, default: false },
103
+ /**
104
+ * The text content of the button
105
+ */
93
106
  label: { type: String, default: '' },
107
+ /**
108
+ * The color of the button's text
109
+ */
94
110
  textColor: { type: String!, default: '' },
95
111
  colorsObject: {
96
112
  type: Object as PropType<ButtonColors>,
97
113
  default: null
98
114
  },
115
+ /**
116
+ * The color of the icon inside the button
117
+ */
99
118
  iconColor: { type: String!, default: '' },
119
+ /** Padding inside the button */
100
120
  padding: { type: String, default: '' },
121
+ /**
122
+ * The size of the button, it can be s,m,l or xl
123
+ */
101
124
  margin: { type: String, default: '0 auto' },
102
125
  size: { type: String! as PropType<ButtonSizes>, default: 'm' },
126
+ /**
127
+ * The assigned color will fill the entirety of the button
128
+ */
103
129
  filled: { type: Boolean, default: true },
130
+ /** Makes the button rounded */
104
131
  round: { type: Boolean, default: false },
132
+ /**
133
+ * The width of the button will take that of its container
134
+ */
105
135
  shaded: { type: Boolean, default: false },
106
136
  fluid: Boolean,
137
+ /**
138
+ * The button will not have an outline
139
+ */
107
140
  flat: Boolean,
141
+ /**
142
+ * All the characters inside the button will be uppercase
143
+ */
144
+ uppercase: Boolean,
145
+ /**
146
+ * The button will be transparent with a colored outline
147
+ */
108
148
  transform: {
109
149
  type: String,
110
150
  default: 'default',
@@ -112,10 +152,23 @@ export default defineComponent({
112
152
  transformOptions.includes(value)
113
153
  },
114
154
  outlined: Boolean,
155
+ /**
156
+ * Doesn't allow the button's text to be wrapped along multiple rows
157
+ */
115
158
  noWrap: Boolean,
159
+ /**
160
+ * The name of the icon to go inside the button
161
+ */
116
162
  icon: { type: String, default: '' },
117
163
  overflow: { type: Boolean, default: false, required: false },
164
+ /**
165
+ * The tooltip displayed when hovering over the button
166
+ */
118
167
  tooltip: { type: String, default: null, required: false },
168
+ /**
169
+ * The button will mentain the styles it has when it's pressed if this prop is active
170
+ */
171
+ active: { type: Boolean, default: false, required: false },
119
172
  styles: { type: [Object, String], default: null }
120
173
  },
121
174
  emits: ['click', 'mousedown'],
@@ -157,6 +210,12 @@ export default defineComponent({
157
210
  this.label !== ''
158
211
  )
159
212
  },
213
+ buttonLabel(): string {
214
+ return textTransform(this.label)
215
+ },
216
+ buttonClass() {
217
+ return this.active ? 'dl-button active-class' : 'dl-button'
218
+ },
160
219
  hasIcon(): boolean {
161
220
  return typeof this.icon === 'string' && this.icon !== ''
162
221
  },
@@ -383,7 +442,7 @@ export default defineComponent({
383
442
  gap: var(--dl-button-content-gap, 7px);
384
443
  }
385
444
 
386
- .dl-chip.first-letter-capitalized {
445
+ .dl-button-container.first-letter-capitalized {
387
446
  &::first-letter,
388
447
  & > *::first-letter {
389
448
  text-transform: capitalize;
@@ -394,4 +453,14 @@ export default defineComponent({
394
453
  display: inline-block;
395
454
  width: var(--dl-button-container-width);
396
455
  }
456
+
457
+ .active-class {
458
+ color: var(--dl-button-text-color-hover);
459
+ background-color: var(--dl-button-bg-hover);
460
+ border-color: var(--dl-button-border-hover);
461
+ & .dl-button-label {
462
+ transition: all ease-in 0.15s;
463
+ color: var(--dl-button-color-hover);
464
+ }
465
+ }
397
466
  </style>
@@ -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>
@@ -0,0 +1,4 @@
1
+ import DlGrid from './DlGrid.vue'
2
+ import { DlGridLayout } from './types'
3
+ export { DlGrid }
4
+ export type { DlGridLayout }
@@ -0,0 +1,4 @@
1
+ export interface DlGridLayout {
2
+ name: string
3
+ value: number[][]
4
+ }
@@ -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
- (this.$refs.clone as HTMLElement).appendChild(
93
- this.draggedWidget.cloneNode(true)
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
- ;(this.$refs.clone as HTMLElement).innerHTML = ''
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
- swapNodes({
125
- source: this.draggedWidget,
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, 1000)
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 targetRow = getElementAbove(this.hoveredWidget, 'dl-grid-row')
159
- if (this.isLeftSide) {
160
- targetRow.insertBefore(
161
- this.$refs.wrapper as HTMLElement,
162
- targetWidget
163
- )
164
- } else {
165
- insertAfter(
166
- this.$refs.wrapper as unknown as HTMLElement,
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: pointer;
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
- visibility: hidden;
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
- transition: 0.1s;
248
+ padding: 15px;
240
249
  }
241
250
  </style>
@@ -1,5 +1,3 @@
1
1
  import DlWidget from './DlWidget.vue'
2
- import DlGrid from './DlGrid.vue'
3
- import DlGridRow from './DlGridRow.vue'
4
2
 
5
- export { DlWidget, DlGrid, DlGridRow }
3
+ export { DlWidget }
@@ -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 setFlexBasis() {
26
- Array.from(document.getElementsByClassName('dl-grid-row')).forEach(
27
- (row) => {
28
- Array.from(row.children).forEach((widget: any) => {
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 insertAfter(newNode: HTMLElement, existingNode: HTMLElement) {
36
- existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling)
90
+ export function isCustomEvent(event: Event): event is CustomEvent {
91
+ return 'detail' in event
37
92
  }
@@ -11,4 +11,5 @@ export * from './DlPanelContainer'
11
11
  export * from './DlProgressChart'
12
12
  export * from './DlEllipsis'
13
13
  export * from './DlCard'
14
+ export * from './DlGrid'
14
15
  export * from './DlMarkupTable'
@@ -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, DlGridRow, DlGrid } from '../../../../basic'
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: {
@@ -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
 
@@ -194,6 +194,33 @@
194
194
  Disabled
195
195
  </DlButton>
196
196
  </div>
197
+ <div
198
+ style="
199
+ display: flex;
200
+ justify-content: center;
201
+ flex-direction: column;
202
+ "
203
+ >
204
+ <h3>Button keeping its active state with menu</h3>
205
+ <dl-button
206
+ :active="activeButtonState"
207
+ @click="activeButtonState = !activeButtonState"
208
+ >
209
+ {{ activeButtonState ? 'Close' : 'Open' }}
210
+ <dl-menu
211
+ :offset="[0, 5]"
212
+ anchor="bottom middle"
213
+ self="top middle"
214
+ :model-value="!activeButtonState"
215
+ >
216
+ <div
217
+ style="width: 100px; height: 100px; text-align: center"
218
+ >
219
+ Menu
220
+ </div>
221
+ </dl-menu>
222
+ </dl-button>
223
+ </div>
197
224
  <div>
198
225
  <h3>With badge</h3>
199
226
 
@@ -261,10 +288,9 @@
261
288
  </template>
262
289
 
263
290
  <script lang="ts">
264
- import { defineComponent, reactive } from 'vue-demi'
265
- import { DlButton, DlBadge, DlIcon } from '../components'
291
+ import { defineComponent, reactive, ref } from 'vue-demi'
292
+ import { DlButton, DlBadge, DlIcon, DlMenu } from '../components'
266
293
  import { ButtonSizes } from '../components/basic/DlButton/utils'
267
- import DlMenu from '../components/essential/DlMenu/DlMenu.vue'
268
294
  import DlList from '../components/essential/DlList/DlList.vue'
269
295
  import DlListItem from '../components/basic/DlListItem/DlListItem.vue'
270
296
 
@@ -280,9 +306,10 @@ export default defineComponent({
280
306
  },
281
307
  setup() {
282
308
  const buttons = reactive<ButtonSizes[]>(['s', 'm', 'l', 'xl'])
309
+ const activeButtonState = ref(false)
283
310
 
284
311
  const log = (e: Event) => console.log(e)
285
- return { buttons, log }
312
+ return { buttons, log, activeButtonState }
286
313
  }
287
314
  })
288
315
  </script>
@@ -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>
@@ -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
- DlConfusionMatrix
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
- DlGridRow,
69
- DlConfusionMatrix
206
+ DlIcon
70
207
  },
71
208
  setup() {
72
- return { data, labels, matrix }
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
- <template>
78
- <div>
79
- <dl-grid gap="20px">
80
- <dl-grid-row>
81
- <dl-widget>
82
- <template #header>
83
- <span>Widget 7</span>
84
- <span style="font-size: 12px; color: gray">Subtitle</span>
85
- </template>
86
- <template #content>
87
- <dl-confusion-matrix
88
- :matrix="matrix"
89
- :labels="labels"
90
- />
91
- </template>
92
- <template #description>
93
- <span>Lorem ipsum dolor sit amet consectetur adipisicing
94
- elit. Libero eligee a cupiditate modi dicta eveniet
95
- veritatis?</span>
96
- </template>
97
- </dl-widget>
98
- </dl-grid-row>
99
-
100
- <dl-grid-row gap="20px">
101
- <dl-widget>
102
- <template #header>
103
- <span>Widget 2</span>
104
- </template>
105
- <template #content>
106
- <dl-bar-chart
107
- :legend-props="legendProps"
108
- :data="data"
109
- :options="options"
110
- :items-in-view="6"
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>
@@ -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>
@@ -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
- }