@dolanske/vui 1.4.0 → 1.4.2

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 (214) hide show
  1. package/dist/components/Accordion/Accordion.vue.d.ts +48 -0
  2. package/dist/components/Accordion/AccordionGroup.vue.d.ts +21 -0
  3. package/dist/components/Alert/Alert.vue.d.ts +36 -0
  4. package/dist/components/Avatar/Avatar.vue.d.ts +25 -0
  5. package/dist/components/Badge/Badge.vue.d.ts +22 -0
  6. package/dist/components/Breadcrumbs/BreadcrumbItem.vue.d.ts +22 -0
  7. package/dist/components/Breadcrumbs/Breadcrumbs.vue.d.ts +18 -0
  8. package/dist/components/Button/Button.vue.d.ts +32 -0
  9. package/dist/components/ButtonGroup/ButtonGroup.vue.d.ts +22 -0
  10. package/dist/components/Calendar/Calendar.vue.d.ts +27 -0
  11. package/dist/components/Card/Card.vue.d.ts +26 -0
  12. package/dist/components/Checkbox/Checkbox.vue.d.ts +33 -0
  13. package/dist/components/CopyClipboard/CopyClipboard.vue.d.ts +46 -0
  14. package/dist/components/Divider/Divider.vue.d.ts +23 -0
  15. package/dist/components/Drawer/Drawer.vue.d.ts +53 -0
  16. package/dist/components/Dropdown/Dropdown.vue.d.ts +177 -0
  17. package/dist/components/Dropdown/DropdownItem.vue.d.ts +23 -0
  18. package/dist/components/Dropdown/DropdownTitle.vue.d.ts +21 -0
  19. package/dist/components/Flex/Flex.vue.d.ts +41 -0
  20. package/dist/components/Grid/Grid.vue.d.ts +35 -0
  21. package/dist/components/Input/Color.vue.d.ts +11 -0
  22. package/dist/components/Input/Counter.vue.d.ts +19 -0
  23. package/dist/components/Input/Dropzone.vue.d.ts +193 -0
  24. package/dist/components/Input/File.vue.d.ts +8 -0
  25. package/dist/components/Input/Input.vue.d.ts +56 -0
  26. package/dist/components/Input/Password.vue.d.ts +6 -0
  27. package/dist/components/Input/Textarea.vue.d.ts +31 -0
  28. package/dist/components/Kbd/Kbd.vue.d.ts +23 -0
  29. package/dist/components/Kbd/KbdGroup.vue.d.ts +19 -0
  30. package/dist/components/Modal/Confirm.vue.d.ts +43 -0
  31. package/dist/components/Modal/Modal.vue.d.ts +58 -0
  32. package/dist/components/OTP/OTP.vue.d.ts +44 -0
  33. package/dist/components/OTP/OTPItem.vue.d.ts +5 -0
  34. package/dist/components/Pagination/Pagination.vue.d.ts +46 -0
  35. package/dist/components/Pagination/pagination.d.ts +12 -0
  36. package/dist/components/Popout/Popout.vue.d.ts +36 -0
  37. package/dist/components/Progress/Progress.vue.d.ts +33 -0
  38. package/dist/components/Radio/Radio.vue.d.ts +29 -0
  39. package/dist/components/Radio/RadioGroup.vue.d.ts +27 -0
  40. package/dist/components/Select/Select.vue.d.ts +35 -0
  41. package/dist/components/Sheet/Sheet.vue.d.ts +47 -0
  42. package/dist/components/Sidebar/Sidebar.vue.d.ts +70 -0
  43. package/dist/components/Skeleton/Skeleton.vue.d.ts +8 -0
  44. package/dist/components/Spinner/Spinner.vue.d.ts +6 -0
  45. package/dist/components/Switch/Switch.vue.d.ts +28 -0
  46. package/dist/components/Table/Cell.vue.d.ts +22 -0
  47. package/dist/components/Table/Head.vue.d.ts +30 -0
  48. package/dist/components/Table/Root.vue.d.ts +41 -0
  49. package/dist/components/Table/SelectAll.vue.d.ts +2 -0
  50. package/dist/components/Table/SelectRow.vue.d.ts +6 -0
  51. package/dist/components/Table/index.d.ts +6 -0
  52. package/dist/components/Table/table.d.ts +68 -0
  53. package/dist/components/Tabs/Tab.vue.d.ts +22 -0
  54. package/dist/components/Tabs/Tabs.vue.d.ts +34 -0
  55. package/dist/components/Toast/Toasts.vue.d.ts +2 -0
  56. package/dist/components/Toast/toast.d.ts +287 -0
  57. package/dist/components/Tooltip/Tooltip.vue.d.ts +33 -0
  58. package/dist/fonts/GeistMono-Regular.ttf +0 -0
  59. package/dist/fonts/GeistMono-SemiBold.ttf +0 -0
  60. package/dist/fonts/Inter_18pt-Black.ttf +0 -0
  61. package/dist/fonts/Inter_18pt-Bold.ttf +0 -0
  62. package/dist/fonts/Inter_18pt-ExtraBold.ttf +0 -0
  63. package/dist/fonts/Inter_18pt-Light.ttf +0 -0
  64. package/dist/fonts/Inter_18pt-Medium.ttf +0 -0
  65. package/dist/fonts/Inter_18pt-Regular.ttf +0 -0
  66. package/dist/fonts/Inter_18pt-SemiBold.ttf +0 -0
  67. package/dist/index.d.ts +56 -0
  68. package/dist/internal/Backdrop/Backdrop.vue.d.ts +21 -0
  69. package/dist/shared/helpers.d.ts +34 -0
  70. package/dist/shared/slots.d.ts +20 -0
  71. package/dist/shared/theme.d.ts +3 -0
  72. package/dist/shared/types.d.ts +24 -0
  73. package/dist/vui.css +1 -0
  74. package/dist/vui.js +16215 -0
  75. package/package.json +1 -2
  76. package/src/App.vue +0 -103
  77. package/src/components/Accordion/Accordion.vue +0 -98
  78. package/src/components/Accordion/AccordionGroup.vue +0 -49
  79. package/src/components/Accordion/accordion.scss +0 -97
  80. package/src/components/Alert/Alert.vue +0 -59
  81. package/src/components/Alert/alert.scss +0 -162
  82. package/src/components/Avatar/Avatar.vue +0 -53
  83. package/src/components/Avatar/avatar.scss +0 -52
  84. package/src/components/Badge/Badge.vue +0 -21
  85. package/src/components/Badge/badge.scss +0 -210
  86. package/src/components/Breadcrumbs/BreadcrumbItem.vue +0 -26
  87. package/src/components/Breadcrumbs/Breadcrumbs.vue +0 -29
  88. package/src/components/Breadcrumbs/breadcrumbs.scss +0 -31
  89. package/src/components/Button/Button.vue +0 -86
  90. package/src/components/Button/button.scss +0 -292
  91. package/src/components/ButtonGroup/ButtonGroup.vue +0 -28
  92. package/src/components/ButtonGroup/button-group.scss +0 -51
  93. package/src/components/Calendar/Calendar.vue +0 -66
  94. package/src/components/Calendar/calendar.scss +0 -88
  95. package/src/components/Card/Card.vue +0 -48
  96. package/src/components/Card/card.scss +0 -55
  97. package/src/components/Checkbox/Checkbox.vue +0 -54
  98. package/src/components/Checkbox/checkbox.scss +0 -80
  99. package/src/components/CopyClipboard/CopyClipboard.vue +0 -98
  100. package/src/components/CopyClipboard/copy-clipboard.scss +0 -25
  101. package/src/components/Divider/Divider.vue +0 -38
  102. package/src/components/Divider/divider.scss +0 -37
  103. package/src/components/Drawer/Drawer.vue +0 -102
  104. package/src/components/Drawer/drawer.scss +0 -37
  105. package/src/components/Dropdown/Dropdown.vue +0 -120
  106. package/src/components/Dropdown/DropdownItem.vue +0 -33
  107. package/src/components/Dropdown/DropdownTitle.vue +0 -14
  108. package/src/components/Dropdown/dropdown-item.scss +0 -84
  109. package/src/components/Dropdown/dropdown.scss +0 -53
  110. package/src/components/Flex/Flex.vue +0 -113
  111. package/src/components/Grid/Grid.vue +0 -87
  112. package/src/components/Input/Color.vue +0 -26
  113. package/src/components/Input/Counter.vue +0 -66
  114. package/src/components/Input/Dropzone.vue +0 -65
  115. package/src/components/Input/File.vue +0 -15
  116. package/src/components/Input/Input.vue +0 -123
  117. package/src/components/Input/Password.vue +0 -35
  118. package/src/components/Input/Textarea.vue +0 -78
  119. package/src/components/Input/input.scss +0 -302
  120. package/src/components/Kbd/Kbd.vue +0 -48
  121. package/src/components/Kbd/KbdGroup.vue +0 -28
  122. package/src/components/Kbd/kbd.scss +0 -19
  123. package/src/components/Modal/Confirm.vue +0 -56
  124. package/src/components/Modal/Modal.vue +0 -103
  125. package/src/components/Modal/modal.scss +0 -54
  126. package/src/components/OTP/OTP.vue +0 -133
  127. package/src/components/OTP/OTPItem.vue +0 -37
  128. package/src/components/OTP/otp.scss +0 -84
  129. package/src/components/Pagination/Pagination.vue +0 -92
  130. package/src/components/Pagination/pagination.ts +0 -78
  131. package/src/components/Popout/Popout.vue +0 -73
  132. package/src/components/Popout/popout.scss +0 -16
  133. package/src/components/Progress/Progress.vue +0 -103
  134. package/src/components/Progress/progress.scss +0 -47
  135. package/src/components/Radio/Radio.vue +0 -38
  136. package/src/components/Radio/RadioGroup.vue +0 -34
  137. package/src/components/Radio/radio.scss +0 -78
  138. package/src/components/Select/Select.vue +0 -212
  139. package/src/components/Select/select.scss +0 -82
  140. package/src/components/Sheet/Sheet.vue +0 -106
  141. package/src/components/Sheet/sheet.scss +0 -71
  142. package/src/components/Sidebar/Sidebar.vue +0 -116
  143. package/src/components/Sidebar/sidebar.scss +0 -124
  144. package/src/components/Skeleton/Skeleton.vue +0 -43
  145. package/src/components/Skeleton/skeleton.scss +0 -14
  146. package/src/components/Spinner/Spinner.vue +0 -42
  147. package/src/components/Spinner/spinner.scss +0 -47
  148. package/src/components/Switch/Switch.vue +0 -31
  149. package/src/components/Switch/switch.scss +0 -93
  150. package/src/components/Table/Cell.vue +0 -23
  151. package/src/components/Table/Head.vue +0 -66
  152. package/src/components/Table/Root.vue +0 -66
  153. package/src/components/Table/SelectAll.vue +0 -23
  154. package/src/components/Table/SelectRow.vue +0 -30
  155. package/src/components/Table/index.ts +0 -7
  156. package/src/components/Table/table.scss +0 -155
  157. package/src/components/Table/table.ts +0 -248
  158. package/src/components/Tabs/Tab.vue +0 -25
  159. package/src/components/Tabs/Tabs.vue +0 -90
  160. package/src/components/Tabs/tabs.scss +0 -87
  161. package/src/components/Toast/Toasts.vue +0 -52
  162. package/src/components/Toast/toast.scss +0 -45
  163. package/src/components/Toast/toast.ts +0 -75
  164. package/src/components/Tooltip/Tooltip.vue +0 -78
  165. package/src/components/Tooltip/tooltip.scss +0 -5
  166. package/src/examples/ExampleAccordions.vue +0 -69
  167. package/src/examples/ExampleAlerts.vue +0 -78
  168. package/src/examples/ExampleAvatars.vue +0 -44
  169. package/src/examples/ExampleBadges.vue +0 -48
  170. package/src/examples/ExampleBreadcrumbs.vue +0 -46
  171. package/src/examples/ExampleButtons.vue +0 -148
  172. package/src/examples/ExampleCalendars.vue +0 -40
  173. package/src/examples/ExampleCards.vue +0 -94
  174. package/src/examples/ExampleCheckboxes.vue +0 -123
  175. package/src/examples/ExampleCopyClipboard.vue +0 -47
  176. package/src/examples/ExampleDividers.vue +0 -39
  177. package/src/examples/ExampleDrawers.vue +0 -67
  178. package/src/examples/ExampleDropdowns.vue +0 -114
  179. package/src/examples/ExampleFlexGrid.vue +0 -124
  180. package/src/examples/ExampleInputs.vue +0 -236
  181. package/src/examples/ExampleKBD.vue +0 -65
  182. package/src/examples/ExampleModals.vue +0 -143
  183. package/src/examples/ExamplePalette.vue +0 -165
  184. package/src/examples/ExamplePopouts.vue +0 -41
  185. package/src/examples/ExampleSheets.vue +0 -77
  186. package/src/examples/ExampleSidebars.vue +0 -276
  187. package/src/examples/ExampleSkeletons.vue +0 -26
  188. package/src/examples/ExampleSpinners.vue +0 -80
  189. package/src/examples/ExampleTables.vue +0 -359
  190. package/src/examples/ExampleTabs.vue +0 -142
  191. package/src/examples/ExampleToasts.vue +0 -96
  192. package/src/examples/ExampleTooltips.vue +0 -70
  193. package/src/examples/shared/ExampleColor.vue +0 -28
  194. package/src/index.ts +0 -116
  195. package/src/internal/Backdrop/Backdrop.vue +0 -22
  196. package/src/internal/Backdrop/backdrop.scss +0 -34
  197. package/src/main.ts +0 -5
  198. package/src/shared/helpers.ts +0 -124
  199. package/src/shared/slots.ts +0 -61
  200. package/src/shared/theme.ts +0 -22
  201. package/src/shared/types.ts +0 -29
  202. package/src/style/animation.scss +0 -50
  203. package/src/style/core.scss +0 -133
  204. package/src/style/fonts.scss +0 -73
  205. package/src/style/layout.scss +0 -179
  206. package/src/style/media-query.scss +0 -29
  207. package/src/style/reset.scss +0 -135
  208. package/src/style/text.scss +0 -137
  209. package/src/style/theme.scss +0 -195
  210. package/src/style/tooltip.scss +0 -146
  211. package/src/style/typography.scss +0 -435
  212. package/src/style/utils.scss +0 -36
  213. package/src/style.scss +0 -1
  214. package/src/vite-env.d.ts +0 -1
