@dolanske/vui 1.0.4 → 1.1.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 (195) hide show
  1. package/LICENSE +673 -673
  2. package/README.md +42 -42
  3. package/dist/components/Accordion/Accordion.vue.d.ts +3 -2
  4. package/dist/components/Accordion/AccordionGroup.vue.d.ts +5 -2
  5. package/dist/components/Alert/Alert.vue.d.ts +3 -2
  6. package/dist/components/Avatar/Avatar.vue.d.ts +3 -2
  7. package/dist/components/Badge/Badge.vue.d.ts +3 -2
  8. package/dist/components/Breadcrumbs/BreadcrumbItem.vue.d.ts +3 -2
  9. package/dist/components/Breadcrumbs/Breadcrumbs.vue.d.ts +3 -2
  10. package/dist/components/Button/Button.vue.d.ts +3 -2
  11. package/dist/components/ButtonGroup/ButtonGroup.vue.d.ts +3 -2
  12. package/dist/components/Calendar/Calendar.vue.d.ts +6 -6
  13. package/dist/components/Card/Card.vue.d.ts +4 -3
  14. package/dist/components/Checkbox/Checkbox.vue.d.ts +7 -6
  15. package/dist/components/CopyClipboard/CopyClipboard.vue.d.ts +2 -1
  16. package/dist/components/Divider/Divider.vue.d.ts +3 -2
  17. package/dist/components/Drawer/Drawer.vue.d.ts +10 -9
  18. package/dist/components/Dropdown/Dropdown.vue.d.ts +66 -3
  19. package/dist/components/Dropdown/DropdownItem.vue.d.ts +3 -2
  20. package/dist/components/Dropdown/DropdownTitle.vue.d.ts +6 -6
  21. package/dist/components/Flex/Flex.vue.d.ts +13 -12
  22. package/dist/components/Grid/Grid.vue.d.ts +7 -6
  23. package/dist/components/Input/Color.vue.d.ts +5 -5
  24. package/dist/components/Input/Counter.vue.d.ts +5 -5
  25. package/dist/components/Input/Dropzone.vue.d.ts +95 -10
  26. package/dist/components/Input/File.vue.d.ts +4 -3
  27. package/dist/components/Input/Input.vue.d.ts +7 -6
  28. package/dist/components/Input/Password.vue.d.ts +1 -1
  29. package/dist/components/Input/Textarea.vue.d.ts +7 -6
  30. package/dist/components/Kbd/Kbd.vue.d.ts +1 -1
  31. package/dist/components/Kbd/KbdGroup.vue.d.ts +2 -1
  32. package/dist/components/Modal/Confirm.vue.d.ts +7 -9
  33. package/dist/components/Modal/Modal.vue.d.ts +16 -13
  34. package/dist/components/OTP/OTP.vue.d.ts +7 -6
  35. package/dist/components/OTP/OTPItem.vue.d.ts +1 -1
  36. package/dist/components/Pagination/Pagination.vue.d.ts +3 -2
  37. package/dist/components/Popout/Popout.vue.d.ts +3 -2
  38. package/dist/components/Progress/Progress.vue.d.ts +5 -5
  39. package/dist/components/Radio/Radio.vue.d.ts +7 -6
  40. package/dist/components/Radio/RadioGroup.vue.d.ts +7 -6
  41. package/dist/components/Select/Select.vue.d.ts +4 -8
  42. package/dist/components/Sheet/Sheet.vue.d.ts +22 -13
  43. package/dist/components/Sidebar/Sidebar.vue.d.ts +7 -6
  44. package/dist/components/Skeleton/Skeleton.vue.d.ts +1 -1
  45. package/dist/components/Spinner/Spinner.vue.d.ts +1 -1
  46. package/dist/components/Switch/Switch.vue.d.ts +7 -6
  47. package/dist/components/Table/Cell.vue.d.ts +5 -2
  48. package/dist/components/Table/Head.vue.d.ts +3 -2
  49. package/dist/components/Table/Root.vue.d.ts +3 -2
  50. package/dist/components/Table/table.d.ts +2 -2
  51. package/dist/components/Tabs/Tab.vue.d.ts +3 -2
  52. package/dist/components/Tabs/Tabs.vue.d.ts +7 -6
  53. package/dist/components/Toast/toast.d.ts +6 -6
  54. package/dist/components/Tooltip/Tooltip.vue.d.ts +2 -1
  55. package/dist/internal/Backdrop/Backdrop.vue.d.ts +3 -2
  56. package/dist/vui.css +1 -0
  57. package/dist/vui.js +8090 -7884
  58. package/package.json +73 -72
  59. package/src/App.vue +95 -95
  60. package/src/components/Accordion/Accordion.vue +91 -91
  61. package/src/components/Accordion/AccordionGroup.vue +43 -43
  62. package/src/components/Accordion/accordion.scss +82 -82
  63. package/src/components/Alert/Alert.vue +59 -59
  64. package/src/components/Alert/alert.scss +161 -161
  65. package/src/components/Avatar/Avatar.vue +53 -53
  66. package/src/components/Avatar/avatar.scss +52 -52
  67. package/src/components/Badge/Badge.vue +21 -21
  68. package/src/components/Badge/badge.scss +210 -206
  69. package/src/components/Breadcrumbs/BreadcrumbItem.vue +26 -26
  70. package/src/components/Breadcrumbs/Breadcrumbs.vue +30 -30
  71. package/src/components/Breadcrumbs/breadcrumbs.scss +31 -31
  72. package/src/components/Button/Button.vue +85 -85
  73. package/src/components/Button/button.scss +279 -279
  74. package/src/components/ButtonGroup/ButtonGroup.vue +28 -28
  75. package/src/components/ButtonGroup/button-group.scss +51 -51
  76. package/src/components/Calendar/Calendar.vue +66 -66
  77. package/src/components/Calendar/calendar.scss +83 -83
  78. package/src/components/Card/Card.vue +48 -48
  79. package/src/components/Card/card.scss +53 -53
  80. package/src/components/Checkbox/Checkbox.vue +54 -54
  81. package/src/components/Checkbox/checkbox.scss +80 -80
  82. package/src/components/CopyClipboard/CopyClipboard.vue +91 -91
  83. package/src/components/CopyClipboard/copy-clipboard.scss +25 -25
  84. package/src/components/Divider/Divider.vue +44 -44
  85. package/src/components/Divider/divider.scss +35 -35
  86. package/src/components/Drawer/Drawer.vue +102 -97
  87. package/src/components/Drawer/drawer.scss +37 -37
  88. package/src/components/Dropdown/Dropdown.vue +135 -135
  89. package/src/components/Dropdown/DropdownItem.vue +33 -33
  90. package/src/components/Dropdown/DropdownTitle.vue +14 -14
  91. package/src/components/Dropdown/dropdown-item.scss +84 -84
  92. package/src/components/Dropdown/dropdown.scss +53 -53
  93. package/src/components/Flex/Flex.vue +113 -113
  94. package/src/components/Grid/Grid.vue +79 -80
  95. package/src/components/Input/Color.vue +26 -26
  96. package/src/components/Input/Counter.vue +66 -66
  97. package/src/components/Input/Dropzone.vue +65 -65
  98. package/src/components/Input/File.vue +15 -15
  99. package/src/components/Input/Input.vue +123 -123
  100. package/src/components/Input/Password.vue +35 -35
  101. package/src/components/Input/Textarea.vue +78 -78
  102. package/src/components/Input/input.scss +302 -302
  103. package/src/components/Kbd/Kbd.vue +48 -48
  104. package/src/components/Kbd/KbdGroup.vue +27 -27
  105. package/src/components/Kbd/kbd.scss +19 -19
  106. package/src/components/Modal/Confirm.vue +56 -56
  107. package/src/components/Modal/Modal.vue +103 -99
  108. package/src/components/Modal/modal.scss +54 -54
  109. package/src/components/OTP/OTP.vue +133 -133
  110. package/src/components/OTP/OTPItem.vue +37 -37
  111. package/src/components/OTP/otp.scss +84 -84
  112. package/src/components/Pagination/Pagination.vue +77 -77
  113. package/src/components/Pagination/pagination.ts +78 -78
  114. package/src/components/Popout/Popout.vue +52 -52
  115. package/src/components/Popout/popout.scss +15 -15
  116. package/src/components/Progress/Progress.vue +103 -103
  117. package/src/components/Progress/progress.scss +47 -47
  118. package/src/components/Radio/Radio.vue +38 -38
  119. package/src/components/Radio/RadioGroup.vue +40 -40
  120. package/src/components/Radio/radio.scss +78 -78
  121. package/src/components/Select/Select.vue +211 -211
  122. package/src/components/Select/select.scss +77 -77
  123. package/src/components/Sheet/Sheet.vue +108 -98
  124. package/src/components/Sheet/sheet.scss +69 -69
  125. package/src/components/Sidebar/Sidebar.vue +115 -115
  126. package/src/components/Sidebar/sidebar.scss +124 -124
  127. package/src/components/Skeleton/Skeleton.vue +43 -43
  128. package/src/components/Skeleton/skeleton.scss +14 -14
  129. package/src/components/Spinner/Spinner.vue +42 -42
  130. package/src/components/Spinner/spinner.scss +47 -47
  131. package/src/components/Switch/Switch.vue +31 -31
  132. package/src/components/Switch/switch.scss +93 -93
  133. package/src/components/Table/Cell.vue +23 -23
  134. package/src/components/Table/Head.vue +59 -59
  135. package/src/components/Table/Root.vue +66 -66
  136. package/src/components/Table/SelectAll.vue +23 -23
  137. package/src/components/Table/SelectRow.vue +30 -30
  138. package/src/components/Table/index.ts +7 -7
  139. package/src/components/Table/table.scss +154 -154
  140. package/src/components/Table/table.ts +248 -248
  141. package/src/components/Tabs/Tab.vue +25 -25
  142. package/src/components/Tabs/Tabs.vue +90 -90
  143. package/src/components/Tabs/tabs.scss +87 -87
  144. package/src/components/Toast/Toasts.vue +52 -52
  145. package/src/components/Toast/toast.scss +45 -45
  146. package/src/components/Toast/toast.ts +75 -75
  147. package/src/components/Tooltip/Tooltip.vue +86 -86
  148. package/src/components/Tooltip/tooltip.scss +8 -8
  149. package/src/examples/ExampleAccordions.vue +58 -58
  150. package/src/examples/ExampleAlerts.vue +78 -78
  151. package/src/examples/ExampleAvatars.vue +44 -44
  152. package/src/examples/ExampleBadges.vue +48 -48
  153. package/src/examples/ExampleBreadcrumbs.vue +46 -46
  154. package/src/examples/ExampleButtons.vue +140 -140
  155. package/src/examples/ExampleCalendars.vue +40 -40
  156. package/src/examples/ExampleCards.vue +94 -94
  157. package/src/examples/ExampleCheckboxes.vue +123 -123
  158. package/src/examples/ExampleCopyClipboard.vue +47 -47
  159. package/src/examples/ExampleDividers.vue +39 -39
  160. package/src/examples/ExampleDrawers.vue +67 -67
  161. package/src/examples/ExampleDropdowns.vue +114 -114
  162. package/src/examples/ExampleFlexGrid.vue +124 -122
  163. package/src/examples/ExampleInputs.vue +234 -234
  164. package/src/examples/ExampleKBD.vue +65 -65
  165. package/src/examples/ExampleModals.vue +143 -143
  166. package/src/examples/ExamplePalette.vue +159 -159
  167. package/src/examples/ExamplePopouts.vue +41 -41
  168. package/src/examples/ExampleSheets.vue +77 -77
  169. package/src/examples/ExampleSidebars.vue +270 -270
  170. package/src/examples/ExampleSkeletons.vue +26 -26
  171. package/src/examples/ExampleSpinners.vue +80 -78
  172. package/src/examples/ExampleTables.vue +195 -195
  173. package/src/examples/ExampleTabs.vue +119 -119
  174. package/src/examples/ExampleToasts.vue +96 -96
  175. package/src/examples/ExampleTooltips.vue +70 -70
  176. package/src/examples/shared/ExampleColor.vue +28 -28
  177. package/src/index.ts +116 -116
  178. package/src/internal/Backdrop/Backdrop.vue +22 -22
  179. package/src/internal/Backdrop/backdrop.scss +34 -34
  180. package/src/main.ts +5 -5
  181. package/src/shared/helpers.ts +117 -117
  182. package/src/shared/theme.ts +22 -22
  183. package/src/shared/types.ts +29 -29
  184. package/src/style/animation.scss +22 -22
  185. package/src/style/core.scss +119 -125
  186. package/src/style/layout.scss +207 -233
  187. package/src/style/media-query.scss +29 -29
  188. package/src/style/reset.scss +135 -135
  189. package/src/style/text.scss +137 -124
  190. package/src/style/theme.scss +195 -195
  191. package/src/style/tooltip.scss +146 -146
  192. package/src/style/typography.scss +415 -415
  193. package/src/style/utils.scss +36 -36
  194. package/src/style.scss +1 -1
  195. package/dist/style.css +0 -1
