@dolanske/vui 0.1.5 → 0.2.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 (48) hide show
  1. package/README.md +27 -99
  2. package/dist/components/Accordion/Accordion.vue.d.ts +1 -0
  3. package/dist/components/Avatar/Avatar.vue.d.ts +4 -2
  4. package/dist/components/Divider/Divider.vue.d.ts +2 -4
  5. package/dist/components/Dropdown/Dropdown.vue.d.ts +105 -0
  6. package/dist/components/Input/Dropzone.vue.d.ts +1 -0
  7. package/dist/components/Input/Input.vue.d.ts +1 -0
  8. package/dist/components/Popout/Popout.vue.d.ts +3 -3
  9. package/dist/components/Radio/Radio.vue.d.ts +1 -1
  10. package/dist/components/Radio/RadioGroup.vue.d.ts +3 -12
  11. package/dist/components/Tooltip/Tooltip.vue.d.ts +1 -1
  12. package/dist/shared/helpers.d.ts +6 -0
  13. package/dist/shared/types.d.ts +3 -0
  14. package/dist/style.css +1 -1
  15. package/dist/vui.js +3922 -3842
  16. package/package.json +1 -1
  17. package/src/App.vue +7 -19
  18. package/src/components/Accordion/Accordion.vue +8 -4
  19. package/src/components/Accordion/accordion.scss +38 -2
  20. package/src/components/Avatar/Avatar.vue +25 -4
  21. package/src/components/Avatar/avatar.scss +5 -5
  22. package/src/components/Button/Button.vue +4 -4
  23. package/src/components/Calendar/Calendar.vue +10 -8
  24. package/src/components/Card/Card.vue +2 -2
  25. package/src/components/Checkbox/Checkbox.vue +4 -1
  26. package/src/components/Checkbox/checkbox.scss +12 -6
  27. package/src/components/Divider/Divider.vue +22 -12
  28. package/src/components/Drawer/Drawer.vue +6 -8
  29. package/src/components/Drawer/drawer.scss +0 -13
  30. package/src/components/Dropdown/Dropdown.vue +13 -8
  31. package/src/components/Input/Input.vue +4 -1
  32. package/src/components/Input/Textarea.vue +11 -6
  33. package/src/components/Input/input.scss +13 -4
  34. package/src/components/Popout/Popout.vue +3 -3
  35. package/src/components/Progress/Progress.vue +19 -11
  36. package/src/components/Progress/progress.scss +1 -1
  37. package/src/components/Radio/Radio.vue +1 -1
  38. package/src/components/Radio/RadioGroup.vue +10 -5
  39. package/src/components/Sheet/Sheet.vue +16 -15
  40. package/src/components/Sheet/sheet.scss +4 -0
  41. package/src/components/Skeleton/Skeleton.vue +19 -20
  42. package/src/components/Spinner/Spinner.vue +5 -5
  43. package/src/components/Table/table.ts +2 -1
  44. package/src/components/Tooltip/Tooltip.vue +1 -1
  45. package/src/shared/helpers.ts +15 -0
  46. package/src/shared/types.ts +6 -0
  47. package/src/style/core.scss +4 -1
  48. package/src/style/layout.scss +4 -0
@@ -1,6 +1,6 @@
1
1
  <script setup lang='ts'>
2
- import { onMounted, useTemplateRef, watchEffect } from 'vue'
3
- import { delay, isNil, randomMinMax } from '../../shared/helpers'
2
+ import { computed, onMounted, useTemplateRef, watchEffect } from 'vue'
3
+ import { delay, formatUnitValue, isNil, randomMinMax } from '../../shared/helpers'
4
4
  import './progress.scss'
5
5
 