@@ -1,48 +0,0 @@
1
- <script setup lang='ts'>
2
- import { useMagicKeys, whenever } from '@vueuse/core'
3
- import { computed } from 'vue'
4
- import './kbd.scss'
5
-
6
- interface Props {
7
- /**
8
- * Specify the key or the combination of keys connected with "+". Make sure
9
- * there are no white spaces between letters.
10
- *
11
- * keys="Escape" keys="Ctrl+A"
12
- */
13
- keys: string
14
- /**
15
- * Display custom label instead of the automatically formatted keys.
16
- */
17
- label?: string
18
- /**
19
- * Show active state when this combination of keys is pressed.
20
- */
21
- highlight?: boolean
22
- }
23
-
24
- const props = defineProps<Props>()
25
- const emits = defineEmits<{
26
- trigger: []
27
- }>()
28
- const keyHandler = useMagicKeys()
29
-
30
- whenever(keyHandler[props.keys], () => {
31
- emits('trigger')
32
- })
33
-
34
- const isActive = computed(() => {
35
- if (!props.highlight)
36
- return false
37
-
38
- return props.keys.split('+').every((key) => {
39
- return keyHandler.current.has(key.toLowerCase())
40
- })
41
- })
42
- </script>
43
-
44
- <template>
45
- <kbd class="vui-kbd" :class="{ active: isActive }">
46
- {{ props.label ?? props.keys.replaceAll("+", " + ") }}
47
- </kbd>
48
- </template>
@@ -1,28 +0,0 @@
1
- <script setup lang='ts'>
2
- import { useMagicKeys, whenever } from '@vueuse/core'
3
- import { enforceSlotType, useFlattenedSlot } from '../../shared/slots'
4
-
5
- /**
6
- * Can be used to wrap multiple <Kbd /> elements and triggers the callback when
7
- * all of them are active
8
- */
9
-
10
- const emits = defineEmits<{
11
- trigger: []
12
- }>()
13
-
14
- const slots = defineSlots()
15
- const keys = useMagicKeys()
16
-
17
- const flattened = useFlattenedSlot(slots.default)
18
- enforceSlotType(flattened, 'Kbd')
19
-
20
- whenever(
21
- keys[flattened.value.map(vnode => vnode.props.keys).join('+')],
22
- () => emits('trigger'),
23
- )
24
- </script>
25
-
26
- <template>
27
- <slot />
28
- </template>
@@ -1,19 +0,0 @@
1
- .vui-kbd {
2
- display: inline-flex;
3
- align-items: center;
4
- justify-content: center;
5
- height: 24px;
6
- border-radius: var(--border-radius-xs);
7
- font-size: var(--font-size-s);
8
- padding: 0 4px;
9
- transition: var(--transition-fast);
10
- font-weight: 600;
11
- background-color: var(--color-button-gray);
12
- color: var(--color-text-accent);
13
-
14
- &.active {
15
- transform: translateY(2px);
16
- color: var(--color-text-invert);
17
- background-color: var(--color-button-fill);
18
- }
19
- }
@@ -1,56 +0,0 @@
1
- <script setup lang='ts'>
2
- import type { Variants } from '../Button/Button.vue'
3
- import type { ModalProps } from './Modal.vue'
4
- import Button from '../Button/Button.vue'
5
- import Flex from '../Flex/Flex.vue'
6
- import Modal from './Modal.vue'
7
-
8
- type Props = {
9
- title?: string
10
- content?: string
11
- confirmText?: string
12
- confirmVariant?: Variants
13
- cancelText?: string
14
- showCancel?: boolean
15
- } & Partial<ModalProps>
16
-
17
- const props = withDefaults(defineProps<Props>(), {
18
- cancelText: 'Cancel',
19
- confirmText: 'Ok',
20
- size: 's',
21
- canDismiss: true,
22
- showCancel: true,
23
- confirmVariant: 'gray',
24
- open: false,
25
- })
26
-
27
- const emit = defineEmits<{
28
- cancel: []
29
- confirm: []
30
- close: []
31
- }>()
32
- </script>
33
-
34
- <template>
35
- <Modal
36
- v-bind="props"
37
- :open="props.open"
38
- @close="emit('close')"
39
- >
40
- <template #default>
41
- <div class="typeset">
42
- <slot />
43
- </div>
44
- </template>
45
- <template #footer>
46
- <Flex x-end>
47
- <Button v-if="props.showCancel" plain @click="emit('cancel'), emit('close')">
48
- {{ props.cancelText }}
49
- </Button>
50
- <Button :variant="props.confirmVariant" @click="emit('confirm'), emit('close')">
51
- {{ props.confirmText }}
52
- </Button>
53
- </Flex>
54
- </template>
55
- </Modal>
56
- </template>
@@ -1,103 +0,0 @@
1
- <script setup lang='ts'>
2
- import type { Sizes } from '../../shared/types'
3
- import type { Props as CardProps } from '../Card/Card.vue'
4
- import { useAttrs } from 'vue'
5
- import Backdrop from '../../internal/Backdrop/Backdrop.vue'
6
- import Button from '../Button/Button.vue'
7
- import Card from '../Card/Card.vue'
8
- import './modal.scss'
9
-
10
- export interface ModalProps {
11
- /**
12
- * Controls the visibility of the modal
13
- */
14
- open?: boolean
15
- /**
16
- * Controls the width of the modal
17
- */
18
- size?: Sizes | 'full' | 'screen'
19
- /**
20
- * Modal wraps a floating card. You can optinally pass in any props you'd pass
21
- * into the <Card /> component.
22
- */
23
- card?: CardProps
24
- /**
25
- * Modal will not overflow the screen, but its card's content will be scrollable instead.
26
- */
27
- scrollable?: boolean
28
- /**
29
- * Modal appears in the center of the screen
30
- */
31
- centered?: boolean
32
- /**
33
- * Wether modal can be closed by clicking the X button
34
- */
35
- canDismiss?: boolean
36
- }
37
-
38
- const {
39
- size = 'm',
40
- card = {},
41
- scrollable,
42
- centered,
43
- canDismiss = true,
44
- open = false,
45
- } = defineProps<ModalProps>()
46
-
47
- const emit = defineEmits<{ close: [] }>()
48
-
49
- const attrs = useAttrs()
50
-
51
- function tryClose() {
52
- if (canDismiss) {
53
- emit('close')
54
- }
55
- }
56
- </script>
57
-
58
- <template>
59
- <Teleport to="body">
60
- <Transition appear name="modal">
61
- <Backdrop v-if="open" :class="{ 'p-0': size === 'screen' }" @close="tryClose">
62
- <div class="vui-modal" :class="[`vui-modal-size-${size}`, { scrollable: scrollable || size === 'screen', centered }]" v-bind="attrs" @click.self="tryClose">
63
- <Card v-bind="card">
64
- <template v-if="$slots.header" #header>
65
- <slot name="header" :close="() => emit('close')" />
66
- </template>
67
- <template #header-end>
68
- <Button
69
- v-if="canDismiss"
70
- class="vui-modal-close"
71
- plain
72
- square
73
- icon="ph:x"
74
- @click="emit('close')"
75
- />
76
- </template>
77
- <template v-if="$slots.default" #default>
78
- <div>
79
- <slot name="default" :close="() => emit('close')" />
80
- </div>
81
- </template>
82
- <template v-if="$slots.footer" #footer>
83
- <slot name="footer" :close="() => emit('close')" />
84
- </template>
85
- </Card>
86
- </div>
87
- </Backdrop>
88
- </Transition>
89
- </Teleport>
90
- </template>
91
-
92
- <style scoped>
93
- .modal-enter-active,
94
- .modal-leave-active {
95
- transition: var(--transition);
96
- }
97
-
98
- .modal-enter-from,
99
- .modal-leave-to {
100
- opacity: 0;
101
- transform: scale(1.025);
102
- }
103
- </style>
@@ -1,54 +0,0 @@
1
- .vui-modal {
2
- width: 100%;
3
- margin-inline: auto;
4
- height: 100%;
5
- position: relative;
6
-
7
- &.centered {
8
- display: flex;
9
- align-items: center;
10
- }
11
-
12
- &.vui-modal-size-s {
13
- max-width: 440px;
14
- }
15
-
16
- &.vui-modal-size-m {
17
- max-width: 620px;
18
- }
19
-
20
- &.vui-modal-size-l {
21
- max-width: 728px;
22
- }
23
-
24
- &.vui-modal-size-screen {
25
- position: fixed;
26
- inset: 0;
27
-
28
- & > .vui-card {
29
- border-radius: 0;
30
- border: none;
31
- height: 100vh;
32
- }
33
- }
34
-
35
- &.scrollable {
36
- & > .vui-card {
37
- display: flex;
38
- flex-direction: column;
39
- inline-size: 100%;
40
- max-height: 100%;
41
-
42
- .vui-card-content {
43
- flex: 1 1 0%;
44
- overflow-y: auto;
45
- }
46
- }
47
- }
48
-
49
- & > .vui-card {
50
- width: 100%;
51
- margin-bottom: var(--backdrop-offset);
52
- box-shadow: var(--box-shadow-strong);
53
- }
54
- }
@@ -1,133 +0,0 @@
1
- <script setup lang='ts'>
2
- import type { ModelRef, Ref } from 'vue'
3
- import { computed, provide, ref, toRef, useTemplateRef, watch } from 'vue'
4
- import { setCharAt } from '../../shared/helpers'
5
- import './otp.scss'
6
-
7
- export interface OtpContext {
8
- otpValue: ModelRef<string>
9
- cursorIndex: Ref<number>
10
- redacted: Ref<boolean>
11
- register: () => void
12
- }
13
-
14
- interface Props {
15
- mode?: 'num' | 'char' | 'both'
16
- redacted?: boolean
17
- }
18
-
19
- const {
20
- mode = 'both',
21
- redacted = false,
22
- } = defineProps<Props>()
23
-
24
- const emits = defineEmits<{
25
- change: [value?: string]
26
- complete: [value: string]
27
- }>()
28
-
29
- const otpValue = defineModel<string>({
30
- default: '',
31
- })
32
-
33
- const cursorIndex = ref<number>(-1)
34
- const regexNumbers = '^\\d+$'
35
- const regexChars = '^[a-z]+$'
36
- const regexBoth = '^[a-z0-9]+$'
37
-
38
- const pattern = computed(() => {
39
- if (mode === 'num')
40
- return new RegExp(regexNumbers)
41
- else if (mode === 'char')
42
- return new RegExp(regexChars, 'i')
43
- else return new RegExp(regexBoth, 'i')
44
- })
45
-
46
- const maxLen = ref(0)
47
-
48
- const input = useTemplateRef('inputRef')
49
-
50
- provide('otp-context', {
51
- otpValue,
52
- cursorIndex,
53
- redacted: toRef(() => redacted),
54
- // Called by all OTPItem child components to properly set max length of the input.
55
- register: () => maxLen.value++,
56
- })
57
-
58
- watch(otpValue, value => emits('change', value))
59
-
60
- function setOtpValue(value: string) {
61
- otpValue.value = value
62
- if (input.value) {
63
- input.value.value = value
64
- }
65
- }
66
-
67
- function updateValue(e: KeyboardEvent) {
68
- const key = e.key
69
-
70
- // Capping at length 0 prevents all non-character keyboard inputs
71
- if (pattern.value.test(key) && key.length === 1) {
72
- const newValue = setCharAt(otpValue.value, key, cursorIndex.value)
73
-
74
- if (newValue.length <= maxLen.value) {
75
- setOtpValue(newValue)
76
-
77
- if (cursorIndex.value < maxLen.value - 1)
78
- cursorIndex.value++
79
- }
80
- }
81
- else if (key === 'ArrowLeft' && cursorIndex.value > 0) {
82
- cursorIndex.value--
83
- }
84
- else if (key === 'ArrowRight' && cursorIndex.value < otpValue.value.length) {
85
- cursorIndex.value++
86
- }
87
- else if (key === 'Backspace') {
88
- // If we press backspace multiple times make sure to traverse back by 1
89
- if (otpValue.value.charAt(cursorIndex.value) === '' && cursorIndex.value > 0) {
90
- cursorIndex.value--
91
- }
92
-
93
- const newValue = setCharAt(otpValue.value, '', cursorIndex.value)
94
- setOtpValue(newValue)
95
- }
96
- }
97
-
98
- function handlePaste(e: any) {
99
- const clipboard = e.clipboardData?.getData('text/plain')
100
- if (clipboard) {
101
- const clipboardTrim = clipboard.trim().slice(0, maxLen.value - cursorIndex.value)
102
-
103
- if (!pattern.value.test(clipboardTrim)) {
104
- return
105
- }
106
-
107
- const currentTrimStart = otpValue.value.slice(0, cursorIndex.value)
108
- const currentTrimEnd = otpValue.value.slice(cursorIndex.value + clipboardTrim.length)
109
- const newValue = (currentTrimStart + clipboardTrim + currentTrimEnd).trim()
110
- setOtpValue(newValue)
111
- cursorIndex.value = Math.min(newValue.length, maxLen.value - 1)
112
- }
113
- }
114
- </script>
115
-
116
- <template>
117
- <div class="vui-otp">
118
- <input
119
- ref="inputRef"
120
- type="text"
121
- class="vui-otp-input"
122
- contenteditable="true"
123
- @keydown="updateValue"
124
- @blur="cursorIndex = -1"
125
- @focus="cursorIndex = Math.min(otpValue.length, maxLen - 1)"
126
- @paste="handlePaste"
127
- >
128
-
129
- <div class="vui-otp-items">
130
- <slot />
131
- </div>
132
- </div>
133
- </template>
@@ -1,37 +0,0 @@
1
- <script setup lang='ts'>
2
- import type { OtpContext } from './OTP.vue'
3
- import { Icon } from '@iconify/vue'
4
- import { inject } from 'vue'
5
-
6
- interface Props {
7
- i: number
8
- }
9
-
10
- const props = defineProps<Props>()
11
-
12
- const {
13
- otpValue,
14
- cursorIndex,
15
- redacted,
16
- register,
17
- } = inject('otp-context') as OtpContext
18
-
19
- register()
20
- </script>
21
-
22
- <template>
23
- <div
24
- class="vui-otp-item" :class="{
25
- 'active': props.i === cursorIndex,
26
- 'has-value': otpValue.trim().at(props.i),
27
- }"
28
- >
29
- <div class="blinker" />
30
- <template v-if="otpValue.trim().at(props.i)">
31
- <Icon v-if="redacted" icon="ph:asterisk" />
32
- <template v-else>
33
- {{ otpValue.at(props.i) }}
34
- </template>
35
- </template>
36
- </div>
37
- </template>
@@ -1,84 +0,0 @@
1
- .vui-otp {
2
- display: inline-block;
3
- position: relative;
4
-
5
- .vui-otp-items {
6
- display: inline-flex;
7
- gap: 0;
8
-
9
- .vui-otp-item {
10
- display: flex;
11
- align-items: center;
12
- justify-content: center;
13
- width: var(--interactive-el-height);
14
- height: var(--interactive-el-height);
15
- border: 1px solid var(--color-border-strong);
16
- color: var(--color-text);
17
- z-index: var(--z-default);
18
- font-size: var(--font-size-m);
19
- outline: 0 solid var(--color-text-light);
20
- transition: var(--transition-fast);
21
-
22
- .blinker {
23
- display: block;
24
- height: 16px;
25
- width: 1px;
26
- background-color: var(--color-text);
27
- animation: blink 1s ease-out infinite;
28
- visibility: hidden;
29
- }
30
-
31
- @keyframes blink {
32
- 0%,
33
- 70%,
34
- 100% {
35
- opacity: 1;
36
- }
37
- 20%,
38
- 50% {
39
- opacity: 0;
40
- }
41
- }
42
-
43
- &.has-value {
44
- background-color: var(--color-bg-medium);
45
-
46
- .blinker {
47
- display: none !important;
48
- }
49
- }
50
-
51
- &.active {
52
- z-index: var(--z-active);
53
- outline-width: 2px;
54
-
55
- .blinker {
56
- visibility: visible;
57
- }
58
- }
59
-
60
- &:not(:first-child) {
61
- margin-left: -1px;
62
- }
63
-
64
- &:first-child {
65
- border-top-left-radius: var(--border-radius-m);
66
- border-bottom-left-radius: var(--border-radius-m);
67
- }
68
-
69
- &:last-child {
70
- border-top-right-radius: var(--border-radius-m);
71
- border-bottom-right-radius: var(--border-radius-m);
72
- }
73
- }
74
- }
75
-
76
- .vui-otp-input {
77
- position: absolute;
78
- inset: 0;
79
- outline-width: 0px;
80
- opacity: 0;
81
- background: transparent;
82
- z-index: var(--z-mask);
83
- }
84
- }
@@ -1,92 +0,0 @@
1
- <script setup lang='ts'>
2
- import type { Variants } from '../Button/Button.vue'
3
- import type { Pagination } from './pagination'
4
- import { computed } from 'vue'
5
- import Button from '../Button/Button.vue'
6
- import Flex from '../Flex/Flex.vue'
7
- import Tooltip from '../Tooltip/Tooltip.vue'
8
-
9
- interface Props {
10
- numbers?: boolean
11
- pagination: Pagination
12
- prevNext?: boolean
13
- firstLast?: boolean
14
- variant?: Variants
15
- }
16
-
17
- const props = withDefaults(defineProps<Props>(), {
18
- numbers: true,
19
- prevNext: true,
20
- firstLast: true,
21
- variant: 'gray',
22
- })
23
-
24
- const emit = defineEmits<{
25
- change: [page: number]
26
- }>()
27
-
28
- const canNextPage = computed(() => props.pagination.currentPage < props.pagination.endPage)
29
- const canPrevPage = computed(() => props.pagination.currentPage > props.pagination.startPage)
30
-
31
- function setNext() {
32
- emit('change', props.pagination.currentPage + 1)
33
- }
34
-
35
- function setPrev() {
36
- emit('change', props.pagination.currentPage - 1)
37
- }
38
- </script>
39
-
40
- <template>
41
- <Flex inline class="vui-pagination" gap="xxs">
42
- <slot name="start">
43
- <Tooltip v-if="props.firstLast">
44
- <Button plain :disabled="props.pagination.startPage === props.pagination.currentPage" square icon="ph:caret-double-left" @click="emit('change', props.pagination.startPage)" />
45
- <template #tooltip>
46
- <p>First page</p>
47
- </template>
48
- </Tooltip>
49
- </slot>
50
-
51
- <slot name="prev" :disabled="canPrevPage" :set-page="setPrev">
52
- <Tooltip v-if="props.prevNext">
53
- <Button plain :disabled="!canPrevPage" square icon="ph:caret-left" @click="setPrev" />
54
- <template #tooltip>
55
- <p>Previous page</p>
56
- </template>
57
- </Tooltip>
58
- </slot>
59
-
60
- <template v-if="props.numbers">
61
- <Flex gap="xxs">
62
- <Button
63
- v-for="page in props.pagination.pages"
64
- :key="page"
65
- square
66
- :plain="props.pagination.currentPage !== page"
67
- variant="gray"
68
- @click="emit('change', page)"
69
- >
70
- {{ page }}
71
- </Button>
72
- </Flex>
73
- </template>
74
- <slot name="next" :disabled="canNextPage" :set-page="setNext">
75
- <Tooltip v-if="props.prevNext">
76
- <Button plain :disabled="!canNextPage" square icon="ph:caret-right" @click="setNext" />
77
- <template #tooltip>
78
- <p>Next page</p>
79
- </template>
80
- </Tooltip>
81
- </slot>
82
-
83
- <slot name="end">
84
- <Tooltip v-if="props.firstLast">
85
- <Button plain :disabled="props.pagination.endPage === props.pagination.currentPage" square icon="ph:caret-double-right" @click="emit('change', props.pagination.endPage)" />
86
- <template #tooltip>
87
- <p>Last page</p>
88
- </template>
89
- </Tooltip>
90
- </slot>
91
- </Flex>
92
- </template>