@@ -1,97 +1,102 @@
1
- <script setup lang="ts">
2
- import type { DrawerPortalProps, DrawerRootProps } from 'vaul-vue'
3
- import type { Sizes, VueClass } from '../../shared/types'
4
- import { DrawerContent, DrawerOverlay, DrawerPortal, DrawerRoot, DrawerTitle } from 'vaul-vue'
5
- import { computed, onMounted, useId } from 'vue'
6
- import './drawer.scss'
7
-
8
- interface Props {
9
- /**
10
- * Title for accessibility.
11
- */
12
- title?: string
13
- /**
14
- * CSS class applied to the container of the drawer content. Accepts Vue's
15
- * class conditional declaration, string, object or an array.
16
- */
17
- containerClass?: VueClass
18
- /**
19
- * Size of the container. Either use a preset size or number to specify
20
- * max-width of the container.
21
- */
22
- containerSize?: Sizes | 'xl' | 'full' | number
23
- /**
24
- * Wether to display the handle symbol. It doesn't actually do anything, it's
25
- * just for the visuals.
26
- */
27
- handle?: boolean
28
- /**
29
- * Control the underlying Vaul root component
30
- */
31
- rootProps?: DrawerRootProps
32
- portalProps?: DrawerPortalProps
33
- }
34
-
35
- const {
36
- title,
37
- containerClass,
38
- containerSize = 'm',
39
- rootProps,
40
- portalProps,
41
- handle = true,
42
- } = defineProps<Props>()
43
-
44
- const open = defineModel<boolean>()
45
-
46
- const mW = computed(() => {
47
- if (typeof containerSize === 'string') {
48
- if (containerSize === 'full') {
49
- return '100%'
50
- }
51
- else {
52
- return getComputedStyle(document.documentElement)
53
- .getPropertyValue(`--container-${containerSize}`)
54
- }
55
- }
56
- else {
57
- return `${containerSize}px`
58
- }
59
- })
60
-
61
- const id = useId()
62
-
63
- onMounted(() => {
64
- if (!document.querySelector('[vaul-drawer-wrapper]')) {
65
- console.error('Your root component is missing \'vaul-drawer-wrapper\' attribute. \n Without it the <Drawer /> component will not be functional.')
66
- }
67
- })
68
- </script>
69
-
70
- <template>
71
- <DrawerRoot
72
- :open
73
- v-bind="rootProps"
74
- :aria-describedby="id"
75
- @close="open = false"
76
- @update:open="(state) => open = state"
77
- >
78
- <DrawerPortal v-bind="portalProps">
79
- <DrawerOverlay class="vui-drawer-overlay" />
80
- <DrawerContent class="vui-drawer-content" :class="{ 'hide-handle': handle === false }">
81
- <div :key="mW" class="vui-drawer-container container" :class="containerClass" :style="{ 'max-width': mW }">
82
- <DrawerTitle class="visually-hidden" :name="id">
83
- {{ title }}
84
- </DrawerTitle>
85
- <slot />
86
- </div>
87
- </DrawerContent>
88
- </DrawerPortal>
89
- </DrawerRoot>
90
- </template>
91
-
92
- <style lang="scss" scoped>
93
- :global(body) {
94
- transition: var(--transition-fast);
95
- background-color: var(--color-bg);
96
- }
97
- </style>
1
+ <script setup lang="ts">
2
+ import type { DrawerPortalProps, DrawerRootProps } from 'vaul-vue'
3
+ import type { Sizes, VueClass } from '../../shared/types'
4
+ import { DrawerContent, DrawerOverlay, DrawerPortal, DrawerRoot, DrawerTitle } from 'vaul-vue'
5
+ import { computed, onMounted, useId } from 'vue'
6
+ import './drawer.scss'
7
+
8
+ interface Props {
9
+ /**
10
+ * Controls the visibility of the drawer
11
+ */
12
+ open?: boolean
13
+ /**
14
+ * Title for accessibility.
15
+ */
16
+ title?: string
17
+ /**
18
+ * CSS class applied to the container of the drawer content. Accepts Vue's
19
+ * class conditional declaration, string, object or an array.
20
+ */
21
+ containerClass?: VueClass
22
+ /**
23
+ * Size of the container. Either use a preset size or number to specify
24
+ * max-width of the container.
25
+ */
26
+ containerSize?: Sizes | 'xl' | 'full' | number
27
+ /**
28
+ * Wether to display the handle symbol. It doesn't actually do anything, it's
29
+ * just for the visuals.
30
+ */
31
+ handle?: boolean
32
+ /**
33
+ * Control the underlying Vaul root component
34
+ */
35
+ rootProps?: DrawerRootProps
36
+ portalProps?: DrawerPortalProps
37
+ }
38
+
39
+ const {
40
+ title,
41
+ containerClass,
42
+ containerSize = 'm',
43
+ rootProps,
44
+ portalProps,
45
+ handle = true,
46
+ open = false,
47
+ } = defineProps<Props>()
48
+
49
+ const emit = defineEmits<{ close: [] }>()
50
+
51
+ const mW = computed(() => {
52
+ if (typeof containerSize === 'string') {
53
+ if (containerSize === 'full') {
54
+ return '100%'
55
+ }
56
+ else {
57
+ return getComputedStyle(document.documentElement)
58
+ .getPropertyValue(`--container-${containerSize}`)
59
+ }
60
+ }
61
+ else {
62
+ return `${containerSize}px`
63
+ }
64
+ })
65
+
66
+ const id = useId()
67
+
68
+ onMounted(() => {
69
+ if (!document.querySelector('[vaul-drawer-wrapper]')) {
70
+ console.error('Your root component is missing \'vaul-drawer-wrapper\' attribute. \n Without it the <Drawer /> component will not be functional.')
71
+ }
72
+ })
73
+ </script>
74
+
75
+ <template>
76
+ <DrawerRoot
77
+ :open
78
+ v-bind="rootProps"
79
+ :aria-describedby="id"
80
+ @close=" emit('close')"
81
+ @update:open="(state) => state === false && emit('close')"
82
+ >
83
+ <DrawerPortal v-bind="portalProps">
84
+ <DrawerOverlay class="vui-drawer-overlay" />
85
+ <DrawerContent class="vui-drawer-content" :class="{ 'hide-handle': handle === false }">
86
+ <div :key="mW" class="vui-drawer-container container" :class="containerClass" :style="{ 'max-width': mW }">
87
+ <DrawerTitle class="visually-hidden" :name="id">
88
+ {{ title }}
89
+ </DrawerTitle>
90
+ <slot />
91
+ </div>
92
+ </DrawerContent>
93
+ </DrawerPortal>
94
+ </DrawerRoot>
95
+ </template>
96
+
97
+ <style lang="scss" scoped>
98
+ :global(body) {
99
+ transition: var(--transition-fast);
100
+ background-color: var(--color-bg);
101
+ }
102
+ </style>
@@ -1,37 +1,37 @@
1
- .vui-drawer-content {
2
- background-color: var(--color-bg-raised);
3
- padding-inline: var(--space-l);
4
- border-top: 1px solid var(--color-border);
5
- border-top-left-radius: var(--border-radius-l);
6
- border-top-right-radius: var(--border-radius-l);
7
- padding-top: 30px;
8
- padding-bottom: 64px;
9
- position: fixed;
10
- bottom: 0;
11
- left: 0;
12
- right: 0;
13
- box-shadow: var(--box-shadow);
14
-
15
- &.hide-handle:before {
16
- display: none;
17
- }
18
-
19
- &.vaul-dragging {
20
- &:before {
21
- background-color: var(--color-text-lighter);
22
- }
23
- }
24
-
25
- &:before {
26
- content: '';
27
- position: absolute;
28
- left: 50%;
29
- transform: translateX(-50%);
30
- width: 56px;
31
- height: 6px;
32
- top: 12px;
33
- border-radius: 3px;
34
- background-color: var(--color-border-strong);
35
- transition: var(--transition-fast);
36
- }
37
- }
1
+ .vui-drawer-content {
2
+ background-color: var(--color-bg-raised);
3
+ padding-inline: var(--space-l);
4
+ border-top: 1px solid var(--color-border);
5
+ border-top-left-radius: var(--border-radius-l);
6
+ border-top-right-radius: var(--border-radius-l);
7
+ padding-top: 30px;
8
+ padding-bottom: 64px;
9
+ position: fixed;
10
+ bottom: 0;
11
+ left: 0;
12
+ right: 0;
13
+ box-shadow: var(--box-shadow);
14
+
15
+ &.hide-handle:before {
16
+ display: none;
17
+ }
18
+
19
+ &.vaul-dragging {
20
+ &:before {
21
+ background-color: var(--color-text-lighter);
22
+ }
23
+ }
24
+
25
+ &:before {
26
+ content: '';
27
+ position: absolute;
28
+ left: 50%;
29
+ transform: translateX(-50%);
30
+ width: 56px;
31
+ height: 6px;
32
+ top: 12px;
33
+ border-radius: 3px;
34
+ background-color: var(--color-border-strong);
35
+ transition: var(--transition-fast);
36
+ }
37
+ }
@@ -1,135 +1,135 @@
1
- <script setup lang='ts'>
2
- import type { MaybeElement } from '@vueuse/core'
3
- import type { Placement } from '../../shared/types'
4
- import { onClickOutside, useMagicKeys, whenever } from '@vueuse/core'
5
- import { computed, onMounted, ref, useTemplateRef, watch } from 'vue'
6
- import { formatUnitValue } from '../../shared/helpers'
7
- import Popout from '../Popout/Popout.vue'
8
- import './dropdown.scss'
9
-
10
- export interface Props {
11
- /**
12
- * Tooltip placement related to the anchor
13
- */
14
- placement?: Placement
15
- /**
16
- * Set the minimum width of the dropdown element
17
- */
18
- minWidth?: number | string
19
- /**
20
- * Sets the width of the dropdown to the width of its anchor
21
- */
22
- expand?: boolean
23
-
24
- /**
25
- * Set he max height of the dropdown element before it starts scrolling
26
- */
27
- maxHeight?: number | string
28
- }
29
-
30
- const {
31
- placement = 'bottom-start',
32
- maxHeight = 356,
33
- expand,
34
- minWidth = 156,
35
- } = defineProps<Props>()
36
-
37
- const emit = defineEmits<{
38
- close: []
39
- }>()
40
-
41
- const anchorRef = useTemplateRef<HTMLDivElement>('anchor')
42
- const dropdownRef = useTemplateRef<MaybeElement>('dropdown')
43
-
44
- const showMenu = ref(false)
45
-
46
- function open() {
47
- showMenu.value = true
48
- }
49
-
50
- function close() {
51
- showMenu.value = false
52
- }
53
-
54
- function toggle() {
55
- showMenu.value = !showMenu.value
56
- }
57
-
58
- onClickOutside(dropdownRef, (event) => {
59
- // Hide dropdown when it is clicked outside EXCEPT when we click the trigger,
60
- // as that is either by the slot itself
61
- if (!anchorRef.value?.contains(event.target as Node | null))
62
- showMenu.value = false
63
- })
64
-
65
- const anchorWidth = computed(() => {
66
- if (!expand || !window)
67
- return 0
68
- return anchorRef.value?.getBoundingClientRect().width
69
- })
70
-
71
- defineExpose({
72
- open,
73
- close,
74
- toggle,
75
- isOpen: showMenu,
76
- })
77
-
78
- const mW = computed(() => formatUnitValue(minWidth))
79
- const w = computed(() => expand ? `${anchorWidth.value}px` : 'initial')
80
-
81
- const { escape } = useMagicKeys()
82
- whenever(escape, close)
83
-
84
- watch(showMenu, (v) => {
85
- if (!v)
86
- emit('close')
87
- })
88
-
89
- onMounted(() => {
90
- if (expand && minWidth !== 156)
91
- console.warn('[Dropdown] Dropdown: minWidth prop is ignored when expand is set to true')
92
- })
93
- </script>
94
-
95
- <template>
96
- <div
97
- ref="anchor"
98
- class="vui-dropdown-trigger-wrap"
99
- role="button"
100
- :aria-expanded="showMenu"
101
- :aria-haspopup="true"
102
- name="Dropdown menu"
103
- >
104
- <slot name="trigger" :open :is-open="showMenu" :close :toggle />
105
- </div>
106
-
107
- <!-- <Transition name="dropdown" mode="out-in"> -->
108
- <Popout
109
- v-if="showMenu"
110
- ref="dropdown"
111
- :anchor="anchorRef"
112
- class="vui-dropdown"
113
- :placement
114
- :style="{
115
- minWidth: expand ? w : mW,
116
- width: w,
117
- maxHeight: formatUnitValue(maxHeight),
118
- }"
119
- >
120
- <slot :open :close :toggle :is-open="showMenu" />
121
- </Popout>
122
- <!-- </Transition> -->
123
- </template>
124
-
125
- <!-- <style scoped lang="scss">
126
- .dropdown-enter-active,
127
- .dropdown-leave-active {
128
- transition: var(--transition-fast);
129
- }
130
-
131
- .dropdown-enter-from,
132
- .dropdown-leave-to {
133
- opacity: 0;
134
- }
135
- </style> -->
1
+ <script setup lang='ts'>
2
+ import type { MaybeElement } from '@vueuse/core'
3
+ import type { Placement } from '../../shared/types'
4
+ import { onClickOutside, useMagicKeys, whenever } from '@vueuse/core'
5
+ import { computed, onMounted, ref, useTemplateRef, watch } from 'vue'
6
+ import { formatUnitValue } from '../../shared/helpers'
7
+ import Popout from '../Popout/Popout.vue'
8
+ import './dropdown.scss'
9
+
10
+ export interface Props {
11
+ /**
12
+ * Tooltip placement related to the anchor
13
+ */
14
+ placement?: Placement
15
+ /**
16
+ * Set the minimum width of the dropdown element
17
+ */
18
+ minWidth?: number | string
19
+ /**
20
+ * Sets the width of the dropdown to the width of its anchor
21
+ */
22
+ expand?: boolean
23
+
24
+ /**
25
+ * Set he max height of the dropdown element before it starts scrolling
26
+ */
27
+ maxHeight?: number | string
28
+ }
29
+
30
+ const {
31
+ placement = 'bottom-start',
32
+ maxHeight = 356,
33
+ expand,
34
+ minWidth = 156,
35
+ } = defineProps<Props>()
36
+
37
+ const emit = defineEmits<{
38
+ close: []
39
+ }>()
40
+
41
+ const anchorRef = useTemplateRef<HTMLDivElement>('anchor')
42
+ const dropdownRef = useTemplateRef<MaybeElement>('dropdown')
43
+
44
+ const showMenu = ref(false)
45
+
46
+ function open() {
47
+ showMenu.value = true
48
+ }
49
+
50
+ function close() {
51
+ showMenu.value = false
52
+ }
53
+
54
+ function toggle() {
55
+ showMenu.value = !showMenu.value
56
+ }
57
+
58
+ onClickOutside(dropdownRef, (event) => {
59
+ // Hide dropdown when it is clicked outside EXCEPT when we click the trigger,
60
+ // as that is either by the slot itself
61
+ if (!anchorRef.value?.contains(event.target as Node | null))
62
+ showMenu.value = false
63
+ })
64
+
65
+ const anchorWidth = computed(() => {
66
+ if (!expand || !window)
67
+ return 0
68
+ return anchorRef.value?.getBoundingClientRect().width
69
+ })
70
+
71
+ defineExpose({
72
+ open,
73
+ close,
74
+ toggle,
75
+ isOpen: showMenu,
76
+ })
77
+
78
+ const mW = computed(() => formatUnitValue(minWidth))
79
+ const w = computed(() => expand ? `${anchorWidth.value}px` : 'initial')
80
+
81
+ const { escape } = useMagicKeys()
82
+ whenever(escape, close)
83
+
84
+ watch(showMenu, (v) => {
85
+ if (!v)
86
+ emit('close')
87
+ })
88
+
89
+ onMounted(() => {
90
+ if (expand && minWidth !== 156)
91
+ console.warn('[Dropdown] Dropdown: minWidth prop is ignored when expand is set to true')
92
+ })
93
+ </script>
94
+
95
+ <template>
96
+ <div
97
+ ref="anchor"
98
+ class="vui-dropdown-trigger-wrap"
99
+ role="button"
100
+ :aria-expanded="showMenu"
101
+ :aria-haspopup="true"
102
+ name="Dropdown menu"
103
+ >
104
+ <slot name="trigger" :open :is-open="showMenu" :close :toggle />
105
+ </div>
106
+
107
+ <!-- <Transition name="dropdown" mode="out-in"> -->
108
+ <Popout
109
+ v-if="showMenu"
110
+ ref="dropdown"
111
+ :anchor="anchorRef"
112
+ class="vui-dropdown"
113
+ :placement
114
+ :style="{
115
+ minWidth: expand ? w : mW,
116
+ width: w,
117
+ maxHeight: formatUnitValue(maxHeight),
118
+ }"
119
+ >
120
+ <slot :open :close :toggle :is-open="showMenu" />
121
+ </Popout>
122
+ <!-- </Transition> -->
123
+ </template>
124
+
125
+ <!-- <style scoped lang="scss">
126
+ .dropdown-enter-active,
127
+ .dropdown-leave-active {
128
+ transition: var(--transition-fast);
129
+ }
130
+
131
+ .dropdown-enter-from,
132
+ .dropdown-leave-to {
133
+ opacity: 0;
134
+ }
135
+ </style> -->
@@ -1,33 +1,33 @@
1
- <script setup lang='ts'>
2
- import { Icon } from '@iconify/vue'
3
- import './dropdown-item.scss'
4
-
5
- interface Props {
6
- disabled?: boolean
7
- icon?: string
8
- iconEnd?: string
9
- }
10
-
11
- const props = defineProps<Props>()
12
- </script>
13
-
14
- <template>
15
- <button class="vui-dropdown-item" :class="{ disabled }" :disabled>
16
- <!-- This should always be here to offset items which dont have icons -->
17
- <div v-if="props.icon" class="vui-dropdown-item-icon">
18
- <Icon :icon="props.icon" />
19
- </div>
20
-
21
- <div class="vui-dropdown-item-slot">
22
- <slot />
23
- </div>
24
-
25
- <div v-if="$slots.hint" class="vui-dropdown-item-hint">
26
- <slot name="hint" />
27
- </div>
28
-
29
- <div v-if="props.iconEnd" class="vui-dropdown-item-icon">
30
- <Icon :icon="props.iconEnd" />
31
- </div>
32
- </button>
33
- </template>
1
+ <script setup lang='ts'>
2
+ import { Icon } from '@iconify/vue'
3
+ import './dropdown-item.scss'
4
+
5
+ interface Props {
6
+ disabled?: boolean
7
+ icon?: string
8
+ iconEnd?: string
9
+ }
10
+
11
+ const props = defineProps<Props>()
12
+ </script>
13
+
14
+ <template>
15
+ <button class="vui-dropdown-item" :class="{ disabled }" :disabled>
16
+ <!-- This should always be here to offset items which dont have icons -->
17
+ <div v-if="props.icon" class="vui-dropdown-item-icon">
18
+ <Icon :icon="props.icon" />
19
+ </div>
20
+
21
+ <div class="vui-dropdown-item-slot">
22
+ <slot />
23
+ </div>
24
+
25
+ <div v-if="$slots.hint" class="vui-dropdown-item-hint">
26
+ <slot name="hint" />
27
+ </div>
28
+
29
+ <div v-if="props.iconEnd" class="vui-dropdown-item-icon">
30
+ <Icon :icon="props.iconEnd" />
31
+ </div>
32
+ </button>
33
+ </template>
@@ -1,14 +1,14 @@
1
- <script lang="ts" setup>
2
- const { sticky } = defineProps<{
3
- sticky?: boolean
4
- }>()
5
- </script>
6
-
7
- <template>
8
- <div class="vui-dropdown-title" :class="{ sticky }">
9
- <slot />
10
- <div v-if="$slots.end" class="vui-dropdown-title-end">
11
- <slot name="end" />
12
- </div>
13
- </div>
14
- </template>
1
+ <script lang="ts" setup>
2
+ const { sticky } = defineProps<{
3
+ sticky?: boolean
4
+ }>()
5
+ </script>
6
+
7
+ <template>
8
+ <div class="vui-dropdown-title" :class="{ sticky }">
9
+ <slot />
10
+ <div v-if="$slots.end" class="vui-dropdown-title-end">
11
+ <slot name="end" />
12
+ </div>
13
+ </div>
14
+ </template>