@veritree/ui 0.27.0 → 0.28.0-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.
Files changed (116) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/index.js +105 -75
  3. package/mixins/floating-ui-content.js +17 -4
  4. package/mixins/floating-ui-item.js +31 -15
  5. package/mixins/floating-ui.js +142 -24
  6. package/mixins/form-control-icon.js +3 -3
  7. package/mixins/form-control.js +45 -20
  8. package/nuxt.js +38 -26
  9. package/package.json +17 -6
  10. package/src/components/Alert/VTAlert.vue +55 -14
  11. package/src/components/Avatar/VTAvatarImage.vue +6 -26
  12. package/src/components/Badge/VTBadge.vue +60 -0
  13. package/src/components/Badge/VTBadgeNew.vue +60 -0
  14. package/src/components/Breadcrumb/VTBreadcrumbItem.vue +11 -0
  15. package/src/components/Breadcrumb/VTBreadcrumbLink.vue +40 -0
  16. package/src/components/Breadcrumb/VTBreadcrumbList.vue +11 -0
  17. package/src/components/Breadcrumb/VTBreadcrumbRoot.vue +11 -0
  18. package/src/components/Breadcrumb/VTBreadcrumbSeparator.vue +19 -0
  19. package/src/components/Button/VTButton.vue +104 -56
  20. package/src/components/Carousel/VTCarousel.vue +69 -0
  21. package/src/components/Carousel/VTCarouselBackward.vue +36 -0
  22. package/src/components/Carousel/VTCarouselForward.vue +38 -0
  23. package/src/components/Carousel/VTCarouselTracker.vue +80 -0
  24. package/src/components/Checkbox/VTCheckbox.vue +134 -0
  25. package/src/components/Checkbox/VTCheckboxLabel.vue +3 -0
  26. package/src/components/Checkbox/VTCheckboxText.vue +20 -0
  27. package/src/components/Chip/VTChip.vue +29 -0
  28. package/src/components/Dialog/VTDialog.vue +59 -25
  29. package/src/components/Dialog/VTDialogClose.vue +3 -2
  30. package/src/components/Dialog/VTDialogContent.vue +29 -7
  31. package/src/components/Dialog/VTDialogFooter.vue +17 -2
  32. package/src/components/Dialog/VTDialogHeader.vue +2 -1
  33. package/src/components/Dialog/VTDialogMain.vue +5 -1
  34. package/src/components/Dialog/VTDialogOverlay.vue +5 -1
  35. package/src/components/Dialog/VTDialogTitle.vue +1 -1
  36. package/src/components/Disclosure/VTDisclosure.vue +2 -11
  37. package/src/components/Disclosure/VTDisclosureContent.vue +26 -52
  38. package/src/components/Disclosure/VTDisclosureDetails.vue +27 -2
  39. package/src/components/Disclosure/VTDisclosureHeader.vue +56 -89
  40. package/src/components/Disclosure/VTDisclosureIcon.vue +42 -31
  41. package/src/components/Divider/VTDivider.vue +9 -0
  42. package/src/components/Drawer/VTDrawer.vue +6 -15
  43. package/src/components/Drawer/VTDrawerClose.vue +5 -5
  44. package/src/components/Drawer/VTDrawerContent.vue +10 -10
  45. package/src/components/Drawer/VTDrawerFooter.vue +4 -4
  46. package/src/components/Drawer/VTDrawerHeader.vue +4 -4
  47. package/src/components/Drawer/VTDrawerMain.vue +5 -5
  48. package/src/components/Drawer/VTDrawerOverlay.vue +6 -6
  49. package/src/components/Drawer/VTDrawerTitle.vue +5 -5
  50. package/src/components/DropdownMenu/VTDropdownMenu.vue +0 -6
  51. package/src/components/DropdownMenu/VTDropdownMenuContent.vue +10 -1
  52. package/src/components/DropdownMenu/VTDropdownMenuDivider.vue +7 -16
  53. package/src/components/DropdownMenu/VTDropdownMenuItem.vue +5 -1
  54. package/src/components/DropdownMenu/VTDropdownMenuLabel.vue +1 -10
  55. package/src/components/DropdownMenu/VTDropdownMenuTrigger.vue +2 -4
  56. package/src/components/Form/VTFieldset.vue +5 -0
  57. package/src/components/Form/VTForm.vue +11 -0
  58. package/src/components/Form/VTFormCol.vue +20 -0
  59. package/src/components/Form/VTFormFeedback.vue +7 -1
  60. package/src/components/Form/VTFormGroup.vue +5 -7
  61. package/src/components/Form/VTFormLabel.vue +22 -0
  62. package/src/components/Form/VTFormLabelHelper.vue +22 -0
  63. package/src/components/Form/VTFormRow.vue +5 -0
  64. package/src/components/Form/VTInput.vue +2 -5
  65. package/src/components/Form/VTInputDate.vue +602 -0
  66. package/src/components/Form/VTInputIcon.vue +3 -9
  67. package/src/components/Form/VTInputNumber.vue +198 -0
  68. package/src/components/Form/VTInputPassword.vue +14 -5
  69. package/src/components/Form/VTInputRange.vue +92 -0
  70. package/src/components/Form/VTLegend.vue +24 -0
  71. package/src/components/Form/VTTextarea.vue +2 -2
  72. package/src/components/Image/VTImage.vue +10 -10
  73. package/src/components/Listbox/VTListbox.vue +128 -9
  74. package/src/components/Listbox/VTListboxContent.vue +14 -1
  75. package/src/components/Listbox/VTListboxDivider.vue +21 -0
  76. package/src/components/Listbox/VTListboxGroup.vue +9 -0
  77. package/src/components/Listbox/VTListboxItem.vue +57 -15
  78. package/src/components/Listbox/VTListboxLabel.vue +5 -4
  79. package/src/components/Listbox/VTListboxList.vue +1 -6
  80. package/src/components/Listbox/VTListboxPlaceholder.vue +25 -0
  81. package/src/components/Listbox/VTListboxSearch.vue +12 -8
  82. package/src/components/Listbox/VTListboxTrigger.vue +87 -6
  83. package/src/components/Listbox/VTListboxTriggerHighlight.vue +204 -0
  84. package/src/components/Listbox/VTListboxViewport.vue +33 -0
  85. package/src/components/Popover/VTPopoverContent.vue +3 -3
  86. package/src/components/Popover/VTPopoverDivider.vue +1 -1
  87. package/src/components/Popover/VTPopoverItem.vue +6 -2
  88. package/src/components/ProgressBar/VTProgressBar.vue +35 -10
  89. package/src/components/ProgressBar/VTProgressBarIndicator.vue +53 -0
  90. package/src/components/ScrollShadows/VTScrollShadows.vue +76 -0
  91. package/src/components/Separator/VTSeparator.vue +13 -0
  92. package/src/components/Switch/VTSwitch.vue +61 -0
  93. package/src/components/Tabs/VTTab.vue +6 -5
  94. package/src/components/Tabs/VTTabGroup.vue +88 -9
  95. package/src/components/Tabs/VTTabPanel.vue +4 -5
  96. package/src/components/Toast/README.md +263 -0
  97. package/src/components/Toast/VTToast.vue +145 -0
  98. package/src/components/Toast/VTToastAction.vue +25 -0
  99. package/src/components/Toast/VTToastClose.vue +52 -0
  100. package/src/components/Toast/VTToastContent.vue +25 -0
  101. package/src/components/Toast/VTToastDescription.vue +36 -0
  102. package/src/components/Toast/VTToastIcon.vue +72 -0
  103. package/src/components/Toast/VTToastItem.vue +180 -0
  104. package/src/components/Toast/VTToastTitle.vue +34 -0
  105. package/src/components/Tooltip/VTTooltipTrigger.vue +3 -5
  106. package/src/components/Transitions/FadeInOut.vue +2 -2
  107. package/src/components/Utils/FloatingUi.vue +31 -13
  108. package/src/helpers/currency.js +21 -0
  109. package/src/utils/components.js +18 -0
  110. package/src/utils/images.js +31 -12
  111. package/src/components/Input/VTInput.vue +0 -82
  112. package/src/components/Input/VTInputDate.vue +0 -36
  113. package/src/components/Input/VTInputFile.vue +0 -60
  114. package/src/components/Input/VTInputUpload.vue +0 -54
  115. package/src/components/Modal/VTModal.vue +0 -69
  116. package/src/utils/genId.js +0 -13
