@veritree/ui 0.24.0 → 0.25.0-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.
Files changed (74) hide show
  1. package/index.js +64 -72
  2. package/mixins/floating-ui-content.js +1 -1
  3. package/mixins/floating-ui-item.js +11 -7
  4. package/mixins/floating-ui.js +8 -1
  5. package/mixins/form-control-icon.js +3 -3
  6. package/mixins/form-control.js +9 -14
  7. package/nuxt.js +30 -24
  8. package/package.json +14 -6
  9. package/src/components/Alert/VTAlert.vue +55 -14
  10. package/src/components/Avatar/VTAvatarImage.vue +6 -26
  11. package/src/components/Button/VTButton.vue +25 -11
  12. package/src/components/Checkbox/VTCheckbox.vue +134 -0
  13. package/src/components/Checkbox/VTCheckboxLabel.vue +3 -0
  14. package/src/components/Checkbox/VTCheckboxText.vue +20 -0
  15. package/src/components/Dialog/VTDialog.vue +22 -23
  16. package/src/components/Dialog/VTDialogClose.vue +1 -1
  17. package/src/components/Dialog/VTDialogContent.vue +13 -5
  18. package/src/components/Dialog/VTDialogFooter.vue +8 -2
  19. package/src/components/Dialog/VTDialogHeader.vue +2 -1
  20. package/src/components/Dialog/VTDialogMain.vue +1 -1
  21. package/src/components/Dialog/VTDialogOverlay.vue +5 -1
  22. package/src/components/Disclosure/VTDisclosureContent.vue +1 -1
  23. package/src/components/Disclosure/VTDisclosureDetails.vue +1 -1
  24. package/src/components/Disclosure/VTDisclosureHeader.vue +2 -2
  25. package/src/components/Disclosure/VTDisclosureIcon.vue +1 -1
  26. package/src/components/Drawer/VTDrawer.vue +6 -15
  27. package/src/components/Drawer/VTDrawerClose.vue +5 -5
  28. package/src/components/Drawer/VTDrawerContent.vue +10 -10
  29. package/src/components/Drawer/VTDrawerFooter.vue +4 -4
  30. package/src/components/Drawer/VTDrawerHeader.vue +4 -4
  31. package/src/components/Drawer/VTDrawerMain.vue +5 -5
  32. package/src/components/Drawer/VTDrawerOverlay.vue +6 -6
  33. package/src/components/Drawer/VTDrawerTitle.vue +5 -5
  34. package/src/components/DropdownMenu/VTDropdownMenu.vue +0 -6
  35. package/src/components/DropdownMenu/VTDropdownMenuContent.vue +10 -1
  36. package/src/components/DropdownMenu/VTDropdownMenuDivider.vue +7 -16
  37. package/src/components/DropdownMenu/VTDropdownMenuItem.vue +5 -1
  38. package/src/components/DropdownMenu/VTDropdownMenuLabel.vue +1 -10
  39. package/src/components/DropdownMenu/VTDropdownMenuTrigger.vue +2 -4
  40. package/src/components/Form/VTFormFeedback.vue +7 -1
  41. package/src/components/Form/VTFormGroup.vue +5 -7
  42. package/src/components/Form/VTFormLabel.vue +22 -0
  43. package/src/components/Form/VTFormRow.vue +5 -0
  44. package/src/components/Form/VTInput.vue +2 -5
  45. package/src/components/Form/VTInputIcon.vue +1 -2
  46. package/src/components/Form/VTInputPassword.vue +14 -5
  47. package/src/components/Form/VTTextarea.vue +3 -6
  48. package/src/components/Image/VTImage.vue +39 -8
  49. package/src/components/Listbox/VTListbox.vue +72 -5
  50. package/src/components/Listbox/VTListboxContent.vue +0 -1
  51. package/src/components/Listbox/VTListboxItem.vue +11 -1
  52. package/src/components/Listbox/VTListboxLabel.vue +3 -4
  53. package/src/components/Listbox/VTListboxList.vue +3 -1
  54. package/src/components/Listbox/VTListboxSearch.vue +10 -7
  55. package/src/components/Listbox/VTListboxTrigger.vue +2 -0
  56. package/src/components/Popover/VTPopoverContent.vue +3 -3
  57. package/src/components/Popover/VTPopoverItem.vue +6 -2
  58. package/src/components/ProgressBar/VTProgressBar.vue +21 -3
  59. package/src/components/Skeleton/VTSkeleton.vue +11 -0
  60. package/src/components/Skeleton/VTSkeletonItem.vue +9 -0
  61. package/src/components/Tabs/VTTab.vue +6 -5
  62. package/src/components/Tabs/VTTabGroup.vue +9 -7
  63. package/src/components/Tabs/VTTabPanel.vue +4 -5
  64. package/src/components/Tooltip/VTTooltipTrigger.vue +3 -5
  65. package/src/components/Transitions/FadeInOut.vue +2 -2
  66. package/src/components/Utils/FloatingUi.vue +31 -13
  67. package/src/utils/components.js +18 -0
  68. package/src/utils/images.js +18 -25
  69. package/src/components/Input/VTInput.vue +0 -82
  70. package/src/components/Input/VTInputDate.vue +0 -36
  71. package/src/components/Input/VTInputFile.vue +0 -60
  72. package/src/components/Input/VTInputUpload.vue +0 -54
  73. package/src/components/Modal/VTModal.vue +0 -69
  74. package/src/utils/genId.js +0 -13
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <component :is="as" :class="{ 'dialog-footer': headless }">
2
+ <component :is="as" :class="{ 'Dialog-footer': headless }">
3
3
  <slot></slot>
