wave-ui 2.47.0 → 2.48.0

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": "wave-ui",
3
- "version": "2.47.0",
3
+ "version": "2.48.0",
4
4
  "description": "An emerging UI framework for Vue.js (2 & 3) with only the bright side. :sunny:",
5
5
  "author": "Antoni Andre <antoniandre.web@gmail.com>",
6
6
  "homepage": "https://antoniandre.github.io/wave-ui",
@@ -27,6 +27,7 @@ export default {
27
27
 
28
28
  data: () => ({
29
29
  el: {
30
+ savedState: false,
30
31
  originalStyles: '',
31
32
  width: 0,
32
33
  height: 0,
@@ -59,7 +60,7 @@ export default {
59
60
  beforeAppear (el) {
60
61
  // Only save original state once before a 'clean' transition start.
61
62
  // Not when clicking very fast and mixing states order.
62
- if (this.cleanTransitionCycle) this.saveOriginalStyles(el)
63
+ if (this.cleanTransitionCycle) this.saveOriginalInlineStyles(el)
63
64
  this.cleanTransitionCycle = false
64
65
  },
65
66
  appear (el, done) {
@@ -76,7 +77,7 @@ export default {
76
77
  beforeEnter (el) {
77
78
  // Only save original state once before a 'clean' transition start.
78
79
  // Not when clicking very fast and mixing states order.
79
- if (this.cleanTransitionCycle) this.saveOriginalStyles(el)
80
+ if (this.cleanTransitionCycle) this.saveOriginalInlineStyles(el)
80
81
  this.cleanTransitionCycle = false
81
82
  },
82
83
  enter (el, done) {
@@ -91,6 +92,9 @@ export default {
91
92
  this.cleanTransitionCycle = false
92
93
  },
93
94
  beforeLeave (el) {
95
+ // When starting with an open item.
96
+ if (!this.el.savedState) this.saveComputedStyles(el)
97
+
94
98
  this.beforeHide(el)
95
99
  this.cleanTransitionCycle = false
96
100
  },
@@ -102,6 +106,9 @@ export default {
102
106
  afterLeave (el) {
103
107
  this.applyOriginalStyles(el)
104
108
  this.cleanTransitionCycle = true
109
+ // Reset for recomputing the next time we start the transition from an open state.
110
+ // In case there might be some changed styles from last closing.
111
+ this.el.savedState = false
105
112
  },
106
113
 
107
114
  applyHideStyles (el) {
@@ -151,11 +158,25 @@ export default {
151
158
  applyOriginalStyles (el) {
152
159
  el.style.cssText = this.el.originalStyles
153
160
  },
154
- saveOriginalStyles (el) {
155
- // Keep the original styles to restore them after transition.
161
+ saveOriginalInlineStyles (el) {
162
+ // Keep any original inline styles to restore them after transition.
156
163
  this.el.originalStyles = el.style.cssText
157
164
  },
158
165
  show (el, done) {
166
+ this.saveComputedStyles(el)
167
+ this.applyHideStyles(el)
168
+
169
+ setTimeout(() => this.applyShowStyles(el), 20)
170
+ setTimeout(done, this.duration)
171
+ },
172
+ beforeHide (el) {
173
+ this.applyShowStyles(el)
174
+ },
175
+ hide (el, done) {
176
+ setTimeout(() => this.applyHideStyles(el), 20)
177
+ setTimeout(done, this.duration)
178
+ },
179
+ saveComputedStyles (el) {
159
180
  const computedStyles = window.getComputedStyle(el, null)
160
181
 
161
182
  // Save the width & height then set them to 0 as the animation starting point.
@@ -177,17 +198,7 @@ export default {
177
198
  this.el.borderTopWidth = computedStyles.getPropertyValue('borderTopWidth')
178
199
  this.el.borderBottomWidth = computedStyles.getPropertyValue('borderBottomWidth')
179
200
  }
180
- this.applyHideStyles(el)
181
-
182
- setTimeout(() => this.applyShowStyles(el), 20)
183
- setTimeout(done, this.duration)
184
- },
185
- beforeHide (el) {
186
- this.applyShowStyles(el)
187
- },
188
- hide (el, done) {
189
- setTimeout(() => this.applyHideStyles(el), 20)
190
- setTimeout(done, this.duration)
201
+ this.el.savedState = true
191
202
  }
192
203
  }
193
204
  }
@@ -2,7 +2,7 @@
2
2
  .w-confirm
3
3
  w-menu(v-model="showPopup" v-bind="wMenuProps")
4
4
  template(#activator="{ on }")
5
- w-button.w-confirm__button(v-bind="{ ...$attrs, ...buttonProps, ...on }")
5
+ w-button.w-confirm__button(v-bind="{ ...$attrs, ...buttonProps, ...(disablePrompt ? {} : on) }")
6
6
  slot
7
7
  w-flex(:column="!inline" align-center)
8
8
  div
@@ -32,6 +32,7 @@ export default {
32
32
  bgColor: { type: String },
33
33
  color: { type: String },
34
34
  icon: { type: String },
35
+ disablePrompt: { type: Boolean }, // If true, the confirm button acts like a simple w-button.
35
36
  mainButton: { type: Object }, // Allow passing down an object of props to the w-button component.
36
37
  question: { type: String, default: 'Are you sure?' },
37
38
 
@@ -194,7 +194,7 @@ export default {
194
194
  // eslint-disable-next-line vue/custom-event-name-casing
195
195
  else if (e.keyCode === 27) this.$emit('keydown:escape')
196
196
  // On arrow keys press, navigate to prev/next item.
197
- else if (this.arrowsNavigation) {
197
+ else if (this.arrowsNavigation && [38, 40].includes(e.keyCode)) {
198
198
  e.preventDefault()
199
199
  if (e.keyCode === 38) this.focusPrevNextItem(li._index, false)
200
200
  if (e.keyCode === 40) this.focusPrevNextItem(li._index, true)
@@ -60,7 +60,7 @@ component(
60
60
  v-for="(val, i) in (inputValue.length ? inputValue : [{}])"
61
61
  :key="i"
62
62
  type="hidden"
63
- :value="val.value || ''"
63
+ :value="val.value === undefined ? '' : val.value.toString()"
64
64
  :name="inputName + (multiple ? '[]' : '')")
65
65
  template(v-if="labelPosition === 'inside' && showLabelInside")
66
66
  label.w-select__label.w-select__label--inside.w-form-el-shakable(
@@ -298,7 +298,8 @@ export default {
298
298
  // Also accept objects if returnObject is true.
299
299
  // In any case, always end up with an array.
300
300
  checkSelection (items) {
301
- items = Array.isArray(items) ? items : (items ? [items] : [])
301
+ console.log(items)
302
+ items = Array.isArray(items) ? items : (items !== undefined ? [items] : [])
302
303
  // `selectItems` items always have a value.
303
304
  const allValues = this.selectItems.map(item => item.value)
304
305
 
@@ -423,8 +424,10 @@ export default {
423
424
  &__selection {
424
425
  width: 100%;
425
426
  height: 100%;
426
- font-size: inherit;
427
+ min-height: inherit;
428
+ font: inherit;
427
429
  color: inherit;
430
+ text-align: inherit;
428
431
  background: none;
429
432
  border: none;
430
433
  outline: none;
@@ -521,12 +524,15 @@ export default {
521
524
  position: absolute;
522
525
  top: 50%;
523
526
  left: 0;
527
+ right: 0;
524
528
  // Use margin instead of padding as the scale transformation bellow decreases the real padding
525
529
  // size and misaligns the label.
526
530
  margin-left: 2 * $base-increment;
527
531
  transform: translateY(-50%);
528
532
  pointer-events: none;
529
533
 
534
+ .w-select--inner-icon-right & {padding-right: 22px;}
535
+
530
536
  .w-select--no-padding & {
531
537
  left: 0;
532
538
  margin-left: 0;
@@ -128,12 +128,34 @@
128
128
  slot(name="extra-row")
129
129
 
130
130
  //- Table footer.
131
- tfoot.w-table__footer(v-if="$slots.footer || $slots['footer-row']")
131
+ tfoot.w-table__footer(v-if="$slots.footer || $slots['footer-row'] || pagination")
132
132
  slot(v-if="$slots['footer-row']" name="footer-row")
133
- tr.w-table__row(v-else)
133
+ tr.w-table__row(v-else-if="$slots.footer")
134
134
  td.w-table__cell(:colspan="headers.length")
135
135
  slot(name="footer")
136
- //- .pagination
136
+ tr.w-table__row.w-table__pagination-wrap(v-if="pagination && paginationConfig")
137
+ td.w-table__cell(:colspan="headers.length")
138
+ .w-table__pagination
139
+ w-select.pagination-number.pagination-number--items-per-page(
140
+ v-if="paginationConfig.itemsPerPageOptions"
141
+ v-model="paginationConfig.itemsPerPage"
142
+ :items="paginationConfig.itemsPerPageOptions"
143
+ label-position="left"
144
+ label="Items per page"
145
+ label-color="inherit")
146
+ span.pagination-number.pagination-number--results.
147
+ {{ paginationConfig.start }}-{{ paginationConfig.end }} of {{ paginationConfig.total }}
148
+ .pagination-arrows
149
+ w-button.pagination-arrow.pagination-arrow--prev(
150
+ @click="paginationConfig.page--"
151
+ icon="wi-chevron-left"
152
+ text
153
+ lg)
154
+ w-button.pagination-arrow.pagination-arrow--next(
155
+ @click="paginationConfig.page++"
156
+ icon="wi-chevron-right"
157
+ text
158
+ lg)
137
159
  </template>
138
160
 
139
161
  <script>
@@ -189,13 +211,28 @@ export default {
189
211
 
190
212
  forceSelection: { type: Boolean },
191
213
 
192
- // Useful to select or expand a row, and even after a filter, the same row will stay selected or exanded.
214
+ // Useful to select or expand a row, and even after a filter, the same row will stay selected or expanded.
193
215
  uidKey: { type: String, default: 'id' },
194
216
 
195
217
  filter: { type: Function },
196
218
  sortFunction: { type: Function },
197
219
  mobileBreakpoint: { type: Number, default: 0 },
198
- resizableColumns: { type: Boolean }
220
+ resizableColumns: { type: Boolean },
221
+
222
+ pagination: {
223
+ type: [Boolean, Object, String],
224
+ validator: object => {
225
+ if (!object) return true // Accept any falsy value.
226
+ else if (typeof object === 'object' && (!object.itemsPerPage || (object.page && isNaN(object.page)))) {
227
+ consoleError(
228
+ 'Wrong pagination config received in the w-table\'s `pagination` prop (received: `' + JSON.stringify(object) + '`). ' +
229
+ '\nExpected object: { itemsPerPage: Integer, page: Integer } or { itemsPerPage: Integer, start: Integer }.'
230
+ )
231
+ return false
232
+ }
233
+ return true
234
+ }
235
+ }
199
236
  },
200
237
 
201
238
  emits: [
@@ -222,7 +259,8 @@ export default {
222
259
  nextColWidth: null,
223
260
  columnEl: null,
224
261
  nextColumnEl: null
225
- }
262
+ },
263
+ paginationConfig: {}
226
264
  }),
227
265
 
228
266
  computed: {
@@ -490,6 +528,20 @@ export default {
490
528
  this.colResizing.colWidth = null
491
529
  this.colResizing.nextColWidth = null
492
530
  }, 0)
531
+ },
532
+
533
+ updatePaginationConfig () {
534
+ const itemsPerPage = this.pagination?.itemsPerPage || 10
535
+ const total = this.pagination?.total || this.items.length
536
+ const page = this.pagination?.page || 1
537
+ this.paginationConfig = {
538
+ itemsPerPage,
539
+ itemsPerPageOptions: this.pagination?.itemsPerPageOptions || [{ label: '10', value: 10 }, { label: '100', value: 100 }, { label: 'All', value: 0 }],
540
+ page,
541
+ start: this.pagination?.start || 1,
542
+ end: total >= (itemsPerPage * page) ? (itemsPerPage * page) : (total % (itemsPerPage * page)),
543
+ total
544
+ }
493
545
  }
494
546
  },
495
547
 
@@ -499,6 +551,8 @@ export default {
499
551
 
500
552
  if ((this.expandedRows || []).length) this.expandedRowsInternal = this.expandedRows
501
553
  if ((this.selectedRows || []).length) this.selectedRowsInternal = this.selectedRows
554
+
555
+ if (this.pagination) this.updatePaginationConfig()
502
556
  },
503
557
 
504
558
  watch: {
@@ -739,6 +793,29 @@ $tr-border-top: 1px;
739
793
  border-bottom: $border;
740
794
  }
741
795
  }
796
+
797
+ &__pagination {
798
+ display: flex;
799
+ align-items: center;
800
+ justify-content: flex-end;
801
+ padding-top: $base-increment;
802
+ padding-bottom: $base-increment;
803
+
804
+ .pagination-number--items-per-page {
805
+ margin-right: 6 * $base-increment;
806
+ flex-grow: 0;
807
+ text-align: right;
808
+ }
809
+ .pagination-number--of {
810
+ margin-left: $base-increment;
811
+ margin-right: $base-increment;
812
+ }
813
+ .w-select__selection {max-width: 60px;}
814
+
815
+ .pagination-arrows {
816
+ margin-left: 6 * $base-increment;
817
+ }
818
+ }
742
819
  }
743
820
 
744
821
  // Mobile layout.
@@ -18,7 +18,7 @@ ul.w-tree(:class="classes")
18
18
  text
19
19
  sm)
20
20
  slot(name="item-label" :item="item.originalItem" :depth="depth" :open="item.open")
21
- w-icon(v-if="itemIcon(item)" class="w-tree__item-icon") {{ itemIcon(item) }}
21
+ w-icon(v-if="itemIcon(item)" class="w-tree__item-icon" :color="item.originalItem[itemIconColorKey] || iconColor") {{ itemIcon(item) }}
22
22
  span {{ item.label }}
23
23
  span.ml1(v-if="counts && (item.children || item.branch)").
24
24
  ({{ item.originalItem.children?.length || 0 }})
@@ -70,8 +70,11 @@ export default {
70
70
  noTransition: { type: Boolean },
71
71
  selectable: { type: Boolean },
72
72
  // By default it only reacts to items count change (added or deleted items) not property of items change.
73
- depthReactivity: { type: Boolean },
74
- counts: { type: Boolean }
73
+ deepReactivity: { type: Boolean },
74
+ counts: { type: Boolean },
75
+ itemIconKey: { type: String, default: 'icon' }, // Support a different icon per item.
76
+ iconColor: { type: String }, // Applies a color on all the label item icons.
77
+ itemIconColorKey: { type: String, default: 'iconColor' } // Applies a specific color on each label item icons.
75
78
  },
76
79
 
77
80
  emits: ['update:model-value', 'before-open', 'open', 'before-close', 'close', 'click', 'select'],
@@ -105,7 +108,7 @@ export default {
105
108
  children: !!item.children, // The children tree remains available in originalItem.
106
109
  branch: item.branch,
107
110
  depth: this.depth,
108
- open: oldItems[i]?.open || false
111
+ open: !!(oldItems[i]?.open || this.expandAll)
109
112
  })
110
113
  })
111
114
  },
@@ -168,6 +171,7 @@ export default {
168
171
  treeTabbableItems[i + indexModifier] && treeTabbableItems[i + indexModifier].focus()
169
172
  return true // Break the loop.
170
173
  }
174
+ return false
171
175
  })
172
176
  }
173
177
  }
@@ -182,6 +186,7 @@ export default {
182
186
  * @param {String} selector any valid DOM selector to match the siblings.
183
187
  */
184
188
  getPreviousSibling (node, selector) {
189
+ // eslint-disable-next-line no-unmodified-loop-condition
185
190
  while (selector && (node = node.previousElementSibling)) {
186
191
  if (node.matches(selector)) return node
187
192
  }
@@ -195,6 +200,7 @@ export default {
195
200
  * @param {String} selector any valid DOM selector to match the siblings.
196
201
  */
197
202
  getNextSibling (node, selector) {
203
+ // eslint-disable-next-line no-unmodified-loop-condition
198
204
  while (selector && (node = node.nextElementSibling)) {
199
205
  if (node.matches(selector)) return node
200
206
  }
@@ -207,7 +213,7 @@ export default {
207
213
 
208
214
  itemIcon (item) {
209
215
  return (
210
- item.originalItem.icon ||
216
+ item.originalItem[this.itemIconKey] ||
211
217
  (!item.children && !item.branch && this.leafIcon) ||
212
218
  ((item.children || item.branch) && ((item.open && this.branchOpenIcon) || this.branchIcon))
213
219
  )
@@ -229,7 +235,7 @@ export default {
229
235
  // The open property of each item has to be retained from this.currentDepthItems in order to stay
230
236
  // in the same state after DOM repaint.
231
237
  items => this.updateCurrentDepthTree(items, this.currentDepthItems),
232
- { deep: !!this.depthReactivity } // Deep watching is more resource consuming. Only enable on user demand.
238
+ { deep: !!this.deepReactivity } // Deep watching is more resource consuming. Only enable on user demand.
233
239
  )
234
240
  },
235
241