@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,78 +1,78 @@
1
- import { createArray } from '../../shared/helpers'
2
-
3
- export interface Pagination {
4
- totalItems: number
5
- currentPage: number
6
- perPage: number
7
- totalPages: number
8
- startPage: number
9
- endPage: number
10
- startIndex: number
11
- endIndex: number
12
- pages: number[]
13
- }
14
-
15
- export function paginate(
16
- totalItems: number,
17
- currentPage: number = 1,
18
- perPage: number = 15,
19
- maxPages: number = 5,
20
- ): Pagination {
21
- // calculate total pages
22
- const totalPages = Math.ceil(totalItems / perPage)
23
-
24
- // ensure current page isn't out of range
25
- if (currentPage < 1) {
26
- currentPage = 1
27
- }
28
- else if (currentPage > totalPages) {
29
- currentPage = totalPages
30
- }
31
-
32
- let startPage: number, endPage: number
33
- if (totalPages <= maxPages) {
34
- // total pages less than max so show all pages
35
- startPage = 1
36
- endPage = totalPages
37
- }
38
- else {
39
- // total pages more than max so calculate start and end pages
40
- const maxPagesBeforeCurrentPage = Math.floor(maxPages / 2)
41
- const maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1
42
- if (currentPage <= maxPagesBeforeCurrentPage) {
43
- // current page near the start
44
- startPage = 1
45
- endPage = maxPages
46
- }
47
- else if (currentPage + maxPagesAfterCurrentPage >= totalPages) {
48
- // current page near the end
49
- startPage = totalPages - maxPages + 1
50
- endPage = totalPages
51
- }
52
- else {
53
- // current page somewhere in the middle
54
- startPage = currentPage - maxPagesBeforeCurrentPage
55
- endPage = currentPage + maxPagesAfterCurrentPage
56
- }
57
- }
58
-
59
- // calculate start and end item indexes
60
- const startIndex = (currentPage - 1) * perPage
61
- const endIndex = Math.min(startIndex + perPage - 1, totalItems - 1)
62
-
63
- // create an array of pages to ng-repeat in the pager control
64
- const pages = createArray((endPage + 1) - startPage).map(i => startPage + i)
65
-
66
- // return object with all pager properties required by the view
67
- return {
68
- totalItems,
69
- currentPage,
70
- perPage,
71
- totalPages,
72
- startPage,
73
- endPage,
74
- startIndex,
75
- endIndex,
76
- pages,
77
- }
78
- }
1
+ import { createArray } from '../../shared/helpers'
2
+
3
+ export interface Pagination {
4
+ totalItems: number
5
+ currentPage: number
6
+ perPage: number
7
+ totalPages: number
8
+ startPage: number
9
+ endPage: number
10
+ startIndex: number
11
+ endIndex: number
12
+ pages: number[]
13
+ }
14
+
15
+ export function paginate(
16
+ totalItems: number,
17
+ currentPage: number = 1,
18
+ perPage: number = 15,
19
+ maxPages: number = 5,
20
+ ): Pagination {
21
+ // calculate total pages
22
+ const totalPages = Math.ceil(totalItems / perPage)
23
+
24
+ // ensure current page isn't out of range
25
+ if (currentPage < 1) {
26
+ currentPage = 1
27
+ }
28
+ else if (currentPage > totalPages) {
29
+ currentPage = totalPages
30
+ }
31
+
32
+ let startPage: number, endPage: number
33
+ if (totalPages <= maxPages) {
34
+ // total pages less than max so show all pages
35
+ startPage = 1
36
+ endPage = totalPages
37
+ }
38
+ else {
39
+ // total pages more than max so calculate start and end pages
40
+ const maxPagesBeforeCurrentPage = Math.floor(maxPages / 2)
41
+ const maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1
42
+ if (currentPage <= maxPagesBeforeCurrentPage) {
43
+ // current page near the start
44
+ startPage = 1
45
+ endPage = maxPages
46
+ }
47
+ else if (currentPage + maxPagesAfterCurrentPage >= totalPages) {
48
+ // current page near the end
49
+ startPage = totalPages - maxPages + 1
50
+ endPage = totalPages
51
+ }
52
+ else {
53
+ // current page somewhere in the middle
54
+ startPage = currentPage - maxPagesBeforeCurrentPage
55
+ endPage = currentPage + maxPagesAfterCurrentPage
56
+ }
57
+ }
58
+
59
+ // calculate start and end item indexes
60
+ const startIndex = (currentPage - 1) * perPage
61
+ const endIndex = Math.min(startIndex + perPage - 1, totalItems - 1)
62
+
63
+ // create an array of pages to ng-repeat in the pager control
64
+ const pages = createArray((endPage + 1) - startPage).map(i => startPage + i)
65
+
66
+ // return object with all pager properties required by the view
67
+ return {
68
+ totalItems,
69
+ currentPage,
70
+ perPage,
71
+ totalPages,
72
+ startPage,
73
+ endPage,
74
+ startIndex,
75
+ endIndex,
76
+ pages,
77
+ }
78
+ }
@@ -1,52 +1,52 @@
1
- <script setup lang='ts'>
2
- import type { Placement, PopoutMaybeElement } from '../../shared/types'
3
- import { flip, offset, shift, useFloating } from '@floating-ui/vue'
4
- import { onClickOutside } from '@vueuse/core'
5
- import { toRef, useTemplateRef } from 'vue'
6
- import './popout.scss'
7
-
8
- export interface Props {
9
- /**
10
- * Reference to the HTML element the Popout is anchored to
11
- */
12
- anchor: PopoutMaybeElement<HTMLElement>
13
- /**
14
- * Override the autoPlacement option
15
- */
16
- placement?: Placement
17
- /**
18
- * Distance between the anchor and the rendered tooltip
19
- */
20
- offset?: number
21
- }
22
-
23
- const props = withDefaults(defineProps<Props>(), {
24
- offset: 8,
25
- })
26
-
27
- const emit = defineEmits<{
28
- clickOutside: []
29
- }>()
30
- const popoutRef = useTemplateRef('popout')
31
- const anchorRef = toRef(props.anchor)
32
-
33
- const { floatingStyles } = useFloating(anchorRef, popoutRef, {
34
- placement: props.placement,
35
- middleware: [
36
- // ...(props.placement
37
- // ? []
38
- // : [autoPlacement()]),
39
- shift({ padding: 8 }),
40
- flip(),
41
- offset(props.offset),
42
- ],
43
- })
44
-
45
- onClickOutside(popoutRef, () => emit('clickOutside'))
46
- </script>
47
-
48
- <template>
49
- <div ref="popout" :style="floatingStyles" class="vui-popout">
50
- <slot />
51
- </div>
52
- </template>
1
+ <script setup lang='ts'>
2
+ import type { Placement, PopoutMaybeElement } from '../../shared/types'
3
+ import { flip, offset, shift, useFloating } from '@floating-ui/vue'
4
+ import { onClickOutside } from '@vueuse/core'
5
+ import { toRef, useTemplateRef } from 'vue'
6
+ import './popout.scss'
7
+
8
+ export interface Props {
9
+ /**
10
+ * Reference to the HTML element the Popout is anchored to
11
+ */
12
+ anchor: PopoutMaybeElement<HTMLElement>
13
+ /**
14
+ * Override the autoPlacement option
15
+ */
16
+ placement?: Placement
17
+ /**
18
+ * Distance between the anchor and the rendered tooltip
19
+ */
20
+ offset?: number
21
+ }
22
+
23
+ const props = withDefaults(defineProps<Props>(), {
24
+ offset: 8,
25
+ })
26
+
27
+ const emit = defineEmits<{
28
+ clickOutside: []
29
+ }>()
30
+ const popoutRef = useTemplateRef('popout')
31
+ const anchorRef = toRef(props.anchor)
32
+
33
+ const { floatingStyles } = useFloating(anchorRef, popoutRef, {
34
+ placement: props.placement,
35
+ middleware: [
36
+ // ...(props.placement
37
+ // ? []
38
+ // : [autoPlacement()]),
39
+ shift({ padding: 8 }),
40
+ flip(),
41
+ offset(props.offset),
42
+ ],
43
+ })
44
+
45
+ onClickOutside(popoutRef, () => emit('clickOutside'))
46
+ </script>
47
+
48
+ <template>
49
+ <div ref="popout" :style="floatingStyles" class="vui-popout">
50
+ <slot />
51
+ </div>
52
+ </template>
@@ -1,15 +1,15 @@
1
- .vui-popout {
2
- border-radius: var(--border-radius);
3
- box-shadow: var(--box-shadow);
4
- min-width: 80px;
5
- background-color: var(--color-bg-medium);
6
- border-radius: var(--border-radius-m);
7
- z-index: 1000;
8
- }
9
-
10
- :root.light {
11
- .vui-popout {
12
- background-color: var(--color-bg);
13
- box-shadow: var(--box-shadow-strong);
14
- }
15
- }
1
+ .vui-popout {
2
+ border-radius: var(--border-radius);
3
+ box-shadow: var(--box-shadow);
4
+ min-width: 80px;
5
+ background-color: var(--color-bg-medium);
6
+ border-radius: var(--border-radius-m);
7
+ z-index: 1000;
8
+ }
9
+
10
+ :root.light {
11
+ .vui-popout {
12
+ background-color: var(--color-bg);
13
+ box-shadow: var(--box-shadow-strong);
14
+ }
15
+ }
@@ -1,103 +1,103 @@
1
- <script setup lang='ts'>
2
- import { whenever } from '@vueuse/core'
3
- import { computed, onMounted, useTemplateRef, watch, watchEffect } from 'vue'
4
- import { clamp, delay, formatUnitValue, isNil, randomMinMax } from '../../shared/helpers'
5
- import './progress.scss'
6
-
7
- interface Props {
8
- /**
9
- * Will randomly increment but never actually reach the end
10
- */
11
- fake?: boolean
12
- /**
13
- * Indicator color. Use CSS color values or variables
14
- */
15
- color?: string
16
- /**
17
- * Displays loader at the top of the page. It is only displayed when the
18
- * progress is between 0 and 100 (exclusive).
19
- */
20
- fixed?: boolean
21
- /**
22
- * Height
23
- */
24
- height?: number | string
25
- }
26
-
27
- const {
28
- fake,
29
- color = 'var(--color-accent)',
30
- fixed,
31
- height,
32
- } = defineProps<Props>()
33
-
34
- const emit = defineEmits<{
35
- done: []
36
- }>()
37
-
38
- const progressAmount = defineModel<number>({
39
- default: 0,
40
- set(value) {
41
- return clamp(0, 100, value)
42
- },
43
- })
44
-
45
- // Set height programatically
46
- const progressRef = useTemplateRef('progress')
47
-
48
- watchEffect(() => {
49
- if (progressRef.value && !isNil(height)) {
50
- progressRef.value.style.setProperty(
51
- '--vui-progress-height',
52
- formatUnitValue(height),
53
- )
54
- }
55
- })
56
-
57
- whenever(() => fake, fakeIncrement)
58
-
59
- // Automatically / randomly increment but never reach 100% until
60
- async function fakeIncrement() {
61
- if (fake && progressAmount.value < 100) {
62
- if (progressAmount.value > 90) {
63
- // Only in crement by the fraction of the remaining amount
64
- progressAmount.value += (100 - progressAmount.value) * 0.05
65
- await delay(randomMinMax(500, 3000))
66
- }
67
- else {
68
- progressAmount.value += randomMinMax(1, 10)
69
- await delay(randomMinMax(200, 12000))
70
- }
71
- fakeIncrement()
72
- }
73
- }
74
-
75
- watch(progressAmount, (v) => {
76
- if (v >= 100) {
77
- emit('done')
78
- }
79
- })
80
-
81
- onMounted(fakeIncrement)
82
-
83
- const w = computed(() => `${clamp(0, 100, progressAmount.value)}%`)
84
- const bC = computed(() => color)
85
- </script>
86
-
87
- <template>
88
- <div
89
- ref="progress"
90
- class="vui-progress"
91
- :class="{
92
- fixed,
93
- 'fixed-active': progressAmount > 0 && progressAmount < 100,
94
- }"
95
- >
96
- <div
97
- class="vui-progress-indicator" :style="{
98
- width: w,
99
- backgroundColor: bC,
100
- }"
101
- />
102
- </div>
103
- </template>
1
+ <script setup lang='ts'>
2
+ import { whenever } from '@vueuse/core'
3
+ import { computed, onMounted, useTemplateRef, watch, watchEffect } from 'vue'
4
+ import { clamp, delay, formatUnitValue, isNil, randomMinMax } from '../../shared/helpers'
5
+ import './progress.scss'
6
+
7
+ interface Props {
8
+ /**
9
+ * Will randomly increment but never actually reach the end
10
+ */
11
+ fake?: boolean
12
+ /**
13
+ * Indicator color. Use CSS color values or variables
14
+ */
15
+ color?: string
16
+ /**
17
+ * Displays loader at the top of the page. It is only displayed when the
18
+ * progress is between 0 and 100 (exclusive).
19
+ */
20
+ fixed?: boolean
21
+ /**
22
+ * Height
23
+ */
24
+ height?: number | string
25
+ }
26
+
27
+ const {
28
+ fake,
29
+ color = 'var(--color-accent)',
30
+ fixed,
31
+ height,
32
+ } = defineProps<Props>()
33
+
34
+ const emit = defineEmits<{
35
+ done: []
36
+ }>()
37
+
38
+ const progressAmount = defineModel<number>({
39
+ default: 0,
40
+ set(value) {
41
+ return clamp(0, 100, value)
42
+ },
43
+ })
44
+
45
+ // Set height programatically
46
+ const progressRef = useTemplateRef('progress')
47
+
48
+ watchEffect(() => {
49
+ if (progressRef.value && !isNil(height)) {
50
+ progressRef.value.style.setProperty(
51
+ '--vui-progress-height',
52
+ formatUnitValue(height),
53
+ )
54
+ }
55
+ })
56
+
57
+ whenever(() => fake, fakeIncrement)
58
+
59
+ // Automatically / randomly increment but never reach 100% until
60
+ async function fakeIncrement() {
61
+ if (fake && progressAmount.value < 100) {
62
+ if (progressAmount.value > 90) {
63
+ // Only in crement by the fraction of the remaining amount
64
+ progressAmount.value += (100 - progressAmount.value) * 0.05
65
+ await delay(randomMinMax(500, 3000))
66
+ }
67
+ else {
68
+ progressAmount.value += randomMinMax(1, 10)
69
+ await delay(randomMinMax(200, 12000))
70
+ }
71
+ fakeIncrement()
72
+ }
73
+ }
74
+
75
+ watch(progressAmount, (v) => {
76
+ if (v >= 100) {
77
+ emit('done')
78
+ }
79
+ })
80
+
81
+ onMounted(fakeIncrement)
82
+
83
+ const w = computed(() => `${clamp(0, 100, progressAmount.value)}%`)
84
+ const bC = computed(() => color)
85
+ </script>
86
+
87
+ <template>
88
+ <div
89
+ ref="progress"
90
+ class="vui-progress"
91
+ :class="{
92
+ fixed,
93
+ 'fixed-active': progressAmount > 0 && progressAmount < 100,
94
+ }"
95
+ >
96
+ <div
97
+ class="vui-progress-indicator" :style="{
98
+ width: w,
99
+ backgroundColor: bC,
100
+ }"
101
+ />
102
+ </div>
103
+ </template>
@@ -1,47 +1,47 @@
1
- .vui-progress {
2
- --vui-progress-height: 3px;
3
-
4
- display: block;
5
- width: 100%;
6
- position: relative;
7
- border-radius: 999px;
8
- background-color: var(--color-bg-raised);
9
- overflow: hidden;
10
- height: var(--vui-progress-height);
11
-
12
- &.fixed {
13
- transition: var(--transition-slow);
14
- transition-property: height;
15
- position: fixed;
16
- inset: 0;
17
- bottom: unset;
18
- height: 0;
19
- border-radius: none !important;
20
-
21
- &.fixed-active {
22
- height: var(--vui-progress-height);
23
- }
24
-
25
- .vui-progress-indicator {
26
- border-top-left-radius: unset !important;
27
- border-bottom-left-radius: unset !important;
28
- }
29
- }
30
-
31
- .vui-progress-indicator {
32
- position: absolute;
33
- z-index: 4;
34
- inset: 0;
35
- right: unset;
36
- width: 0;
37
- border-radius: 999px;
38
- background-color: var(--color-text-lighter);
39
- transition: var(--transition-slow);
40
- }
41
- }
42
-
43
- :root.light {
44
- .vui-progress-indicator {
45
- background-color: var(--);
46
- }
47
- }
1
+ .vui-progress {
2
+ --vui-progress-height: 3px;
3
+
4
+ display: block;
5
+ width: 100%;
6
+ position: relative;
7
+ border-radius: 999px;
8
+ background-color: var(--color-bg-raised);
9
+ overflow: hidden;
10
+ height: var(--vui-progress-height);
11
+
12
+ &.fixed {
13
+ transition: var(--transition-slow);
14
+ transition-property: height;
15
+ position: fixed;
16
+ inset: 0;
17
+ bottom: unset;
18
+ height: 0;
19
+ border-radius: none !important;
20
+
21
+ &.fixed-active {
22
+ height: var(--vui-progress-height);
23
+ }
24
+
25
+ .vui-progress-indicator {
26
+ border-top-left-radius: unset !important;
27
+ border-bottom-left-radius: unset !important;
28
+ }
29
+ }
30
+
31
+ .vui-progress-indicator {
32
+ position: absolute;
33
+ z-index: 4;
34
+ inset: 0;
35
+ right: unset;
36
+ width: 0;
37
+ border-radius: 999px;
38
+ background-color: var(--color-text-lighter);
39
+ transition: var(--transition-slow);
40
+ }
41
+ }
42
+
43
+ :root.light {
44
+ .vui-progress-indicator {
45
+ background-color: var(--);
46
+ }
47
+ }
@@ -1,38 +1,38 @@
1
- <script setup lang='ts'>
2
- import { Icon } from '@iconify/vue'
3
- import { computed, useId } from 'vue'
4
- import './radio.scss'
5
-
6
- export interface RadioProps {
7
- label?: string
8
- disabled?: boolean
9
- value: any
10
- accent?: boolean
11
- }
12
-
13
- const {
14
- label,
15
- disabled,
16
- value,
17
- accent,
18
- } = defineProps<RadioProps>()
19
- const slots = defineSlots()
20
- const checked = defineModel()
21
- const id = useId()
22
- const isChecked = computed(() => value === checked.value)
23
- </script>
24
-
25
- <template>
26
- <div class="vui-radio" :class="{ disabled: !!disabled, checked: isChecked, accent }">
27
- <input :id v-model="checked" type="radio" :value :checked="isChecked" :disabled>
28
- <label :for="id">
29
- <span class="vui-radio-icon">
30
- <Icon :icon="isChecked ? 'ph:radio-button-fill' : 'ph:circle'" />
31
- </span>
32
- <p v-if="!slots.default" class="vui-radio-content">{{ label || value }}</p>
33
- <div v-else class="vui-radio-content">
34
- <slot />
35
- </div>
36
- </label>
37
- </div>
38
- </template>
1
+ <script setup lang='ts'>
2
+ import { Icon } from '@iconify/vue'
3
+ import { computed, useId } from 'vue'
4
+ import './radio.scss'
5
+
6
+ export interface RadioProps {
7
+ label?: string
8
+ disabled?: boolean
9
+ value: any
10
+ accent?: boolean
11
+ }
12
+
13
+ const {
14
+ label,
15
+ disabled,
16
+ value,
17
+ accent,
18
+ } = defineProps<RadioProps>()
19
+ const slots = defineSlots()
20
+ const checked = defineModel()
21
+ const id = useId()
22
+ const isChecked = computed(() => value === checked.value)
23
+ </script>
24
+
25
+ <template>
26
+ <div class="vui-radio" :class="{ disabled: !!disabled, checked: isChecked, accent }">
27
+ <input :id v-model="checked" type="radio" :value :checked="isChecked" :disabled>
28
+ <label :for="id">
29
+ <span class="vui-radio-icon">
30
+ <Icon :icon="isChecked ? 'ph:radio-button-fill' : 'ph:circle'" />
31
+ </span>
32
+ <p v-if="!slots.default" class="vui-radio-content">{{ label || value }}</p>
33
+ <div v-else class="vui-radio-content">
34
+ <slot />
35
+ </div>
36
+ </label>
37
+ </div>
38
+ </template>