6
6
  interface Props {
@@ -42,16 +42,19 @@ const progressRef = useTemplateRef('progress')
42
42
 
43
43
  watchEffect(() => {
44
44
  if (progressRef.value && !isNil(height)) {
45
- progressRef.value.style.setProperty('--vui-progress-height', `${height}px`)
45
+ progressRef.value.style.setProperty(
46
+ '--vui-progress-height',
47
+ formatUnitValue(height),
48
+ )
46
49
  }
47
50
  })
48
51
 
49
52
  // Automatically / randomly increment but never reach 100% until
50
53
  async function fakeIncrement() {
51
54
  if (fake && progressAmount.value < 100) {
52
- if (progressAmount.value > 95) {
55
+ if (progressAmount.value > 90) {
53
56
  // Only in crement by the fraction of the remaining amount
54
- progressAmount.value += (100 - progressAmount.value) * 0.075
57
+ progressAmount.value += (100 - progressAmount.value) * 0.05
55
58
  await delay(randomMinMax(500, 3000))
56
59
  }
57
60
  else {
@@ -63,6 +66,9 @@ async function fakeIncrement() {
63
66
  }
64
67
 
65
68
  onMounted(fakeIncrement)
69
+
70
+ const w = computed(() => `${progressAmount.value}%`)
71
+ const bC = computed(() => color)
66
72
  </script>
67
73
 
68
74
  <template>
@@ -74,11 +80,13 @@ onMounted(fakeIncrement)
74
80
  'fixed-active': progressAmount > 0 && progressAmount < 100,
75
81
  }"
76
82
  >
77
- <div
78
- class="vui-progress-indicator" :style="{
79
- width: `${progressAmount}%`,
80
- backgroundColor: color,
81
- }"
82
- />
83
+ <div class="vui-progress-indicator" />
83
84
  </div>
84
85
  </template>
86
+
87
+ <style scoped lang="scss">
88
+ .vui-progress-indicator {
89
+ width: v-bind(w);
90
+ background-color: v-bind(bC);
91
+ }
92
+ </style>
@@ -1,5 +1,6 @@
1
1
  .vui-progress {
2
2
  --vui-progress-height: 3px;
3
+
3
4
  display: block;
4
5
  width: 100%;
5
6
  position: relative;
@@ -18,7 +19,6 @@
18
19
  border-radius: none !important;
19
20
 
20
21
  &.fixed-active {
21
- // Some arbitrary value which should never happen to people with
22
22
  height: var(--vui-progress-height);
23
23
  }
24
24
 
@@ -6,7 +6,7 @@ import './radio.scss'
6
6
  export interface RadioProps {
7
7
  label?: string
8
8
  disabled?: boolean
9
- value: string
9
+ value: any
10
10
  }
11
11
 
12
12
  const {
@@ -1,7 +1,7 @@
1
1
  <script setup lang='ts'>
2
- import type { VNode } from 'vue'
3
2
  import type { FlexProps } from '../Flex/Flex.vue'
4
- import type { RadioProps } from './Radio.vue'
3
+ import type Radio from './Radio.vue'
4
+ import { watchEffect } from 'vue'
5
5
  import Flex from '../Flex/Flex.vue'
6
6
 
7
7
  interface Props extends FlexProps {
@@ -14,22 +14,27 @@ const {
14
14
  } = defineProps<Props>()
15
15
 
16
16
  const slots = defineSlots<{
17
- default: () => { children: Array<VNode & { props: RadioProps }> }[]
17
+ default: () => Array<typeof Radio>
18
18
  }>()
19
19
 
20
20
  const checked = defineModel()
21
+
22
+ watchEffect(() => {
23
+ if (slots.default().some(s => s.type.__name !== 'Radio')) {
24
+ console.error('You can only pass `<Radio />` components as children.')
25
+ }
26
+ })
21
27
  </script>
22
28
 
23
29
  <template>
24
30
  <Flex v-bind="flexProps">
25
31
  <Component
26
32
  :is="vnode"
27
- v-for="vnode of slots.default()[0].children"
33
+ v-for="vnode of slots.default()"
28
34
  :key="vnode.props.value"
29
35
  v-bind="vnode.props"
30
36
  v-model="checked"
31
37
  :class="{ disabled: disabled || vnode.props.disabled }"
32
38
  />
33
39
  </Flex>
34
- <!-- <div class="vui-radio-group" /> -->
35
40
  </template>
@@ -1,6 +1,7 @@
1
1
  <script setup lang='ts'>
2
2
  import { computed } from 'vue'
3
3
  import Backdrop from '../../internal/Backdrop/Backdrop.vue'
4
+ import { formatUnitValue } from '../../shared/helpers'
4
5
  import Button from '../Button/Button.vue'
5
6
  import Divider from '../Divider/Divider.vue'
6
7
  import './sheet.scss'
@@ -17,6 +18,8 @@ const {
17
18
  separator,
18
19
  } = defineProps<Props>()
19
20
 
21
+ const TRANSITION_OFFSET = 16
22
+
20
23
  const open = defineModel<boolean>()
21
24
 
22
25
  function close() {
@@ -24,27 +27,21 @@ function close() {
24
27
  }
25
28
 
26
29
  const style = computed(() => {
27
- const formattedSizeValue = typeof size === 'number' ? `${size}px` : size
28
- let style
29
-
30
30
  if (position === 'left' || position === 'right') {
31
- style = { width: formattedSizeValue }
32
- }
33
- else {
34
- style = { minHeight: formattedSizeValue }
31
+ return { width: formatUnitValue(size) }
35
32
  }
36
33
 
37
- return style
34
+ return undefined
38
35
  })
39
36
 
40
37
  // Used to compute base location so that sheet appears to animate form the edge of the screen
41
38
  const baseTransform = computed(() => {
42
39
  switch (position) {
43
- case 'left': return `translate(-16px, 0)`
44
- case 'top': return `translate(0, -16px)`
45
- case 'bottom': return `translate(0, 16px)`
40
+ case 'left': return `translate(-${TRANSITION_OFFSET}px, 0)`
41
+ case 'top': return `translate(0, -${TRANSITION_OFFSET}px)`
42
+ case 'bottom': return `translate(0, ${TRANSITION_OFFSET}px)`
46
43
  case 'right':
47
- default: return `translate(16px, 0)`
44
+ default: return `translate(${TRANSITION_OFFSET}px, 0)`
48
45
  }
49
46
  })
50
47
  </script>
@@ -52,16 +49,16 @@ const baseTransform = computed(() => {
52
49
  <template>
53
50
  <Teleport to="body">
54
51
  <Transition appear name="sheet">
55
- <Backdrop v-if="open" :style="{ padding: 0 }" @close="open = false">
52
+ <Backdrop v-if="open" @close="open = false">
56
53
  <div v-if="open" class="vui-sheet" :class="[`vui-sheet-position-${position}`]" :style>
57
54
  <div class="vui-sheet-header">
58
- <div :style="{ flex: 1 }">
55
+ <div class="flex-1">
59
56
  <slot name="header" :close />
60
57
  </div>
61
58
  <Button square icon="ph:x" @click="open = false" />
62
59
  </div>
63
60
 
64
- <Divider v-if="separator && $slots.header" :size="1" />
61
+ <Divider v-if="separator && $slots.header" :space="1" />
65
62
 
66
63
  <div v-if="$slots.default" class="vui-sheet-content">
67
64
  <slot :close />
@@ -73,6 +70,10 @@ const baseTransform = computed(() => {
73
70
  </template>
74
71
 
75
72
  <style scoped lang="scss">
73
+ .vui-backdrop {
74
+ padding: 0;
75
+ }
76
+
76
77
  .sheet-enter-active,
77
78
  .sheet-leave-active {
78
79
  transition: var(--transition);
@@ -9,20 +9,24 @@
9
9
  &.vui-sheet-position-top {
10
10
  top: 0;
11
11
  border-bottom: 1px solid var(--color-border);
12
+ height: auto;
12
13
  }
13
14
 
14
15
  &.vui-sheet-position-bottom {
15
16
  bottom: 0;
16
17
  border-top: 1px solid var(--color-border);
18
+ height: auto;
17
19
  }
18
20
 
19
21
  &.vui-sheet-position-right {
20
22
  right: 0;
23
+ top: 0;
21
24
  border-left: 1px solid var(--color-border);
22
25
  }
23
26
 
24
27
  &.vui-sheet-position-left {
25
28
  left: 0;
29
+ top: 0;
26
30
  border-right: 1px solid var(--color-border);
27
31
  }
28
32
 
@@ -1,5 +1,7 @@
1
1
  <!-- eslint-disable ts/no-use-before-define -->
2
2
  <script setup lang='ts'>
3
+ import { computed } from 'vue'
4
+ import { formatUnitValue } from '../../shared/helpers'
3
5
  import './skeleton.scss'
4
6
 
5
7
  interface Props {
@@ -20,27 +22,24 @@ const {
20
22
 
21
23
  const DEFAULT_RADIUS = 'var(--border-radius-s)'
22
24
 
23
- function valueToPixels(value: string | number) {
24
- return typeof value === 'number'
25
- ? `${value}px`
26
- // If last value of string is NOT a number, do not add "px" at the end
27
- // eslint-disable-next-line unicorn/prefer-number-properties
28
- : isNaN(Number(value[value.length - 1]))
29
- ? value
30
- : `${value}px`
31
- }
25
+ // Give priority to radius, if it is NOT set to default
26
+ const bR = computed(() => formatUnitValue(circle && radius === DEFAULT_RADIUS ? 9999 : radius))
27
+
28
+ // When using `circle` prop, we want to use the same
29
+ // value for both height and width, but we can't
30
+ // know which one will be defined
31
+ const w = computed(() => formatUnitValue(circle ? (width || height) : width))
32
+ const h = computed(() => formatUnitValue(circle ? (width || height) : height))
32
33
  </script>
33
34
 
34
35
  <template>
35
- <div
36
- class="vui-skeleton" :style="{
37
- // Give priority to radius, if it is NOT set to default
38
- borderRadius: valueToPixels(circle && radius === DEFAULT_RADIUS ? 9999 : radius),
39
- // When using `circle` prop, we want to use the same
40
- // value for both height and width, but we can't
41
- // know which one will be defined
42
- width: valueToPixels(circle ? (width || height) : width),
43
- height: valueToPixels(circle ? (width || height) : height),
44
- }"
45
- />
36
+ <div class="vui-skeleton" />
46
37
  </template>
38
+
39
+ <style lang="scss" scoped>
40
+ .vui-skeleton {
41
+ border-radius: v-bind(bR);
42
+ width: v-bind(w);
43
+ height: v-bind(h);
44
+ }
45
+ </style>
@@ -12,7 +12,7 @@ const {
12
12
  size = 's',
13
13
  } = defineProps<Props>()
14
14
 
15
- const actualSize = computed(() => {
15
+ const w = computed(() => {
16
16
  switch (size) {
17
17
  case Size.s: return '16px'
18
18
  case Size.l: return '38px'
@@ -21,7 +21,7 @@ const actualSize = computed(() => {
21
21
  }
22
22
  })
23
23
 
24
- const actualBorderWidth = computed(() => {
24
+ const bW = computed(() => {
25
25
  switch (size) {
26
26
  case Size.s: return '3px'
27
27
  case Size.l: return '5px'
@@ -37,8 +37,8 @@ const actualBorderWidth = computed(() => {
37
37
 
38
38
  <style lang="scss">
39
39
  .vui-spinner {
40
- width: v-bind(actualSize);
41
- height: v-bind(actualSize);
42
- border-width: v-bind(actualBorderWidth);
40
+ width: v-bind(w);
41
+ height: v-bind(w);
42
+ border-width: v-bind(bW);
43
43
  }
44
44
  </style>
@@ -125,7 +125,8 @@ export function defineTable<const Dataset extends Array<BaseRow>>(
125
125
  const key = sorting.value.key
126
126
 
127
127
  if (key) {
128
- final = final.toSorted((a: Dataset[number], b: Dataset[number]) => {
128
+ // FIXME: change to `toSorted` when typescript is ok
129
+ final = [...final].sort((a: Dataset[number], b: Dataset[number]) => {
129
130
  const aValue = a[key]
130
131
  const bValue = b[key]
131
132
  return sorting.value.type === 'asc'
@@ -1,5 +1,5 @@
1
1
  <script setup lang='ts'>
2
- import type { Placement } from '@floating-ui/vue'
2
+ import type { Placement } from '../../shared/types'
3
3
  import { ref, useTemplateRef, watch } from 'vue'
4
4
  import Popout from '../Popout/Popout.vue'
5
5
  import './tooltip.scss'
@@ -57,3 +57,18 @@ export function setCharAt(str: string, char: string | number, index: number): st
57
57
  return char.toString()
58
58
  return str.substring(0, index) + char + str.substring(index + 1)
59
59
  }
60
+
61
+ /**
62
+ * Takes in a value and if it is a number, appends "px" to it, otherwise returns
63
+ * the original value.
64
+ *
65
+ */
66
+ export function formatUnitValue(value: string | number, unit: string = 'px'): string {
67
+ return typeof value === 'number'
68
+ ? `${value}${unit}`
69
+ // If last value of string is NOT a number, do not add "px" at the end
70
+ // eslint-disable-next-line unicorn/prefer-number-properties
71
+ : isNaN(Number(value[value.length - 1]))
72
+ ? value
73
+ : `${value}${unit}`
74
+ }
@@ -1,3 +1,5 @@
1
+ import type { ComponentPublicInstance } from 'vue'
2
+
1
3
  export enum Size {
2
4
  s = 's',
3
5
  m = 'm',
@@ -9,3 +11,7 @@ export type Sizes = 's' | 'm' | 'l'
9
11
  export type DeepRequired<T> = { [K in keyof T]: DeepRequired<T[K]> } & Required<T>
10
12
 
11
13
  export type VueClass = string | Record<string, | boolean> | Array<string | Record<string, string | boolean>>
14
+
15
+ // FLoating UI imported types were ruining the build so here we go
16
+ export type PopoutMaybeElement<T> = T | ComponentPublicInstance | null | undefined
17
+ export type Placement = 'top' | 'right' | 'bottom' | 'left' | 'top-start' | 'top-end' | 'right-start' | 'right-end' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end'
@@ -23,15 +23,17 @@
23
23
  --font-size-m: 1.6rem;
24
24
  --font-size-l: 1.65rem;
25
25
 
26
+ --space-xxs: 4px;
26
27
  --space-xs: 8px;
27
28
  --space-s: 12px;
28
29
  --space-m: 18px;
29
30
  --space-l: 26px;
30
31
  --space-xl: 40px;
31
32
  --space-xxl: 52px;
33
+ --space-xxxl: 64px;
32
34
 
33
35
  --transition-quick: 0.08s all ease-in-out;
34
- --transition: 0.1s all ease-in-out;
36
+ --transition: 0.14s all ease-in-out;
35
37
  --transition-slow: 0.3s all ease-in-out;
36
38
 
37
39
  --color-bg: rgb(18, 18, 18);
@@ -117,6 +119,7 @@
117
119
 
118
120
  body {
119
121
  color: var(--color-text);
122
+ min-height: 100dvh;
120
123
  }
121
124
 
122
125
  @import './typography.scss';
@@ -7,3 +7,7 @@
7
7
  padding-inline: var(--space-m);
8
8
  max-width: var(--container-l);
9
9
  }
10
+
11
+ .flex-1 {
12
+ flex: 1;
13
+ }