@@ -1,31 +1,29 @@
1
1
  <template>
2
- <Portal>
2
+ <Teleport to="body">
3
3
  <div
4
- v-if="visible"
4
+ v-if="modelValue"
5
5
  :id="id"
6
- :class="[
6
+ :class="
7
7
  headless
8
8
  ? 'dialog'
9
- : 'fixed inset-0 z-50 grid grid-cols-1 grid-rows-1 p-4 md:p-8',
10
- ]"
9
+ : `fixed inset-0 ${zIndexClass} grid grid-cols-1 grid-rows-1 ${classes} ${additionalClass}`
10
+ "
11
11
  aria-modal="true"
12
+ v-bind="$attrs"
12
13
  @click="onClick"
13
14
  >
14
15
  <slot></slot>
15
16
  </div>
16
- </Portal>
17
+ </Teleport>
17
18
  </template>
18
19
 
19
20
  <script>
20
- import { Portal } from '@linusborg/vue-simple-portal';
21
21
  import { genId } from '../../utils/ids';
22
22
 
23
23
  export default {
24
24
  name: 'VTDialog',
25
25
 
26
- components: {
27
- Portal,
28
- },
26
+ inheritAttrs: false,
29
27
 
30
28
  provide() {
31
29
  return {
@@ -42,27 +40,22 @@ export default {
42
40
  this.overlay = overlay;
43
41
  };
44
42
 
45
- const hide = () => this.hide();
46
-
47
- const emit = () => this.emit();
48
-
49
43
  return {
50
44
  componentId,
51
- hide,
52
- emit,
45
+ hide: () => this.hide(),
46
+ emitHidden: () => this.emitHidden(),
47
+ emitShown: () => this.emitShown(),
53
48
  registerContent,
54
49
  registerOverlay,
50
+ full: this.full,
51
+ type: this.type,
55
52
  };
56
53
  },
57
54
  };
58
55
  },