4
4
  </component>
5
5
  </template>
@@ -8,7 +8,7 @@
8
8
  export default {
9
9
  name: 'VTDrawerFooter',
10
10
 
11
- inject: ['api'],
11
+ inject: ['apiDrawer'],
12
12
 
13
13
  props: {
14
14
  as: {
@@ -19,11 +19,11 @@ export default {
19
19
 
20
20
  computed: {
21
21
  dark() {
22
- return this.api().isDark;
22
+ return this.apiDrawer().isDark;
23
23
  },
24
24
 
25
25
  headless() {
26
- return this.api().isHeadless;
26
+ return this.apiDrawer().isHeadless;
27
27
  },
28
28
  },
29
29
  };
@@ -15,7 +15,7 @@
15
15
  export default {
16
16
  name: 'VTDrawerHeader',
17
17
 
18
- inject: ['api'],
18
+ inject: ['apiDrawer'],
19
19
 
20
20
  props: {
21
21
  as: {
@@ -26,15 +26,15 @@ export default {
26
26
 
27
27
  computed: {
28
28
  dark() {
29
- return this.api().isDark;
29
+ return this.apiDrawer().isDark;
30
30
  },
31
31
 
32
32
  headless() {
33
- return this.api().isHeadless;
33
+ return this.apiDrawer().isHeadless;
34
34
  },
35
35
 
36
36
  id() {
37
- return `${this.api().id}-header`;
37
+ return `${this.apiDrawer().id}-header`;
38
38
  },
39
39
  },
40
40
  };
@@ -12,7 +12,7 @@
12
12
  export default {
13
13
  name: 'VTDrawerMain',
14
14
 
15
- inject: ['api'],
15
+ inject: ['apiDrawer'],
16
16
 
17
17
  props: {
18
18
  as: {
@@ -23,15 +23,15 @@ export default {
23
23
 
24
24
  computed: {
25
25
  dark() {
26
- return this.api().isDark;
26
+ return this.apiDrawer().isDark;
27
27
  },
28
28
 
29
29
  headless() {
30
- return this.api().isHeadless;
30
+ return this.apiDrawer().isHeadless;
31
31
  },
32
32
 
33
33
  id() {
34
- return `${this.api().id}-desc`;
34
+ return `${this.apiDrawer().id}-desc`;
35
35
  },
36
36
  },
37
37
 
@@ -42,7 +42,7 @@ export default {
42
42
  methods: {
43
43
  // In here because if there is no body, the dialog will not be described by
44
44
  setDialogDescribedby() {
45
- const dialog = document.getElementById(this.api().id);
45
+ const dialog = document.getElementById(this.apiDrawer().id);
46
46
 
47
47
  if (dialog) {
48
48
  dialog.setAttribute('aria-describedby', this.id);
@@ -12,14 +12,14 @@
12
12
  </template>
13
13
 
14
14
  <script>
15
- import FadeInOut from "../Transitions/FadeInOut.vue";
15
+ import FadeInOut from '../Transitions/FadeInOut.vue';
16
16
 
17
17
  export default {
18
18
  components: {
19
19
  FadeInOut,
20
20
  },
21
21
 
22
- inject: ["api"],
22
+ inject: ['apiDrawer'],
23
23
 
24
24
  data() {
25
25
  return {
@@ -29,21 +29,21 @@ export default {
29
29
 
30
30
  computed: {
31
31
  dark() {
32
- return this.api().isDark;
32
+ return this.apiDrawer().isDark;
33
33
  },
34
34
 
35
35
  headless() {
36
- return this.api().isHeadless;
36
+ return this.apiDrawer().isHeadless;
37
37
  },
38
38
 
39
39
  id() {
40
- return `${this.api().id}-overlay`;
40
+ return `${this.apiDrawer().id}-overlay`;
41
41
  },
42
42
  },
43
43
 
44
44
  mounted() {
45
45
  this.visible = true;
46
- this.api().registerOverlay(this);
46
+ this.apiDrawer().registerOverlay(this);
47
47
  },
48
48
 
49
49
  methods: {
@@ -15,7 +15,7 @@
15
15
  export default {
16
16
  name: 'VTDrawerTitle',
17
17
 
18
- inject: ['api'],
18
+ inject: ['apiDrawer'],
19
19
 
20
20
  props: {
21
21
  as: {
@@ -26,15 +26,15 @@ export default {
26
26
 
27
27
  computed: {
28
28
  dark() {
29
- return this.api().isDark;
29
+ return this.apiDrawer().isDark;
30
30
  },
31
31
 
32
32
  headless() {
33
- return this.api().isHeadless;
33
+ return this.apiDrawer().isHeadless;
34
34
  },
35
35
 
36
36
  id() {
37
- return `${this.api().id}-title`;
37
+ return `${this.apiDrawer().id}-title`;
38
38
  },
39
39
  },
40
40
 
@@ -45,7 +45,7 @@ export default {
45
45
  methods: {
46
46
  // In here because if there is no header, the dialog will not be labelled by
47
47
  setDialogLabelledby() {
48
- const dialog = document.getElementById(this.api().id);
48
+ const dialog = document.getElementById(this.apiDrawer().id);
49
49
 
50
50
  if (dialog) {
51
51
  dialog.setAttribute('aria-labelledby', this.id);
@@ -83,11 +83,5 @@ export default {
83
83
  floatingUiMinWidth: 200,
84
84
  };
85
85
  },
86
-
87
- computed: {
88
- id() {
89
- return `dropdown-menu-${this.componentId}`;
90
- },
91
- },
92
86
  };
93
87
  </script>
@@ -3,7 +3,6 @@
3
3
  :id="id"
4
4
  :visible="visible"
5
5
  :headless="headless"
6
- :portal-class="$vnode.data.staticClass"
7
6
  component="dropdown"
8
7
  >
9
8
  <slot></slot>
@@ -46,5 +45,15 @@ export default {
46
45
 
47
46
  this.apiDropdownMenu().registerContent(content);
48
47
  },
48
+
49
+ methods: {
50
+ hidden() {
51
+ this.$emit('hidden');
52
+ },
53
+
54
+ shown() {
55
+ this.$emit('shown');
56
+ },
57
+ },
49
58
  };
50
59
  </script>
@@ -1,9 +1,8 @@
1
1
  <template>
2
2
  <div
3
- :class="{
4
- PopoverDivider: headless,
5
- '-mx-3 my-2 h-[1px]': !headless,
6
- }"
3
+ :class="[
4
+ headless ? 'dropdown-menu-divider' : '-mx-3 my-2 h-[1px] bg-gray-200',
5
+ ]"
7
6
  ></div>
8
7
  </template>
9
8
 
@@ -13,18 +12,10 @@ export default {
13
12
 
14
13
  inject: ['apiDropdownMenu'],
15
14
 
16
- headless: {
17
- type: Boolean,
18
- default: false,
19
- },
20
-
21
- computed: {
22
- dark() {
23
- return this.apiDropdownMenu().isDark;
24
- },
25
-
26
- headless() {
27
- return this.apiDropdownMenu().isHeadless;
15
+ props: {
16
+ headless: {
17
+ type: Boolean,
18
+ default: false,
28
19
  },
29
20
  },
30
21
  };
@@ -51,7 +51,11 @@ export default {
51
51
 
52
52
  computed: {
53
53
  as() {
54
- return this.href ? 'a' : this.to ? 'NuxtLink' : 'button';
54
+ return this.href
55
+ ? 'a'
56
+ : this.to
57
+ ? resolveComponent('NuxtLink')
58
+ : 'button';
55
59
  },
56
60
  },
57
61
  };
@@ -1,11 +1,6 @@
1
1
  <template>
2
2
  <span
3
- :class="{
4
- MenuLabel: headless,
5
- 'mb-2 block text-xs uppercase': !headless,
6
- 'text-inherit': !dark,
7
- 'text-white': dark,
8
- }"
3
+ :class="[headless ? 'dropdown-menu-label' : 'mb-2 block text-xs uppercase']"
9
4
  >
10
5
  <slot></slot>
11
6
  </span>
@@ -18,10 +13,6 @@ export default {
18
13
  inject: ['apiDropdownMenu'],
19
14
 
20
15
  computed: {
21
- dark() {
22
- return this.apiDropdownMenu().isDark;
23
- },
24
-
25
16
  headless() {
26
17
  return this.apiDropdownMenu().isHeadless;
27
18
  },
@@ -57,7 +57,7 @@ export default {
57
57
 
58
58
  mounted() {
59
59
  const trigger = {
60
- id: this.id,
60
+ id: this.$el.getAttribute('id'), // avoids issues with hydration
61
61
  el: this.$el,
62
62
  cancel: this.cancel,
63
63
  focus: this.focus,
@@ -89,9 +89,7 @@ export default {
89
89
  * errors related to adding the event listener.
90
90
  */
91
91
  addTriggerEvents() {
92
- this.trigger.addEventListener('click', (e) => {
93
- this.onClick(e);
94
- });
92
+ this.trigger.addEventListener('click', this.onClick);
95
93
  },
96
94
 
97
95
  init(e) {
@@ -19,7 +19,13 @@
19
19
  : null,
20
20
  ]"
21
21
  />
22
- <span :class="[headless ? 'form-feedback--text' : 'text-sm text-gray-500']">
22
+ <span
23
+ :class="[
24
+ headless
25
+ ? 'form-feedback--text'
26
+ : 'text-sm lowercase text-gray-500 first-letter:uppercase',
27
+ ]"
28
+ >
23
29
  <slot />
24
30
  </span>
25
31
  </div>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <component :is="as" :class="classes" class="form-group">
2
+ <component :is="as" :class="[headless ? 'form-control' : 'mt-3']">
3
3
  <slot></slot>
4
4
  </component>
5
5
  </template>
@@ -11,12 +11,10 @@ export default {
11
11
  type: String,
12
12
  default: 'div',
13
13
  },
14
- },
15
-
16
- data() {
17
- return {
18
- classes: {},
19
- };
14
+ headless: {
15
+ type: Boolean,
16
+ default: false,
17
+ },
20
18
  },
21
19
  };
22
20
  </script>
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <label
3
+ :class="[
4
+ headless
5
+ ? 'form-label'
6
+ : 'mb-1 flex justify-between gap-3 text-sm font-semibold',
7
+ ]"
8
+ >
9
+ <slot />
10
+ </label>
11
+ </template>
12
+
13
+ <script>
14
+ export default {
15
+ props: {
16
+ headless: {
17
+ type: Boolean,
18
+ default: false,
19
+ },
20
+ },
21
+ };
22
+ </script>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="grid grid-cols-1 md:grid-cols-2 md:gap-4">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <input
3
3
  :class="classComputed"
4
- :value="value"
4
+ :value="modelValue"
5
5
  :disabled="disabled"
6
- v-on="listeners"
6
+ v-bind="attrsComputed"
7
7
  />
8
8
  </template>
9
9
 
@@ -12,10 +12,8 @@ import {
12
12
  formControlMixin,
13
13
  formControlStyleMixin,
14
14
  } from '../../../mixins/form-control';
15
-
16
15
  export default {
17
16
  mixins: [formControlMixin, formControlStyleMixin],
18
-
19
17
  data() {
20
18
  return {
21
19
  name: 'input',
@@ -30,7 +28,6 @@ input[type='date']::-webkit-calendar-picker-indicator {
30
28
  position: absolute;
31
29
  opacity: 0;
32
30
  } */
33
-
34
31
  input[type='number'] {
35
32
  appearance: textfield;
36
33
  }
@@ -4,8 +4,7 @@
4
4
  :class="classComputed"
5
5
  :value="value"
6
6
  :disabled="disabled"
7
- v-bind="$attrs"
8
- v-on="listeners"
7
+ v-bind="attrsComputed"
9
8
  />
10
9
  <div :class="classComputedWrapperIcon">
11
10
  <component :is="icon" class="h-5 w-5" />
@@ -2,21 +2,25 @@
2
2
  <div :class="classComputedWrapper">
3
3
  <input
4
4
  :class="classComputed"
5
- :value="value"
5
+ :value="modelValue"
6
6
  :disabled="disabled"
7
7
  :type="reveal ? 'text' : 'password'"
8
- v-bind="$attrs"
9
- v-on="listeners"
8
+ v-bind="attrsComputed"
10
9
  />
11
10
  <div :class="classComputedWrapperIcon">
12
- <VTButton v-show="value.length" variant="icon" @click="reveal = !reveal">
13
- <component :is="iconVisibility" class="h-5 w-5" />
11
+ <VTButton
12
+ v-show="modelValue.length"
13
+ variant="icon"
14
+ @click="reveal = !reveal"
15
+ >
16
+ <component :is="iconVisibility" class="h-5 w-5 text-gray-500" />
14
17
  </VTButton>
15
18
  </div>
16
19
  </div>
17
20
  </template>
18
21
 
19
22
  <script>
23
+ import { IconVisibilityOn, IconVisibilityOff } from '@veritree/icons';
20
24
  import { formControlIconMixin } from '../../../mixins/form-control-icon';
21
25
 
22
26
  export default {
@@ -24,6 +28,11 @@ export default {
24
28
 
25
29
  mixins: [formControlIconMixin],
26
30
 
31
+ components: {
32
+ IconVisibilityOn,
33
+ IconVisibilityOff,
34
+ },
35
+
27
36
  props: {
28
37
  iconPlacement: {
29
38
  type: String,
@@ -3,18 +3,15 @@
3
3
  :class="classComputed"
4
4
  :value="value"
5
5
  :disabled="disabled"
6
- v-on="listeners"
6
+ v-bind="attrsComputed"
7
7
  />
8
8
  </template>
9
9
 
10
10
  <script>
11
- import {
12
- formControlMixin,
13
- formControlStyleMixin,
14
- } from '../../../mixins/form-control';
11
+ import { formControlMixin } from '../../../mixins/form-control';
15
12
 
16
13
  export default {
17
- mixins: [formControlMixin, formControlStyleMixin],
14
+ mixins: [formControlMixin],
18
15
 
19
16
  data() {
20
17
  return {
@@ -1,7 +1,14 @@
1
1
  <template>
2
2
  <img
3
3
  :src="srcComputed"
4
- :class="{ 'animate-pulse': !isLoaded }"
4
+ :class="[
5
+ headless ? null : isLoaded ? null : 'animate-pulse',
6
+ headless
7
+ ? null
8
+ : hasObjectFit
9
+ ? `h-full w-full ${objectFitComputed}`
10
+ : null,
11
+ ]"
5
12
  v-bind="$attrs"
6
13
  @load="onLoad"
7
14
  @error="onError"
@@ -15,18 +22,26 @@ export default {
15
22
  name: 'VTImage',
16
23
 
17
24
  props: {
18
- src: {
19
- type: String,
20
- default: '',
25
+ headless: {
26
+ type: Boolean,
27
+ default: false,
21
28
  },
22
29
  cdnSrc: {
23
30
  type: [String, Object],
24
31
  default: null,
25
32
  },
33
+ objectFit: {
34
+ type: String,
35
+ default: null,
36
+ },
26
37
  placeholder: {
27
38
  type: String,
28
39
  default: `data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22600%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20%25%7Bw%7D%20%25%7Bh%7D%22%20preserveAspectRatio%3D%22none%22%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20style%3D%22fill%3A%23bbb%3B%22%3E%3C%2Frect%3E%3C%2Fsvg%3E`,
29
40
  },
41
+ src: {
42
+ type: String,
43
+ default: '',
44
+ },
30
45
  },
31
46
 
32
47
  data() {
@@ -45,17 +60,33 @@ export default {
45
60
  return this.placeholder;
46
61
  }
47
62
 
48
- if (this.cdnSrc) {
49
- return this.handleImageResizing(this.cdnSrc, this.$attrs.width);
63
+ if (this.src) {
64
+ return this.src.includes('cloudfront.net/')
65
+ ? handleImageResizing(this.src, this.$attrs.width)
66
+ : this.src;
50
67
  }
51
68
 
52
- if (this.src) {
53
- return this.src;
69
+ if (this.cdnSrc) {
70
+ return handleImageResizing(this.cdnSrc, this.$attrs.width);
54
71
  }
55
72
  }
56
73
 
57
74
  return null;
58
75
  },
76
+
77
+ hasObjectFit() {
78
+ return this.objectFit;
79
+ },
80
+
81
+ objectFitComputed() {
82
+ return this.hasObjectFit
83
+ ? this.objectFit === 'cover'
84
+ ? 'object-cover'
85
+ : this.objectFit === 'contain'
86
+ ? 'object-contain'
87
+ : null
88
+ : null;
89
+ },
59
90
  },
60
91
 
61
92
  methods: {