wave-ui 3.0.5 → 3.1.1

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": "3.0.5",
3
+ "version": "3.1.1",
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",
@@ -49,24 +49,25 @@
49
49
  "lint": "vite lint"
50
50
  },
51
51
  "devDependencies": {
52
- "@babel/core": "^7.21.0",
53
- "@babel/eslint-parser": "^7.19.1",
52
+ "@babel/core": "^7.21.3",
53
+ "@babel/eslint-parser": "^7.21.3",
54
54
  "@babel/plugin-proposal-class-properties": "^7.18.6",
55
+ "@faker-js/faker": "^7.6.0",
55
56
  "@mdi/font": "^5.9.55",
56
57
  "@vitejs/plugin-vue": "^3.2.0",
57
58
  "@vue/compiler-sfc": "3.2.45",
58
- "autoprefixer": "^10.4.13",
59
- "axios": "^0.25.0",
60
- "eslint": "^7.32.0",
61
- "eslint-plugin-vue": "^9.9.0",
59
+ "autoprefixer": "^10.4.14",
60
+ "axios": "^1.3.4",
61
+ "eslint": "^8.36.0",
62
+ "eslint-plugin-vue": "^9.10.0",
62
63
  "font-awesome": "^4.7.0",
63
- "gsap": "^3.11.4",
64
+ "gsap": "^3.11.5",
64
65
  "ionicons": "^4.6.3",
65
66
  "material-design-icons": "^3.0.1",
66
67
  "postcss": "^8.4.21",
67
68
  "pug": "^3.0.2",
68
69
  "rollup-plugin-delete": "^2.0.0",
69
- "sass": "^1.58.3",
70
+ "sass": "^1.60.0",
70
71
  "simple-syntax-highlighter": "^2.2.5",
71
72
  "splitpanes": "^3.1.5",
72
73
  "standard": "^17.0.0",
@@ -119,7 +119,9 @@ component(
119
119
 
120
120
  <script>
121
121
  /**
122
- * @todo Share the common parts between w-input, w-textarea & w-select.
122
+ * @todo
123
+ * - Share the common parts between w-input, w-textarea & w-select.
124
+ * - option to fit to the content using contenteditable div
123
125
  **/
124
126
 
125
127
  import FormElementMixin from '../mixins/form-elements'
@@ -581,6 +583,7 @@ $inactive-color: #777;
581
583
  top: 50%;
582
584
  left: 0;
583
585
  padding-left: 2 * $base-increment;
586
+ white-space: nowrap;
584
587
  transform: translateY(-50%);
585
588
  pointer-events: none;
586
589
 
@@ -40,21 +40,19 @@ component(
40
40
  .w-select__selection-slot(v-if="$slots.selection")
41
41
  //- inputValue is always an array.
42
42
  slot(name="selection" :item="multiple ? inputValue : inputValue[0]")
43
- input.w-select__selection(
43
+ .w-select__selection(
44
44
  ref="selection-input"
45
- type="text"
46
- :value="$slots.selection ? '' : selectionString"
45
+ :contenteditable="isDisabled || isReadonly ? 'false' : 'true'"
47
46
  @focus="!isDisabled && !isReadonly && onFocus($event)"
48
47
  @blur="onBlur"
49
48
  @keydown="!isDisabled && !isReadonly && onKeydown($event)"
50
49
  :id="`w-select--${_.uid}`"
51
- :placeholder="(!$slots.selection && placeholder) || null"
50
+ :class="{ 'w-select__selection--placeholder': !$slots.selection && !selectionString && placeholder }"
52
51
  :disabled="isDisabled || null"
53
52
  readonly
54
53
  aria-readonly="true"
55
- :required="required || null"
56
54
  :tabindex="tabindex || null"
57
- autocomplete="off")
55
+ v-html="$slots.selection ? '' : selectionString || placeholder")
58
56
  //- For standard HTML form submission.
59
57
  input(
60
58
  v-for="(val, i) in (inputValue.length ? inputValue : [{}])"
@@ -149,7 +147,8 @@ export default {
149
147
  noUnselect: { type: Boolean },
150
148
  menuProps: { type: Object }, // Allow passing down an object of props to the w-menu component.
151
149
  dark: { type: Boolean },
152
- light: { type: Boolean }
150
+ light: { type: Boolean },
151
+ fitToContent: { type: Boolean }
153
152
  // Props from mixin: name, disabled, readonly, required, tabindex, validators.
154
153
  // Computed from mixin: inputName, isDisabled & isReadonly.
155
154
  },
@@ -200,6 +199,7 @@ export default {
200
199
  'w-select--dark': this.dark,
201
200
  'w-select--light': this.light,
202
201
  'w-select--disabled': this.isDisabled,
202
+ 'w-select--fit-to-content': this.fitToContent,
203
203
  'w-select--readonly': this.isReadonly,
204
204
  [`w-select--${this.hasValue ? 'filled' : 'empty'}`]: true,
205
205
  'w-select--focused': (this.isFocused || this.showMenu) && !this.isReadonly,
@@ -230,6 +230,7 @@ export default {
230
230
  onFocus (e) {
231
231
  this.isFocused = true
232
232
  this.$emit('focus', e)
233
+ return false
233
234
  },
234
235
 
235
236
  onBlur (e) {
@@ -238,6 +239,11 @@ export default {
238
239
  },
239
240
 
240
241
  onKeydown (e) {
242
+ // Forbid typing in contenteditable element.
243
+ // Note: using contenteditable rather than input in order to be able to fit the select list
244
+ // to its content with CSS. Only contenteditable divs/non-interactive elements can react to focus/blur ).
245
+ e.preventDefault()
246
+
241
247
  if ([13, 27, 38, 40].includes(e.keyCode)) e.preventDefault()
242
248
 
243
249
  if (e.keyCode === 27) this.closeMenu() // Escape.
@@ -300,7 +306,6 @@ export default {
300
306
  // Also accept objects if returnObject is true.
301
307
  // In any case, always end up with an array.
302
308
  checkSelection (items) {
303
- console.log(items)
304
309
  items = Array.isArray(items) ? items : (items !== undefined ? [items] : [])
305
310
  // `selectItems` items always have a value.
306
311
  const allValues = this.selectItems.map(item => item.value)
@@ -368,6 +373,11 @@ export default {
368
373
  -webkit-tap-highlight-color: transparent;
369
374
  }
370
375
 
376
+ &--fit-to-content {
377
+ display: inline-flex;
378
+ flex-grow: 0;
379
+ }
380
+
371
381
  // Selection wrapper.
372
382
  // ------------------------------------------------------
373
383
  &__selection-wrap {
@@ -423,21 +433,21 @@ export default {
423
433
  }
424
434
  }
425
435
 
426
- // selection (input) field.
436
+ // Selection (contenteditable) field.
437
+ // Using contenteditable instead of readonly input in order to be able to fit to content.
438
+ // Then disable typing and hide caret.
427
439
  // ------------------------------------------------------
428
440
  &__selection {
429
441
  width: 100%;
430
442
  height: 100%;
431
443
  min-height: inherit;
432
- font: inherit;
433
- color: inherit;
434
- text-align: inherit;
435
- background: none;
436
- border: none;
437
444
  outline: none;
438
445
  padding-left: 2 * $base-increment;
439
446
  padding-right: 2 * $base-increment;
447
+ display: flex;
448
+ align-items: center;
440
449
  cursor: pointer;
450
+ caret-color: transparent;
441
451
 
442
452
  .w-select__selection-slot + & {
443
453
  position: absolute;
@@ -463,9 +473,9 @@ export default {
463
473
  -webkit-tap-highlight-color: transparent;
464
474
  }
465
475
 
466
- .w-select--disabled input::placeholder {color: inherit;}
467
-
468
476
  .w-select--readonly & {cursor: auto;}
477
+
478
+ &--placeholder {color: #888;}
469
479
  }
470
480
 
471
481
  &__selection-slot {
@@ -529,6 +539,7 @@ export default {
529
539
  top: 50%;
530
540
  left: 0;
531
541
  right: 0;
542
+ white-space: nowrap;
532
543
  // Use margin instead of padding as the scale transformation below decreases the real padding
533
544
  // size and misaligns the label.
534
545
  margin-left: 2 * $base-increment;
@@ -59,7 +59,7 @@
59
59
 
60
60
  //- Normal rows.
61
61
  template(v-if="tableItems.length && loading !== true")
62
- template(v-for="(item, i) in sortedItems" :key="i")
62
+ template(v-for="(item, i) in paginatedItems" :key="i")
63
63
  //- Fully custom tr (`item` slot).
64
64
  slot(
65
65
  v-if="$slots.item"
@@ -136,26 +136,41 @@
136
136
  tr.w-table__row.w-table__pagination-wrap(v-if="pagination && paginationConfig")
137
137
  td.w-table__cell(:colspan="headers.length")
138
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)
139
+ | {{ paginationConfig }}
140
+ slot(
141
+ name="pagination"
142
+ :range="`${paginationConfig.start}-${paginationConfig.end} of ${paginationConfig.total}`"
143
+ :total="paginationConfig.total")
144
+ w-select.pagination-number.pagination-number--items-per-page(
145
+ v-if="paginationConfig.itemsPerPageOptions"
146
+ v-model="paginationConfig.itemsPerPage"
147
+ @input="updatePaginationConfig"
148
+ :items="paginationConfig.itemsPerPageOptions"
149
+ label-position="left"
150
+ label="Items per page"
151
+ label-color="inherit")
152
+ .pagination-arrows
153
+ w-button.pagination-arrow.pagination-arrow--prev(
154
+ @click="goToPage('-1')"
155
+ :disabled="paginationConfig.page <= 1"
156
+ icon="wi-chevron-left"
157
+ text
158
+ lg)
159
+ w-button.pagination-arrow.pagination-arrow--prev(
160
+ v-for="i in paginationConfig.pagesCount"
161
+ :key="i"
162
+ @click="goToPage(i)"
163
+ round
164
+ text
165
+ lg) {{ i }}
166
+ w-button.pagination-arrow.pagination-arrow--next(
167
+ @click="goToPage('+1')"
168
+ :disabled="paginationConfig.page >= paginationConfig.pagesCount"
169
+ icon="wi-chevron-right"
170
+ text
171
+ lg)
172
+ span.pagination-number.pagination-number--results.
173
+ {{ paginationConfig.start }}-{{ paginationConfig.end }} of {{ paginationConfig.total }}
159
174
  </template>
160
175
 
161
176
  <script>
@@ -339,6 +354,10 @@ export default {
339
354
  // Faster lookup than array.includes(uid) and also cached.
340
355
  expandedRowsByUid () {
341
356
  return this.expandedRowsInternal.reduce((obj, uid) => (obj[uid] = true) && obj, {})
357
+ },
358
+
359
+ paginatedItems () {
360
+ return this.sortedItems.slice(this.paginationConfig.start, this.paginationConfig.end)
342
361
  }
343
362
  },
344
363
 
@@ -535,17 +554,32 @@ export default {
535
554
  },
536
555
 
537
556
  updatePaginationConfig () {
538
- const itemsPerPage = this.pagination?.itemsPerPage || 10
557
+ const itemsPerPage = this.pagination?.itemsPerPage || 20
558
+ const itemsPerPageOptions = this.pagination?.itemsPerPageOptions || [20, 100, { label: 'All', value: 0 }]
539
559
  const total = this.pagination?.total || this.items.length
560
+ const itemsPerPageOrTotal = itemsPerPage || total
540
561
  const page = this.pagination?.page || 1
541
562
  this.paginationConfig = {
542
563
  itemsPerPage,
543
- itemsPerPageOptions: this.pagination?.itemsPerPageOptions || [{ label: '10', value: 10 }, { label: '100', value: 100 }, { label: 'All', value: 0 }],
564
+ itemsPerPageOptions: itemsPerPageOptions.map(item => ({
565
+ label: ['string', 'number'].includes(typeof item) ? item.toString() : (item.label || item.value),
566
+ value: ['string', 'number'].includes(typeof item) ? ~~item : (item.value ?? item.label)
567
+ })),
544
568
  page,
545
569
  start: this.pagination?.start || 1,
546
- end: total >= (itemsPerPage * page) ? (itemsPerPage * page) : (total % (itemsPerPage * page)),
547
- total
570
+ end: total >= (itemsPerPageOrTotal * page) ? (itemsPerPageOrTotal * page) : (total % (itemsPerPageOrTotal * page)),
571
+ total,
572
+ pagesCount: Math.ceil(total / itemsPerPageOrTotal)
548
573
  }
574
+ },
575
+
576
+ goToPage (page) {
577
+ if (['-1', '+1'].includes(page)) this.paginationConfig.page += +page
578
+ else this.paginationConfig.page = page
579
+ const { itemsPerPage } = this.paginationConfig
580
+ this.paginationConfig.page = Math.max(1, this.paginationConfig.page)
581
+ this.paginationConfig.start = (itemsPerPage * (this.paginationConfig.page - 1)) + 1
582
+ this.paginationConfig.end = (this.paginationConfig.start - 1) + itemsPerPage
549
583
  }
550
584
  },
551
585
 
@@ -581,6 +615,11 @@ export default {
581
615
 
582
616
  selectedRows (array) {
583
617
  this.selectedRowsInternal = Array.isArray(array) && array.length ? this.selectedRows : []
618
+ },
619
+
620
+ pagination: {
621
+ handler () { this.updatePaginationConfig() },
622
+ deep: true
584
623
  }
585
624
  }
586
625
  }
@@ -800,27 +839,31 @@ $tr-border-top: 1px;
800
839
  }
801
840
  }
802
841
 
842
+ // Pagination.
843
+ // ------------------------------------------------------
844
+ &__pagination-wrap {
845
+ border-top: $border;
846
+ }
803
847
  &__pagination {
804
848
  display: flex;
805
849
  align-items: center;
806
850
  justify-content: flex-end;
807
- padding-top: $base-increment;
808
- padding-bottom: $base-increment;
809
851
 
810
852
  .pagination-number--items-per-page {
811
- margin-right: 6 * $base-increment;
812
853
  flex-grow: 0;
813
854
  text-align: right;
814
855
  }
856
+
857
+ .pagination-arrows {
858
+ margin-left: 3 * $base-increment;
859
+ margin-right: 3 * $base-increment;
860
+ }
861
+
815
862
  .pagination-number--of {
816
863
  margin-left: $base-increment;
817
864
  margin-right: $base-increment;
818
865
  }
819
866
  .w-select__selection {max-width: 60px;}
820
-
821
- .pagination-arrows {
822
- margin-left: 6 * $base-increment;
823
- }
824
867
  }
825
868
  }
826
869
 
@@ -355,6 +355,7 @@ $inactive-color: #777;
355
355
  top: $base-increment;
356
356
  left: 0;
357
357
  padding-left: 2 * $base-increment;
358
+ white-space: nowrap;
358
359
  transform: translateY(0%);
359
360
  pointer-events: none;
360
361
 
@@ -48,7 +48,7 @@ $base-font-size: 14px !default; // Must be a px unit.
48
48
  $base-increment: round(divide($base-font-size, 4)) !default;
49
49
  $layout-padding: $base-increment * 4 !default; // Applied on the .content-wrap tag.
50
50
  $border-radius: 3px !default;
51
- $border-color: rgba(var(--w-contrast-bg-color-rgb), 0.15) !default;
51
+ $border-color: rgba(var(--w-contrast-bg-color-rgb), 0.12) !default;
52
52
  $border: 1px solid $border-color !default;
53
53
  $transition-duration: 0.25s !default;
54
54
  $fast-transition-duration: 0.15s !default;
@@ -275,8 +275,10 @@ export const injectColorsCSSInDOM = themeColors => {
275
275
  css.id = 'wave-ui-colors'
276
276
  css.innerHTML = generateColors(themeColors)
277
277
 
278
- const firstStyle = document.head.querySelectorAll('style,link[rel="stylesheet"]')[0]
279
- if (firstStyle) firstStyle.before(css)
278
+ // Keep the injected colors at the end of other styles.
279
+ // This should have priority over the user rules that have the same specificity.
280
+ const styles = document.head.querySelectorAll('style,link[rel="stylesheet"]')
281
+ if (styles.length) styles[styles.length - 1].after(css)
280
282
  else document.head.appendChild(css)
281
283
  }
282
284
  }