59
56
 
60
- model: {
61
- prop: 'visible',
62
- },
63
-
64
57
  props: {
65
- visible: {
58
+ modelValue: {
66
59
  type: Boolean,
67
60
  default: false,
68
61
  },
@@ -70,6 +63,22 @@ export default {
70
63
  type: Boolean,
71
64
  default: false,
72
65
  },
66
+ type: {
67
+ type: String,
68
+ default: null, // null or static: when set to static, the dialog will not close when clicking outside it or on esc.
69
+ },
70
+ full: {
71
+ type: Boolean,
72
+ default: false,
73
+ },
74
+ zIndex: {
75
+ type: String,
76
+ default: 'highest',
77
+ },
78
+ additionalClass: {
79
+ type: String,
80
+ default: '',
81
+ },
73
82
  },
74
83
 
75
84
  data() {
@@ -85,6 +94,25 @@ export default {
85
94
  return `dialog-${this.componentId}`;
86
95
  },
87
96
 
97
+ zIndexClass() {
98
+ switch (this.zIndex) {
99
+ case 'highest':
100
+ return 'z-50';
101
+ case 'high':
102
+ return 'z-40';
103
+ case 'normal':
104
+ return 'z-30';
105
+ case 'low':
106
+ return 'z-20';
107
+ case 'lowest':
108
+ return 'z-10';
109
+ }
110
+ },
111
+
112
+ classes() {
113
+ return !this.full ? 'p-4 md:p-6' : '';
114
+ },
115
+
88
116
  hasContent() {
89
117
  return this.content !== null;
90
118
  },
@@ -95,7 +123,7 @@ export default {
95
123
  },
96
124
 
97
125
  watch: {
98
- visible(isVisible) {
126
+ modelValue(isVisible) {
99
127
  if (!isVisible) this.hide();
100
128
  },
101
129
  },
@@ -111,13 +139,19 @@ export default {
111
139
  if (this.hasContent) this.content.hide();
112
140
  },
113
141
 
114
- emit() {
142
+ emitHidden() {
115
143
  this.$nextTick(() => {
116
- this.$emit('input', false);
144
+ this.$emit('update:modelValue', false);
117
145
  this.$emit('hidden');
118
146
  });
119
147
  },
120
148
 
149
+ emitShown() {
150
+ this.$nextTick(() => {
151
+ this.$emit('shown');
152
+ });
153
+ },
154
+
121
155
  /**
122
156
  * Hides the dialog when clicking outside its content.
123
157
  *
@@ -125,7 +159,7 @@ export default {
125
159
  */
126
160
  onClick(ev) {
127
161
  if (!ev || ev.target.id !== this.overlay?.id) return;
128
- this.hide();
162
+ if (this.type !== 'static') this.hide();
129
163
  },
130
164
  },
131
165
  };
@@ -2,11 +2,11 @@
2
2
  <VTButton
3
3
  variant="icon"
4
4
  :id="id"
5
- :class="[headless ? 'dialog-close' : null]"
5
+ :class="[headless ? 'dialog-close' : 'self-start']"
6
6
  @click.prevent="hide"
7
7
  >
8
8
  <slot>
9
- <IconClose class="h-5 w-5" />
9
+ <IconClose class="h-4 w-4" />
10
10
  </slot>
11
11
  </VTButton>
12
12
  </template>
@@ -38,6 +38,7 @@ export default {
38
38
  methods: {
39
39
  hide() {
40
40
  this.apiDialog().hide();
41
+ this.$emit('click');
41
42
  },
42
43
  },
43
44
  };
@@ -1,23 +1,24 @@
1
1
  <template>
2
2
  <transition
3
3
  enter-active-class="duration-300 ease-out"
4
- enter-class="translate-y-[50px] opacity-0"
4
+ enter-from-class="translate-y-[50px] opacity-0"
5
5
  enter-to-class="translate-y-0 opacity-100"
6
6
  leave-active-class="duration-300 ease-out"
7
- leave-class="translate-y-0 opacity-100"
7
+ leave-from-class="translate-y-0 opacity-100"
8
8
  leave-to-class="translate-y-[50px] opacity-0"
9
+ @after-enter="showDialog"
9
10
  @after-leave="hideDialog"
10
11
  >
11
12
  <div
12
13
  v-show="visible"
13
14
  :id="id"
14
- :class="[
15
+ :class="
15
16
  headless
16
17
  ? 'dialog-content'
17
- : 'relative m-auto flex max-h-full max-w-full flex-col overflow-auto rounded bg-white p-6 focus:outline-none lg:p-8',
18
- ]"
18
+ : `relative m-auto flex flex-col overflow-auto rounded bg-white px-4 focus:outline-none md:px-6 ${classes}`
19
+ "
19
20
  tabindex="-1"
20
- @keydown.esc.stop="hide"
21
+ @keydown.esc.stop="onEsc"
21
22
  >
22
23
  <slot></slot>
23
24
  </div>
@@ -47,6 +48,18 @@ export default {
47
48
  id() {
48
49
  return `dialog-content-${this.apiDialog().componentId}`;
49
50
  },
51
+
52
+ classes() {
53
+ return this.full ? 'h-screen w-screen' : 'max-h-full max-w-full';
54
+ },
55
+
56
+ full() {
57
+ return this.apiDialog().full;
58
+ },
59
+
60
+ type() {
61
+ return this.apiDialog().type;
62
+ },
50
63
  },
51
64
 
52
65
  mounted() {
@@ -57,6 +70,11 @@ export default {
57
70
  },
58
71
 
59
72
  methods: {
73
+ onEsc() {
74
+ if (this.type === 'static') return;
75
+ this.hide();
76
+ },
77
+
60
78
  show() {
61
79
  this.visible = true;
62
80
  },
@@ -66,7 +84,11 @@ export default {
66
84
  },
67
85
 
68
86
  hideDialog() {
69
- this.apiDialog().emit();
87
+ this.apiDialog().emitHidden();
88
+ },
89
+
90
+ showDialog() {
91
+ this.apiDialog().emitShown();
70
92
  },
71
93
  },
72
94
  };
@@ -1,6 +1,13 @@
1
1
  <template>
2
- <component :is="as" :class="[headless ? 'dialog-footer' : 'w-full']">
3
- <slot></slot>
2
+ <component
3
+ :is="as"
4
+ :class="[
5
+ headless
6
+ ? 'dialog-footer'
7
+ : '-mx-4 flex items-center justify-between gap-x-3 p-4 md:-mx-6 md:px-6 md:py-5',
8
+ ]"
9
+ >
10
+ <slot :hide="hide"></slot>
4
11
  </component>
