@dolanske/vui 0.1.0 → 0.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.
Files changed (161) hide show
  1. package/README.md +7 -0
  2. package/dist/components/Accordion/Accordion.vue.d.ts +45 -0
  3. package/dist/components/Accordion/AccordionGroup.vue.d.ts +32 -0
  4. package/dist/components/Alert/Alert.vue.d.ts +29 -0
  5. package/dist/components/Avatar/Avatar.vue.d.ts +9 -0
  6. package/dist/components/Badge/Badge.vue.d.ts +21 -0
  7. package/dist/components/Breadcrumbs/BreadcrumbItem.vue.d.ts +21 -0
  8. package/dist/components/Breadcrumbs/Breadcrumbs.vue.d.ts +27 -0
  9. package/dist/components/Button/Button.vue.d.ts +41 -0
  10. package/dist/components/ButtonGroup/ButtonGroup.vue.d.ts +19 -0
  11. package/dist/components/Calendar/Calendar.vue.d.ts +27 -0
  12. package/dist/components/Card/Card.vue.d.ts +25 -0
  13. package/dist/components/Checkbox/Checkbox.vue.d.ts +31 -0
  14. package/dist/components/CopyClipboard/CopyClipboard.vue.d.ts +40 -0
  15. package/dist/components/Divider/Divider.vue.d.ts +24 -0
  16. package/dist/components/Drawer/Drawer.vue.d.ts +52 -0
  17. package/dist/components/Dropdown/DropdownItem.vue.d.ts +21 -0
  18. package/dist/components/Dropdown/DropdownTitle.vue.d.ts +17 -0
  19. package/dist/components/Flex/Flex.vue.d.ts +38 -0
  20. package/dist/components/Grid/Grid.vue.d.ts +27 -0
  21. package/dist/components/Input/Counter.vue.d.ts +19 -0
  22. package/dist/components/Input/Dropzone.vue.d.ts +107 -0
  23. package/dist/components/Input/File.vue.d.ts +7 -0
  24. package/dist/components/Input/Input.vue.d.ts +54 -0
  25. package/dist/components/Input/Password.vue.d.ts +6 -0
  26. package/dist/components/Input/Textarea.vue.d.ts +30 -0
  27. package/dist/components/Kbd/Kbd.vue.d.ts +23 -0
  28. package/dist/components/Kbd/KbdGroup.vue.d.ts +31 -0
  29. package/dist/components/Modal/Confirm.vue.d.ts +45 -0
  30. package/dist/components/Modal/Modal.vue.d.ts +55 -0
  31. package/dist/components/Pagination/Pagination.vue.d.ts +42 -0
  32. package/dist/components/Pagination/pagination.d.ts +12 -0
  33. package/dist/components/Popout/Popout.vue.d.ts +34 -0
  34. package/dist/components/Progress/Progress.vue.d.ts +31 -0
  35. package/dist/components/Radio/Radio.vue.d.ts +27 -0
  36. package/dist/components/Radio/RadioGroup.vue.d.ts +40 -0
  37. package/dist/components/Select/Select.vue.d.ts +37 -0
  38. package/dist/components/Sheet/Sheet.vue.d.ts +35 -0
  39. package/dist/components/Skeleton/Skeleton.vue.d.ts +8 -0
  40. package/dist/components/Spinner/Spinner.vue.d.ts +6 -0
  41. package/dist/components/Switch/Switch.vue.d.ts +26 -0
  42. package/dist/components/Table/Cell.vue.d.ts +19 -0
  43. package/dist/components/Table/Header.vue.d.ts +29 -0
  44. package/dist/components/Table/Row.vue.d.ts +16 -0
  45. package/dist/components/Table/SelectAll.vue.d.ts +2 -0
  46. package/dist/components/Table/SelectRow.vue.d.ts +6 -0
  47. package/dist/components/Table/Table.vue.d.ts +40 -0
  48. package/dist/components/Table/table.d.ts +68 -0
  49. package/dist/components/Tabs/Tab.vue.d.ts +8 -0
  50. package/dist/components/Tabs/Tabs.vue.d.ts +43 -0
  51. package/dist/components/Toast/Toasts.vue.d.ts +2 -0
  52. package/dist/components/Toast/toast.d.ts +42 -0
  53. package/dist/components/Tooltip/Tooltip.vue.d.ts +32 -0
  54. package/dist/index.d.ts +54 -1
  55. package/dist/internal/Backdrop/Backdrop.vue.d.ts +20 -0
  56. package/dist/shared/composables.d.ts +3 -0
  57. package/dist/shared/helpers.d.ts +16 -0
  58. package/dist/shared/types.d.ts +10 -0
  59. package/dist/style.css +1 -1
  60. package/package.json +11 -9
  61. package/src/App.vue +158 -0
  62. package/src/components/Accordion/Accordion.vue +75 -0
  63. package/src/components/Accordion/AccordionGroup.vue +43 -0
  64. package/src/components/Accordion/accordion.scss +44 -0
  65. package/src/components/Alert/Alert.vue +53 -0
  66. package/src/components/Alert/alert.scss +80 -0
  67. package/src/components/Avatar/Avatar.vue +36 -0
  68. package/src/components/Avatar/avatar.scss +46 -0
  69. package/src/components/Badge/Badge.vue +21 -0
  70. package/src/components/Badge/badge.scss +89 -0
  71. package/src/components/Breadcrumbs/BreadcrumbItem.vue +26 -0
  72. package/src/components/Breadcrumbs/Breadcrumbs.vue +33 -0
  73. package/src/components/Breadcrumbs/breadcrumbs.scss +30 -0
  74. package/src/components/Button/Button.vue +90 -0
  75. package/src/components/Button/button.scss +176 -0
  76. package/src/components/ButtonGroup/ButtonGroup.vue +25 -0
  77. package/src/components/ButtonGroup/button-group.scss +51 -0
  78. package/src/components/Calendar/Calendar.vue +58 -0
  79. package/src/components/Calendar/calendar.scss +56 -0
  80. package/src/components/Card/Card.vue +48 -0
  81. package/src/components/Card/card.scss +53 -0
  82. package/src/components/Checkbox/Checkbox.vue +49 -0
  83. package/src/components/Checkbox/checkbox.scss +60 -0
  84. package/src/components/CopyClipboard/CopyClipboard.vue +82 -0
  85. package/src/components/CopyClipboard/copy-clipboard.scss +17 -0
  86. package/src/components/Divider/Divider.vue +34 -0
  87. package/src/components/Divider/divider.scss +35 -0
  88. package/src/components/Drawer/Drawer.vue +93 -0
  89. package/src/components/Drawer/drawer.scss +49 -0
  90. package/src/components/Dropdown/Dropdown.vue +100 -0
  91. package/src/components/Dropdown/DropdownItem.vue +29 -0
  92. package/src/components/Dropdown/DropdownTitle.vue +8 -0
  93. package/src/components/Dropdown/dropdown.scss +112 -0
  94. package/src/components/Flex/Flex.vue +109 -0
  95. package/src/components/Grid/Grid.vue +59 -0
  96. package/src/components/Input/Counter.vue +70 -0
  97. package/src/components/Input/Dropzone.vue +63 -0
  98. package/src/components/Input/File.vue +15 -0
  99. package/src/components/Input/Input.vue +118 -0
  100. package/src/components/Input/Password.vue +47 -0
  101. package/src/components/Input/Textarea.vue +73 -0
  102. package/src/components/Input/input.scss +199 -0
  103. package/src/components/Kbd/Kbd.vue +48 -0
  104. package/src/components/Kbd/KbdGroup.vue +31 -0
  105. package/src/components/Kbd/kbd.scss +18 -0
  106. package/src/components/Modal/Confirm.vue +56 -0
  107. package/src/components/Modal/Modal.vue +91 -0
  108. package/src/components/Modal/modal.scss +49 -0
  109. package/src/components/Pagination/Pagination.vue +74 -0
  110. package/src/components/Pagination/pagination.ts +78 -0
  111. package/src/components/Popout/Popout.vue +39 -0
  112. package/src/components/Popout/popout.scss +7 -0
  113. package/src/components/Progress/Progress.vue +84 -0
  114. package/src/components/Progress/progress.scss +41 -0
  115. package/src/components/Radio/Radio.vue +36 -0
  116. package/src/components/Radio/RadioGroup.vue +35 -0
  117. package/src/components/Radio/radio.scss +59 -0
  118. package/src/components/Select/Select.vue +180 -0
  119. package/src/components/Select/select.scss +43 -0
  120. package/src/components/Sheet/Sheet.vue +91 -0
  121. package/src/components/Sheet/sheet.scss +56 -0
  122. package/src/components/Skeleton/Skeleton.vue +46 -0
  123. package/src/components/Skeleton/skeleton.scss +14 -0
  124. package/src/components/Spinner/Spinner.vue +44 -0
  125. package/src/components/Spinner/spinner.scss +46 -0
  126. package/src/components/Switch/Switch.vue +30 -0
  127. package/src/components/Switch/switch.scss +52 -0
  128. package/src/components/Table/Cell.vue +23 -0
  129. package/src/components/Table/Header.vue +59 -0
  130. package/src/components/Table/Row.vue +9 -0
  131. package/src/components/Table/SelectAll.vue +23 -0
  132. package/src/components/Table/SelectRow.vue +29 -0
  133. package/src/components/Table/Table.vue +66 -0
  134. package/src/components/Table/table.scss +134 -0
  135. package/src/components/Table/table.ts +243 -0
  136. package/src/components/Tabs/Tab.vue +21 -0
  137. package/src/components/Tabs/Tabs.vue +76 -0
  138. package/src/components/Tabs/tabs.scss +78 -0
  139. package/src/components/Toast/Toasts.vue +47 -0
  140. package/src/components/Toast/toast.scss +41 -0
  141. package/src/components/Toast/toast.ts +92 -0
  142. package/src/components/Tooltip/Tooltip.vue +80 -0
  143. package/src/components/Tooltip/tooltip.scss +4 -0
  144. package/src/index.scss +1 -0
  145. package/src/index.ts +111 -0
  146. package/src/internal/Backdrop/Backdrop.vue +22 -0
  147. package/src/internal/Backdrop/backdrop.scss +28 -0
  148. package/src/main.ts +5 -0
  149. package/src/shared/composables.ts +18 -0
  150. package/src/shared/helpers.ts +53 -0
  151. package/src/shared/types.ts +11 -0
  152. package/src/style/animation.scss +21 -0
  153. package/src/style/core.scss +128 -0
  154. package/src/style/fonts.scss +0 -0
  155. package/src/style/layout.scss +9 -0
  156. package/src/style/media-query.scss +29 -0
  157. package/src/style/reset.scss +135 -0
  158. package/src/style/tooltip.scss +128 -0
  159. package/src/style/typography.scss +339 -0
  160. package/src/style/utils.scss +22 -0
  161. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,34 @@
