wave-ui 1.61.0 → 1.62.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": "1.61.0",
3
+ "version": "1.62.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,9 @@
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-on="{ ...$listeners, ...on }" v-bind="buttonProps")
5
+ w-button.w-confirm__button(
6
+ v-on="{ ...$listeners, ...(disablePrompt ? {} : on) }"
7
+ v-bind="buttonProps")
6
8
  slot
7
9
  w-flex(:column="!inline" align-center)
8
10
  div
@@ -32,6 +34,7 @@ export default {
32
34
  bgColor: { type: String },
33
35
  color: { type: String },
34
36
  icon: { type: String },
37
+ disablePrompt: { type: Boolean }, // If true, the confirm button acts like a simple w-button.
35
38
  mainButton: { type: Object }, // Allow passing down an object of props to the w-button component.
36
39
  question: { type: String, default: 'Are you sure?' },
37
40
 
@@ -302,7 +302,7 @@ export default {
302
302
  // eslint-disable-next-line vue/custom-event-name-casing
303
303
  else if (e.keyCode === 27) this.$emit('keydown:escape')
304
304
  // On arrow keys press, navigate to prev/next item.
305
- else if (this.arrowsNavigation) {
305
+ else if (this.arrowsNavigation && [38, 40].includes(e.keyCode)) {
306
306
  e.preventDefault()
307
307
  if (e.keyCode === 38) this.focusPrevNextItem(li._index, false)
308
308
  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(
@@ -299,7 +299,7 @@ export default {
299
299
  // Also accept objects if returnObject is true.
300
300
  // In any case, always end up with an array.
301
301
  checkSelection (items) {
302
- items = Array.isArray(items) ? items : (items ? [items] : [])
302
+ items = Array.isArray(items) ? items : (items !== undefined ? [items] : [])
303
303
  // `selectItems` items always have a value.
304
304
  const allValues = this.selectItems.map(item => item.value)
305
305
 
@@ -424,8 +424,10 @@ export default {
424
424
  &__selection {
425
425
  width: 100%;
426
426
  height: 100%;
427
- font-size: inherit;
427
+ min-height: inherit;
428
+ font: inherit;
428
429
  color: inherit;
430
+ text-align: inherit;
429
431
  background: none;
430
432
  border: none;
431
433
  outline: none;
@@ -522,12 +524,15 @@ export default {
522
524
  position: absolute;
523
525
  top: 50%;
524
526
  left: 0;
527
+ right: 0;
525
528
  // Use margin instead of padding as the scale transformation bellow decreases the real padding
526
529
  // size and misaligns the label.
527
530
  margin-left: 2 * $base-increment;
528
531
  transform: translateY(-50%);
529
532
  pointer-events: none;
530
533
 
534
+ .w-select--inner-icon-right & {padding-right: 22px;}
535
+
531
536
  .w-select--no-padding & {
532
537
  left: 0;
533
538
  margin-left: 0;
@@ -38,7 +38,7 @@ component(
38
38
  v-if="loading"
39
39
  circle
40
40
  color="inherit"
41
- v-bind="typeof loading === 'number' ? { 'model-value': loading } : {}")
41
+ v-bind="typeof loading === 'number' ? { value: loading } : {}")
42
42
  slot(v-else name="thumb")
43
43
  template(v-if="hasLabel && !labelOnLeft")
44
44
  label.w-switch__label.w-switch__label--right.w-form-el-shakable(
@@ -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 ? 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: ['input', '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
  },
@@ -183,6 +186,7 @@ export default {
183
186
  * @param {String} selector any valid DOM selector to match the siblings.
184
187
  */
185
188
  getPreviousSibling (node, selector) {
189
+ // eslint-disable-next-line no-unmodified-loop-condition
186
190
  while (selector && (node = node.previousElementSibling)) {
187
191
  if (node.matches(selector)) return node
188
192
  }
@@ -196,6 +200,7 @@ export default {
196
200
  * @param {String} selector any valid DOM selector to match the siblings.
197
201
  */
198
202
  getNextSibling (node, selector) {
203
+ // eslint-disable-next-line no-unmodified-loop-condition
199
204
  while (selector && (node = node.nextElementSibling)) {
200
205
  if (node.matches(selector)) return node
201
206
  }
@@ -208,7 +213,7 @@ export default {
208
213
 
209
214
  itemIcon (item) {
210
215
  return (
211
- item.originalItem.icon ||
216
+ item.originalItem[this.itemIconKey] ||
212
217
  (!item.children && !item.branch && this.leafIcon) ||
213
218
  ((item.children || item.branch) && ((item.open && this.branchOpenIcon) || this.branchIcon))
214
219
  )
@@ -230,7 +235,7 @@ export default {
230
235
  // The open property of each item has to be retained from this.currentDepthItems in order to stay
231
236
  // in the same state after DOM repaint.
232
237
  items => this.updateCurrentDepthTree(items, this.currentDepthItems),
233
- { 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.
234
239
  )
235
240
  },
236
241