5
12
  </template>
6
13
 
@@ -8,6 +15,8 @@
8
15
  export default {
9
16
  name: 'VTDialogFooter',
10
17
 
18
+ inject: ['apiDialog'],
19
+
11
20
  props: {
12
21
  headless: {
13
22
  type: Boolean,
@@ -18,5 +27,11 @@ export default {
18
27
  default: 'footer',
19
28
  },
20
29
  },
30
+
31
+ methods: {
32
+ hide() {
33
+ this.apiDialog().hide();
34
+ },
35
+ },
21
36
  };
22
37
  </script>
@@ -5,8 +5,9 @@
5
5
  :class="[
6
6
  headless
7
7
  ? 'dialog-header'
8
- : 'mb-6 flex w-full items-center justify-between gap-x-3',
8
+ : '-mx-4 flex items-center justify-between gap-x-3 p-4 md:-mx-6 md:px-6 md:py-5',
9
9
  ]"
10
+ @click.stop
10
11
  >
11
12
  <slot></slot>
12
13
  </component>
@@ -2,7 +2,11 @@
2
2
  <component
3
3
  :is="as"
4
4
  :id="id"
5
- :class="[headless ? 'dialog-body' : 'h-full w-full flex-1 overflow-y-auto']"
5
+ :class="[
6
+ headless
7
+ ? 'dialog-body'
8
+ : '-mx-4 flex-1 overflow-y-auto p-4 md:-mx-6 md:px-6 md:py-5',
9
+ ]"
6
10
  >