1
+ <script setup lang="ts">
2
+ import './divider.scss'
3
+
4
+ interface Props {
5
+ thickness?: number
6
+ size?: number
7
+ vertical?: boolean
8
+ width?: number
9
+ height?: number
10
+ margin?: string
11
+ }
12
+
13
+ const {
14
+ thickness = 1,
15
+ size = 32,
16
+ vertical,
17
+ margin = '0',
18
+ } = defineProps<Props>()
19
+ </script>
20
+
21
+ <template>
22
+ <div
23
+ class="vui-divider" :class="{ vertical }" :style="{
24
+ ...(vertical && { width: `${size}px` }),
25
+ height: `${size}px`,
26
+ borderWidth: `${thickness}px`,
27
+ margin,
28
+ }"
29
+ >
30
+ <div v-if="$slots.default" class="vui-divider-slot">
31
+ <slot />
32
+ </div>
33
+ </div>
34
+ </template>
@@ -0,0 +1,35 @@
1
+ .vui-divider {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ position: relative;
6
+ height: 32px;
7
+ width: 100%;
8
+
9
+ &.vertical:before {
10
+ border-bottom: none;
11
+ border-right: 1px solid var(--color-border);
12
+ transform: translateX(-50%);
13
+ width: 1px;
14
+ height: 100%;
15
+ }
16
+
17
+ &:before {
18
+ content: '';
19
+ display: block;
20
+ transform: translateY(-50%);
21
+ width: 100%;
22
+ border-bottom: 1px solid var(--color-border);
23
+ }
24
+
25
+ .vui-divider-slot {
26
+ position: absolute;
27
+ top: 50%;
28
+ left: 50%;
29
+ transform: translate(-50%, -50%);
30
+
31
+ & > *:first-child {
32
+ outline: 3px solid var(--color-bg);
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,93 @@
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, 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
+ const open = defineModel<boolean>()
44
+
45
+ const containerMaxWidth = computed(() => {
46
+ if (typeof containerSize === 'string') {
47
+ if (containerClass === 'full') {
48
+ return '100%'
49
+ }
50
+ else {
51
+ return `var(--container-${containerSize})`
52
+ }
53
+ }
54
+ else {
55
+ return `${containerSize}px`
56
+ }
57
+ })
58
+
59
+ const id = useId()
60
+ </script>
61
+
62
+ <template>
63
+ <DrawerRoot
64
+ :open
65
+ should-scale-background
66
+ v-bind="rootProps"
67
+ @close="open = false"
68
+ @update:open="(state) => open = state"
69
+ >
70
+ <DrawerPortal v-bind="portalProps">
71
+ <DrawerOverlay class="vui-drawer-overlay" />
72
+ <DrawerContent class="vui-drawer-content" :class="{ 'hide-handlk': handle === false }" :aria-describedby="id">
73
+ <div
74
+ class="vui-drawer-container container" :class="containerClass" :style="{
75
+ maxWidth: containerMaxWidth,
76
+ }"
77
+ >
78
+ <DrawerTitle class="visually-hidden" :name="id">
79
+ {{ title }}
80
+ </DrawerTitle>
81
+ <slot />
82
+ </div>
83
+ </DrawerContent>
84
+ </DrawerPortal>
85
+ </DrawerRoot>
86
+ </template>
87
+
88
+ <style lang="scss" scoped>
89
+ :global(body) {
90
+ transition: var(--transition-quick);
91
+ background-color: var(--color-bg);
92
+ }
93
+ </style>
@@ -0,0 +1,49 @@
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
+
14
+ &.hide-handle:before {
15
+ display: none;
16
+ }
17
+
18
+ &.vaul-dragging {
19
+ &:before {
20
+ background-color: var(--color-text-lighter);
21
+ }
22
+ }
23
+
24
+ &:before {
25
+ content: '';
26
+ position: absolute;
27
+ left: 50%;
28
+ transform: translateX(-50%);
29
+ width: 56px;
30
+ height: 6px;
31
+ top: 12px;
32
+ border-radius: 3px;
33
+ background-color: var(--color-border-strong);
34
+ transition: var(--transition-quick);
35
+ }
36
+
37
+ // .vui-drawer-container {
38
+ // width: 100%;
39
+ // max-width: 756px;
40
+ // margin-inline: auto;
41
+ // }
42
+ }
43
+
44
+ .vui-drawer-overlay {
45
+ // opacity: 0.4;
46
+ // position: fixed;
47
+ // inset: 0;
48
+ // background-color: var(--color-bg-lowered);
49
+ }
@@ -0,0 +1,100 @@
1
+ <script setup lang='ts'>
2
+ import type { Placement } from '@floating-ui/vue'
3
+ import type { MaybeElement } from '@vueuse/core'
4
+ import { onClickOutside } from '@vueuse/core'
5
+ import { computed, ref, useTemplateRef } from 'vue'
6
+ import Popout from '../Popout/Popout.vue'
7
+ import './dropdown.scss'
8
+
9
+ interface Props {
10
+ /**
11
+ * Tooltip placement related to the anchor
12
+ */
13
+ placement?: Placement
14
+ /**
15
+ * Set the minimum width of the dropdown element
16
+ */
17
+ minWidth?: number | string
18
+ /**
19
+ * Sets the width of the dropdown to the width of its anchor
20
+ */
21
+ expand?: boolean
22
+ }
23
+
24
+ const {
25
+ placement = 'bottom-start',
26
+ expand,
27
+ minWidth,
28
+ } = defineProps<Props>()
29
+
30
+ const anchorRef = useTemplateRef<HTMLDivElement>('anchorRef')
31
+ const dropdownRef = useTemplateRef<MaybeElement>('dropdownRef')
32
+
33
+ const showMenu = ref(false)
34
+
35
+ function open() {
36
+ showMenu.value = true
37
+ }
38
+
39
+ function close() {
40
+ showMenu.value = false
41
+ }
42
+
43
+ function toggle() {
44
+ showMenu.value = !showMenu.value
45
+ }
46
+
47
+ onClickOutside(dropdownRef, (event) => {
48
+ // Hide dropdown when it is clicked outside EXCEPT when we click the trigger,
49
+ // as that is either by the slot itself
50
+ if (!anchorRef.value?.contains(event.target as Node | null))
51
+ showMenu.value = false
52
+ })
53
+
54
+ const anchorWidth = computed(() => {
55
+ if (!expand)
56
+ return 0
57
+ return anchorRef.value?.getBoundingClientRect().width
58
+ })
59
+
60
+ defineExpose({
61
+ open,
62
+ close,
63
+ toggle,
64
+ isOpen: showMenu,
65
+ })
66
+ </script>
67
+
68
+ <template>
69
+ <div ref="anchorRef" class="vui-dropdown-trigger-wrap">
70
+ <slot name="trigger" :open :is-open="showMenu" :close :toggle />
71
+ </div>
72
+
73
+ <Transition appear name="dropdown">
74
+ <Popout
75
+ v-if="showMenu"
76
+ ref="dropdownRef"
77
+ :anchor="anchorRef"
78
+ class="vui-dropdown"
79
+ :placement
80
+ :style="{
81
+ minWidth: `${minWidth ?? 156}px`,
82
+ ...(expand && { width: `${anchorWidth}px` }),
83
+ }"
84
+ >
85
+ <slot :open :close :toggle :is-open="showMenu" />
86
+ </Popout>
87
+ </Transition>
88
+ </template>
89
+
90
+ <style scoped>
91
+ .dropdown-enter-active,
92
+ .dropdown-leave-active {
93
+ transition: 0.1s opacity ease-in-out;
94
+ }
95
+
96
+ .dropdown-enter-from,
97
+ .dropdown-leave-to {
98
+ opacity: 0;
99
+ }
100
+ </style>
@@ -0,0 +1,29 @@
1
+ <script setup lang='ts'>
2
+ import { Icon } from '@iconify/vue'
3
+
4
+ interface Props {
5
+ disabled?: boolean
6
+ icon?: string
7
+ }
8
+
9
+ const props = defineProps<Props>()
10
+ </script>
11
+
12
+ <template>
13
+ <button class="vui-dropdown-item" :class="{ disabled }">
14
+ <!-- This should always be here to offset items which dont have icons -->
15
+ <div class="vui-dropdown-item-icon">
16
+ <Transition name="fade" appear>
17
+ <Icon v-if="props.icon" :icon="props.icon" />
18
+ </Transition>
19
+ </div>
20
+
21
+ <div class="vui-dropdown-item-slot">
22
+ <slot />
23
+ </div>
24
+
25
+ <div class="vui-dropdown-item-hint">
26
+ <slot name="hint" />
27
+ </div>
28
+ </button>
29
+ </template>
@@ -0,0 +1,8 @@
1
+ <template>
2
+ <div class="vui-dropdown-title">
3
+ <slot />
4
+ <div v-if="$slots.end" class="vui-dropdown-title-end">
5
+ <slot name="end" />
6
+ </div>
7
+ </div>
8
+ </template>
@@ -0,0 +1,112 @@
1
+ .vui-dropdown-trigger-wrap {
2
+ display: inline-block;
3
+ }
4
+
5
+ .vui-dropdown {
6
+ min-width: 156px;
7
+ border-radius: var(--border-radius-m);
8
+ border: 1px solid var(--color-border);
9
+ padding: 4px;
10
+ }
11
+
12
+ .vui-dropdown-item {
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: flex-start;
16
+ width: fit-content;
17
+ gap: var(--space-xs);
18
+ width: 100%;
19
+ height: 32px;
20
+ border-radius: var(--border-radius-m);
21
+ font-size: var(--font-size-s);
22
+ cursor: default;
23
+ transition: var(--transition);
24
+ padding-inline: var(--space-s);
25
+ white-space: nowrap;
26
+ margin-bottom: 4px;
27
+
28
+ &:last-child {
29
+ margin-bottom: 0;
30
+ }
31
+
32
+ &.disabled {
33
+ pointer-events: none;
34
+
35
+ &:hover {
36
+ background-color: transparent;
37
+ }
38
+
39
+ .vui-dropdown-item-slot,
40
+ .vui-dropdown-item-icon svg path {
41
+ color: var(--color-text-lighter);
42
+ }
43
+
44
+ .vui-dropdown-item-hint {
45
+ visibility: hidden;
46
+ opacity: 0;
47
+ z-index: -1;
48
+ }
49
+ }
50
+
51
+ .vui-dropdown-item-icon {
52
+ width: 16px;
53
+ height: 16px;
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: center;
57
+
58
+ svg {
59
+ width: 16px;
60
+ height: 16px;
61
+ }
62
+ }
63
+
64
+ .vui-dropdown-item-hint {
65
+ margin-left: 8px;
66
+ font-size: 0.9rem;
67
+ // white-space: nowrap;
68
+ color: var(--color-text-lighter);
69
+ }
70
+
71
+ .vui-dropdown-item-slot {
72
+ flex: 1;
73
+ display: flex;
74
+ align-items: center;
75
+ justify-content: flex-start;
76
+ color: var(--color-text);
77
+ flex-wrap: nowrap;
78
+ }
79
+
80
+ &.selected,
81
+ &:hover {
82
+ background-color: var(--color-button-gray-hover);
83
+ }
84
+ }
85
+
86
+ .vui-dropdown-title {
87
+ position: relative;
88
+ display: flex;
89
+ align-items: center;
90
+ justify-content: flex-start;
91
+ padding-block: var(--space-s);
92
+ padding-inline: calc(var(--space-s) + 4px);
93
+ font-size: var(--font-size-ms);
94
+ border-bottom: 1px solid var(--color-border);
95
+ font-weight: 500;
96
+ // margin-block: 4px;
97
+ margin-inline: -4px;
98
+ margin-top: -4px;
99
+ margin-bottom: 4px;
100
+ gap: var(--space-m);
101
+ justify-content: space-between;
102
+
103
+ &:not(:first-child) {
104
+ border-top: 1px solid var(--color-border);
105
+ }
106
+
107
+ .vui-dropdown-title-end {
108
+ font-size: var(--font-size-s);
109
+ font-weight: 400;
110
+ color: var(--color-text-lighter);
111
+ }
112
+ }
@@ -0,0 +1,109 @@
1
+ <script setup lang="ts">
2
+ import type { Sizes } from '../../shared/types'
3
+ import { computed } from 'vue'
4
+ import { useActualGap } from '../../shared/composables'
5
+
6
+ export interface FlexProps {
7
+ inline?: boolean
8
+ wrap?: boolean
9
+ wrapReverse?: boolean
10
+
11
+ row?: boolean
12
+ column?: boolean
13
+ rowReverse?: boolean
14
+ columnReverse?: boolean
15
+
16
+ gap?: Sizes | number
17
+
18
+ // NOTE: Add more if needed
19
+ justifyStart?: boolean
20
+ justifyEnd?: boolean
21
+ justifyCenter?: boolean
22
+ spaceBetween?: boolean
23
+ spaceAround?: boolean
24
+ spaceEvenly?: boolean
25
+
26
+ // NOTE: Add more if needed
27
+ alignCenter?: boolean
28
+ alignStart?: boolean
29
+ alignEnd?: boolean
30
+ alignBaseline?: boolean
31
+
32
+ expand?: boolean
33
+ }
34
+
35
+ const props = defineProps<FlexProps>()
36
+
37
+ // Flex gap
38
+ const ag = useActualGap(props.gap)
39
+
40
+ // Flex direction
41
+ const ad = computed(() => {
42
+ if (props.row)
43
+ return 'row'
44
+ else if (props.column)
45
+ return 'column'
46
+ else if (props.rowReverse)
47
+ return 'row-reverse'
48
+ else if (props.columnReverse)
49
+ return 'column-reverse'
50
+ else return 'row'
51
+ })
52
+
53
+ // Justify content
54
+ const aj = computed(() => {
55
+ if (props.justifyStart)
56
+ return 'flex-start'
57
+ else if (props.justifyEnd)
58
+ return 'flex-end'
59
+ else if (props.justifyCenter)
60
+ return 'center'
61
+ else if (props.spaceBetween)
62
+ return 'space-between'
63
+ else if (props.spaceEvenly)
64
+ return 'space-evenly'
65
+ else if (props.spaceAround)
66
+ return 'space-around'
67
+ else return 'flex-start'
68
+ })
69
+
70
+ // Align items
71
+ const aA = computed(() => {
72
+ if (props.alignStart)
73
+ return 'flex-start'
74
+ else if (props.alignEnd)
75
+ return 'flex-end'
76
+ else if (props.alignCenter)
77
+ return 'center'
78
+ else if (props.alignBaseline)
79
+ return 'baseline'
80
+ return 'flex-start'
81
+ })
82
+
83
+ const aY = computed(() => props.inline ? 'inline-flex' : 'flex')
84
+ const aW = computed(() => props.wrap
85
+ ? 'wrap'
86
+ : props.wrapReverse
87
+ ? 'wrap-reverse'
88
+ : 'nowrap')
89
+
90
+ const aH = computed(() => props.expand ? '100%' : 'auto')
91
+ </script>
92
+
93
+ <template>
94
+ <div class="vui-flex">
95
+ <slot />
96
+ </div>
97
+ </template>
98
+
99
+ <style scoped lang="scss">
100
+ .vui-flex {
101
+ display: v-bind(aY);
102
+ flex-wrap: v-bind(aW);
103
+ flex-direction: v-bind(ad);
104
+ justify-content: v-bind(aj);
105
+ gap: v-bind(ag);
106
+ align-items: v-bind(aA);
107
+ width: v-bind(aH);
108
+ }
109
+ </style>
@@ -0,0 +1,59 @@
1
+ <script setup lang="ts">
2
+ import type { Sizes } from '../../shared/types'
3
+ import { computed } from 'vue'
4
+ import { useActualGap } from '../../shared/composables'
5
+ import { createArray } from '../../shared/helpers'
6
+
7
+ /**
8
+ * This component is not meant for complex grids
9
+ */
10
+
11
+ interface Props {
12
+ inline?: boolean
13
+ gap?: Sizes | number
14
+ rows?: number | string
15
+ columns?: number | string
16
+ areas?: string[]
17
+ }
18
+
19
+ const props = defineProps<Props>()
20
+
21
+ const aG = useActualGap(props.gap)
22
+
23
+ const aTC = computed(() => {
24
+ if (typeof props.columns === 'number') {
25
+ return createArray(props.columns)
26
+ .map(() => '1fr')
27
+ .join(' ')
28
+ }
29
+ return props.columns ?? 'none'
30
+ })
31
+
32
+ const aTR = computed(() => {
33
+ if (typeof props.rows === 'number') {
34
+ return createArray(props.rows || 1)
35
+ .map(() => '')
36
+ .join('1fr')
37
+ }
38
+ return props.rows ?? 'none'
39
+ })
40
+
41
+ const aD = computed(() => props.inline ? 'inline-grid' : 'grid')
42
+ </script>
43
+
44
+ <template>
45
+ <div
46
+ class="vui-grid"
47
+ >
48
+ <slot />
49
+ </div>
50
+ </template>
51
+
52
+ <style scoped lang="scss">
53
+ .vui-grid {
54
+ display: v-bind(aD);
55
+ gap: v-bind(aG);
56
+ grid-template-columns: v-bind(aTC);
57
+ grid-template-rows: v-bind(aTR);
58
+ }
59
+ </style>
@@ -0,0 +1,70 @@
1
+ <script setup lang='ts'>
2
+ import type { InputProps } from './Input.vue'
3
+ import { Icon } from '@iconify/vue'
4
+ import Button from '../Button/Button.vue'
5
+ import Input from './Input.vue'
6
+
7
+ type Props = Omit<InputProps, 'type'> & {
8
+ incrementBy?: number
9
+ incrementEnabled?: boolean
10
+ hideIncrement?: boolean
11
+ decrementBy?: number
12
+ decrementEnabled?: boolean
13
+ hideDecrement?: boolean
14
+ }
15
+
16
+ const {
17
+ incrementBy = 1,
18
+ incrementEnabled = true,
19
+ hideIncrement = false,
20
+ decrementBy = 1,
21
+ decrementEnabled = true,
22
+ hideDecrement = false,
23
+ ...inputProps
24
+ } = defineProps<Props>()
25
+
26
+ const count = defineModel<number>({
27
+ default: 0,
28
+ })
29
+ </script>
30
+
31
+ <template>
32
+ <Input v-bind="inputProps" v-model.number="count" type="number">
33
+ <template v-if="!hideDecrement" #start>
34
+ <Button key="decrease" :disabled="!decrementEnabled" size="s" @click="count -= decrementBy">
35
+ <Icon icon="ph:minus" /> {{ decrementBy > 1 ? decrementBy : '' }}
36
+ </Button>
37
+ </template>
38
+
39
+ <template v-if="!hideIncrement" #end>
40
+ <Button key="increase" :disabled="!incrementEnabled" size="s" @click="count += incrementBy">
41
+ <Icon icon="ph:plus" /> {{ incrementBy > 1 ? incrementBy : '' }}
42
+ </Button>
43
+ </template>
44
+ </Input>
45
+ </template>
46
+
47
+ <style scoped lang="scss">
48
+ :deep(.vui-input-style) {
49
+ padding-inline: 4px !important;
50
+ gap: 8px !important;
51
+ }
52
+
53
+ :deep(.vui-button) {
54
+ padding-inline: 2px !important;
55
+ }
56
+
57
+ :deep(input) {
58
+ text-align: center;
59
+
60
+ ::-webkit-outer-spin-button,
61
+ ::-webkit-inner-spin-button {
62
+ -webkit-appearance: none;
63
+ margin: 0;
64
+ }
65
+
66
+ /* Firefox */
67
+ -moz-appearance: textfield;
68
+ appearance: textfield;
69
+ }
70
+ </style>