7
11
  <slot></slot>
8
12
  </component>
@@ -3,7 +3,11 @@
3
3
  <div
4
4
  v-if="visible"
5
5
  :id="id"
6
- :class="[headless ? 'dialog-overlay' : 'bg-primary-200/80 fixed inset-0']"
6
+ :class="[
7
+ headless
8
+ ? 'dialog-overlay'
9
+ : 'bg-primary-200/80 fixed inset-0 backdrop-blur-[3px]',
10
+ ]"
7
11
  />
8
12
  </FadeInOut>
9
13
  </template>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <span
3
3
  :id="id"
4
- :class="[headless ? 'dialog-header' : 'text-2xl font-semibold']"
4
+ :class="[headless ? 'dialog-header' : 'text-xl font-semibold']"
5
5
  >
6
6
  <slot></slot
7
7
  ></span>
@@ -11,11 +11,8 @@ export default {
11
11
  provide() {
12
12
  return {
13
13
  apiDisclosure: () => {
14
- const details = this.details;
15
- const contents = this.contents;
16
14
  const accordion = this.accordion;
17
- const headers = this.headers;
18
- const icons = this.icons;
15
+ const details = this.details;
19
16
 
20
17
  const register = (objKey, item) => {
21
18
  if (!item) return;
@@ -28,11 +25,8 @@ export default {
28
25
  };
29
26
 
30
27
  return {
31
- details,
32
- contents,
33
- headers,
34
- icons,
35
28
  accordion,
29
+ details,
36
30
  register,
37
31
  unregister,
38
32
  };
@@ -50,9 +44,6 @@ export default {
50
44
  data() {
51
45
  return {
52
46
  details: [],
53
- contents: [],
54
- headers: [],
55
- icons: [],
56
47
  };
57
48
  },
58
49
  };
@@ -4,12 +4,19 @@
4
4
  :class="[
5
5
  headless
6
6
  ? 'details-content'
7
- : 'overflow-hidden transition-[height] duration-300 ease-linear',
8
- invisible ? 'absolute opacity-0' : 'h-[var(--height)]',
7
+ : 'grid transition-[grid-template-rows] duration-300 ease-linear',
8
+ headless
9
+ ? isVisible
10
+ ? 'details-content--expanded'
11
+ : null
12
+ : isVisible
13
+ ? 'grid-rows-[1fr]'
14
+ : 'grid-rows-[0fr]',
9
15
  ]"
10
- :style="`--height: ${height};`"
11
16
  >
12
- <slot></slot>
17
+ <div :class="[headless ? 'detail-content__overflow' : 'overflow-hidden']">
18
+ <slot></slot>
19
+ </div>
13
20
  </div>
14
21
  </template>
15
22
 
@@ -24,14 +31,15 @@ export default {
24
31
  type: Boolean,
25
32
  default: false,
26
33
  },
34
+ open: {
35
+ type: Boolean,
36
+ default: false,
37
+ },
27
38
  },
28
39
 
29
40
  data() {
30
41
  return {
31
42
  idGroup: this.apiDetails().idGroup,
32
- expanded: false,
33
- expandedHeight: null,
34
- invisible: false,
35
43
  };
36
44
  },
37
45
 
@@ -40,56 +48,22 @@ export default {
40
48
  return `disclosure-content-${this.idGroup}`;
41
49
  },
42
50
 
43
- height() {
44
- return this.expanded ? this.expandedHeight : 0;
51
+ isVisible() {
52
+ return this.apiDetails().isVisible();
45
53
  },
46
54
  },
47
55
 
48
- mounted() {
49
- this.handleVisibleHeight();
50
-
51
- const content = {
52
- id: this.id,
53
- idGroup: this.idGroup,
54
- collapse: this.collapse,
55
- expand: this.expand,
56
- isVisible: this.isVisible,
57
- };
58
-
59
- this.apiDisclosure().register('contents', content);
60
- },
61
-
62
- beforeDestroy() {
63
- this.apiDisclosure().unregister('contents', this.id);
64
- },
65
-
66
- methods: {
67
- handleVisibleHeight() {
68
- // make panel position absolute and opacity 0,
69
- // to have it fully opened but not visible
70
- this.invisible = true;
71
-
72
- setTimeout(() => {
73
- // get computed height now since its fully opened
74
- // this height will be used by a css custom property to enable the transition
75
- this.expandedHeight = window.getComputedStyle(this.$el).height;
76
-
77
- // make invisible false once the full height is set
78
- this.invisible = false;
79
- }, 500);
80
- },
81
-
82
- expand() {
83
- this.expanded = true;
84
- },
85
-
86
- collapse() {
87
- this.expanded = false;
56
+ watch: {
57
+ open(value) {
58
+ this.apiDetails().setVisible(value);
59
+ this.expand = value;
88
60
  },
61
+ },
89
62
 
90
- isVisible() {
91
- return this.expanded;
92
- },
63
+ mounted() {
64
+ if (this.open) {
65
+ this.apiDetails().setVisible(this.open);
66
+ }
93
67
  },
94
68
  };
95
69
  </script>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div
3
3
  :class="[
4
- headless ? 'disclosure-details' : 'group relative',
4
+ headless ? 'disclosure-details' : 'relative',
5
5
  headless ? (visible ? 'is-open' : null) : null,
6
6
  ]"
7
7
  >
@@ -26,6 +26,7 @@ export default {
26
26
  const idContent = `details-content-${idGroup}`;
27
27
 
28
28
  const isVisible = () => this.isVisible();
29
+ const setVisible = (visible) => this.setVisible(visible);
29
30
 
30
31
  return {
31
32
  idGroup,
@@ -33,6 +34,8 @@ export default {
33
34
  idIcon,
34
35
  idContent,
35
36
  isVisible,
37
+ setVisible,
38
+ visible: this.visible,
36
39
  };
37
40
  },
38
41
  };
@@ -52,6 +55,22 @@ export default {
52
55
  };
53
56
  },
54
57
 
58
+ watch: {
59
+ visible(value) {
60
+ if (value && this.apiDisclosure().accordion) {
61
+ this.apiDisclosure().details.forEach((detail) => {
62
+ if (detail.idGroup !== this.idGroup) {
63
+ detail.hide();
64
+ }
65
+
66
+ if (detail.idGroup === this.idGroup) {
67
+ detail.show();
68
+ }
69
+ });
70
+ }
71
+ },
72
+ },
73
+
55
74
  mounted() {
56
75
  const detail = {
57
76
  idGroup: this.idGroup,
@@ -69,16 +88,22 @@ export default {
69
88
 
70
89
  methods: {
71
90
  show() {
91
+ this.$emit('toggle', true);
72
92
  this.visible = true;
73
93
  },
74
94
 
75
95
  hide() {
96
+ this.$emit('toggle', false);
76
97
  this.visible = false;
77
98
  },
78
99
 
79
100
  isVisible() {
80
101
  return this.visible;
81
102
  },
103
+
104
+ setVisible(visible) {
105
+ this.visible = visible;
106
+ },
82
107
  },
83
108
  };
84
- </script>
109
+ </script>