@dolanske/vui 0.3.4 → 0.4.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 (110) hide show
  1. package/LICENSE +673 -673
  2. package/README.md +49 -40
  3. package/dist/components/Dropdown/DropdownItem.vue.d.ts +1 -0
  4. package/dist/style.css +1 -1
  5. package/dist/vui.js +864 -859
  6. package/package.json +68 -68
  7. package/src/App.vue +198 -175
  8. package/src/components/Accordion/Accordion.vue +91 -91
  9. package/src/components/Accordion/AccordionGroup.vue +43 -43
  10. package/src/components/Accordion/accordion.scss +80 -80
  11. package/src/components/Alert/Alert.vue +53 -53
  12. package/src/components/Alert/alert.scss +80 -80
  13. package/src/components/Avatar/Avatar.vue +50 -50
  14. package/src/components/Avatar/avatar.scss +52 -52
  15. package/src/components/Badge/Badge.vue +21 -21
  16. package/src/components/Badge/badge.scss +89 -89
  17. package/src/components/Breadcrumbs/BreadcrumbItem.vue +26 -26
  18. package/src/components/Breadcrumbs/Breadcrumbs.vue +33 -33
  19. package/src/components/Breadcrumbs/breadcrumbs.scss +30 -30
  20. package/src/components/Button/Button.vue +90 -90
  21. package/src/components/Button/button.scss +176 -176
  22. package/src/components/ButtonGroup/ButtonGroup.vue +25 -25
  23. package/src/components/ButtonGroup/button-group.scss +51 -51
  24. package/src/components/Calendar/Calendar.vue +60 -60
  25. package/src/components/Calendar/calendar.scss +56 -56
  26. package/src/components/Card/Card.vue +48 -48
  27. package/src/components/Card/card.scss +53 -53
  28. package/src/components/Checkbox/Checkbox.vue +52 -52
  29. package/src/components/Checkbox/checkbox.scss +66 -66
  30. package/src/components/CopyClipboard/CopyClipboard.vue +82 -82
  31. package/src/components/CopyClipboard/copy-clipboard.scss +17 -17
  32. package/src/components/Divider/Divider.vue +44 -44
  33. package/src/components/Divider/divider.scss +35 -35
  34. package/src/components/Drawer/Drawer.vue +97 -97
  35. package/src/components/Drawer/drawer.scss +36 -36
  36. package/src/components/Dropdown/Dropdown.vue +111 -111
  37. package/src/components/Dropdown/DropdownItem.vue +32 -29
  38. package/src/components/Dropdown/DropdownTitle.vue +8 -8
  39. package/src/components/Dropdown/dropdown.scss +118 -117
  40. package/src/components/Flex/Flex.vue +110 -106
  41. package/src/components/Grid/Grid.vue +57 -54
  42. package/src/components/Input/Counter.vue +70 -70
  43. package/src/components/Input/Dropzone.vue +65 -65
  44. package/src/components/Input/File.vue +15 -15
  45. package/src/components/Input/Input.vue +121 -121
  46. package/src/components/Input/Password.vue +47 -47
  47. package/src/components/Input/Textarea.vue +76 -76
  48. package/src/components/Input/input.scss +208 -208
  49. package/src/components/Kbd/Kbd.vue +48 -48
  50. package/src/components/Kbd/KbdGroup.vue +31 -31
  51. package/src/components/Kbd/kbd.scss +18 -18
  52. package/src/components/Modal/Confirm.vue +56 -56
  53. package/src/components/Modal/Modal.vue +91 -91
  54. package/src/components/Modal/modal.scss +49 -49
  55. package/src/components/OTP/OTP.vue +133 -133
  56. package/src/components/OTP/OTPItem.vue +37 -37
  57. package/src/components/OTP/otp.scss +83 -83
  58. package/src/components/Pagination/Pagination.vue +74 -74
  59. package/src/components/Pagination/pagination.ts +78 -78
  60. package/src/components/Popout/Popout.vue +42 -42
  61. package/src/components/Popout/popout.scss +8 -8
  62. package/src/components/Progress/Progress.vue +90 -90
  63. package/src/components/Progress/progress.scss +41 -41
  64. package/src/components/Radio/Radio.vue +36 -36
  65. package/src/components/Radio/RadioGroup.vue +40 -40
  66. package/src/components/Radio/radio.scss +59 -59
  67. package/src/components/Select/Select.vue +180 -180
  68. package/src/components/Select/select.scss +44 -44
  69. package/src/components/Sheet/Sheet.vue +92 -92
  70. package/src/components/Sheet/sheet.scss +60 -60
  71. package/src/components/Sidebar/Sidebar.vue +85 -0
  72. package/src/components/Sidebar/sidebar.scss +123 -0
  73. package/src/components/Skeleton/Skeleton.vue +43 -43
  74. package/src/components/Skeleton/skeleton.scss +14 -14
  75. package/src/components/Spinner/Spinner.vue +42 -42
  76. package/src/components/Spinner/spinner.scss +46 -46
  77. package/src/components/Switch/Switch.vue +30 -30
  78. package/src/components/Switch/switch.scss +52 -52
  79. package/src/components/Table/Cell.vue +23 -23
  80. package/src/components/Table/Header.vue +59 -59
  81. package/src/components/Table/Row.vue +9 -9
  82. package/src/components/Table/SelectAll.vue +23 -23
  83. package/src/components/Table/SelectRow.vue +29 -29
  84. package/src/components/Table/Table.vue +66 -66
  85. package/src/components/Table/table.scss +134 -134
  86. package/src/components/Table/table.ts +244 -244
  87. package/src/components/Tabs/Tab.vue +27 -27
  88. package/src/components/Tabs/Tabs.vue +82 -82
  89. package/src/components/Tabs/tabs.scss +79 -79
  90. package/src/components/Toast/Toasts.vue +47 -47
  91. package/src/components/Toast/toast.scss +41 -41
  92. package/src/components/Toast/toast.ts +68 -68
  93. package/src/components/Tooltip/Tooltip.vue +86 -86
  94. package/src/components/Tooltip/tooltip.scss +4 -4
  95. package/src/index.scss +1 -1
  96. package/src/index.ts +119 -119
  97. package/src/internal/Backdrop/Backdrop.vue +22 -22
  98. package/src/internal/Backdrop/backdrop.scss +28 -28
  99. package/src/main.ts +5 -5
  100. package/src/shared/helpers.ts +74 -74
  101. package/src/shared/types.ts +29 -29
  102. package/src/style/animation.scss +21 -21
  103. package/src/style/core.scss +148 -148
  104. package/src/style/fonts.scss +53 -53
  105. package/src/style/layout.scss +136 -136
  106. package/src/style/media-query.scss +29 -29
  107. package/src/style/reset.scss +135 -135
  108. package/src/style/tooltip.scss +128 -128
  109. package/src/style/typography.scss +338 -338
  110. package/src/style/utils.scss +36 -36
@@ -1,59 +1,59 @@
1
- .vui-radio {
2
- --radio-size: 24px;
3
-
4
- &.checked {
5
- .vui-radio-icon svg {
6
- color: var(--color-text);
7
- }
8
- }
9
-
10
- &.disabled {
11
- cursor: not-allowed;
12
- pointer-events: none;
13
-
14
- .vui-radio-icon svg path {
15
- color: var(--color-text-lighter) !important;
16
- }
17
-
18
- input + label p {
19
- color: var(--color-text-lighter);
20
- }
21
- }
22
-
23
- .vui-radio-icon {
24
- cursor: pointer;
25
- width: var(--radio-size);
26
- height: var(--radio-size);
27
-
28
- svg {
29
- width: 100%;
30
- height: 100%;
31
- color: var(--color-text);
32
- }
33
- }
34
-
35
- input {
36
- display: none;
37
-
38
- & + label {
39
- display: grid;
40
- grid-template-columns: 20px 1fr;
41
- gap: 10px;
42
- font-size: var(--font-size-s);
43
- color: var(--color-text);
44
- user-select: none;
45
-
46
- .vui-radio-content {
47
- display: block;
48
-
49
- &:is(p) {
50
- display: flex;
51
- align-items: center;
52
- min-height: var(--radio-size);
53
- font-size: var(--font-size-ms);
54
- // line-height: var(--radio-size);
55
- }
56
- }
57
- }
58
- }
59
- }
1
+ .vui-radio {
2
+ --radio-size: 24px;
3
+
4
+ &.checked {
5
+ .vui-radio-icon svg {
6
+ color: var(--color-text);
7
+ }
8
+ }
9
+
10
+ &.disabled {
11
+ cursor: not-allowed;
12
+ pointer-events: none;
13
+
14
+ .vui-radio-icon svg path {
15
+ color: var(--color-text-lighter) !important;
16
+ }
17
+
18
+ input + label p {
19
+ color: var(--color-text-lighter);
20
+ }
21
+ }
22
+
23
+ .vui-radio-icon {
24
+ cursor: pointer;
25
+ width: var(--radio-size);
26
+ height: var(--radio-size);
27
+
28
+ svg {
29
+ width: 100%;
30
+ height: 100%;
31
+ color: var(--color-text);
32
+ }
33
+ }
34
+
35
+ input {
36
+ display: none;
37
+
38
+ & + label {
39
+ display: grid;
40
+ grid-template-columns: 20px 1fr;
41
+ gap: 10px;
42
+ font-size: var(--font-size-s);
43
+ color: var(--color-text);
44
+ user-select: none;
45
+
46
+ .vui-radio-content {
47
+ display: block;
48
+
49
+ &:is(p) {
50
+ display: flex;
51
+ align-items: center;
52
+ min-height: var(--radio-size);
53
+ font-size: var(--font-size-ms);
54
+ // line-height: var(--radio-size);
55
+ }
56
+ }
57
+ }
58
+ }
59
+ }
@@ -1,180 +1,180 @@
1
- <!-- eslint-disable ts/consistent-type-definitions -->
2
- <script setup lang='ts' generic="T">
3
- import { Icon } from '@iconify/vue'
4
- import { computed, onMounted, ref, useTemplateRef } from 'vue'
5
- import { searchString } from '../../shared/helpers'
6
- import Button from '../Button/Button.vue'
7
- import Dropdown from '../Dropdown/Dropdown.vue'
8
- import DropdownItem from '../Dropdown/DropdownItem.vue'
9
- import DropdownTitle from '../Dropdown/DropdownTitle.vue'
10
- import Input from '../Input/Input.vue'
11
- import '../Input/input.scss'
12
- import './select.scss'
13
-
14
- export type SelectOption = {
15
- value: any
16
- label: string
17
- }
18
-
19
- type Props = {
20
- single?: boolean
21
- readonly?: boolean
22
- options: SelectOption[]
23
- label?: string
24
- placeholder?: string
25
- required?: boolean
26
- expand?: boolean
27
- hint?: string
28
- search?: boolean
29
- maxActiveOptions?: number
30
- showClear?: boolean
31
- }
32
-
33
- const {
34
- expand,
35
- readonly,
36
- required,
37
- hint,
38
- placeholder,
39
- options,
40
- single = true,
41
- search,
42
- maxActiveOptions = 3,
43
- showClear,
44
- } = defineProps<Props>()
45
-
46
- const selected = defineModel<SelectOption[] | undefined>()
47
-
48
- //
49
- function setValue(option: SelectOption) {
50
- if (single) {
51
- // Single
52
- if (selected.value?.some(o => o.value === option.value) && !required) {
53
- selected.value = undefined
54
- }
55
- else {
56
- selected.value = [option]
57
- }
58
- }
59
- else {
60
- if (selected.value && selected.value?.some(o => o.value === option.value)) {
61
- const values = selected.value.filter(o => o.value !== option.value)
62
- // Cant remove the last value if it's required
63
- if ((required && values.length > 0) || !required) {
64
- selected.value = values.length > 0 ? values : undefined
65
- }
66
- }
67
- else {
68
- if (!selected.value) {
69
- selected.value = [option]
70
- }
71
- else {
72
- selected.value?.push(option)
73
- }
74
- }
75
- }
76
- }
77
-
78
- // Search
79
- const searchStr = ref()
80
- const filteredOptions = computed(() => {
81
- if (!searchStr.value || searchStr.value.length === 0)
82
- return options
83
-
84
- return options.filter((option) => {
85
- return searchString(option.label, searchStr.value)
86
- })
87
- })
88
-
89
- // Render text inside the button
90
- const renderPlaceholder = computed(() => {
91
- // Render placeholder or a default select option
92
- if (!selected.value || selected.value.length === 0)
93
- return placeholder ?? 'Select an option'
94
-
95
- // Selected values
96
- if (single)
97
- return selected.value[0].label
98
-
99
- // If amount of selected exceeds the active capacity
100
- if (selected.value.length > maxActiveOptions) {
101
- return `${selected.value.length} selected`
102
- }
103
-
104
- // Just list ALL selected optionsx
105
- return selected.value.map(o => o.label).join(', ')
106
- })
107
-
108
- onMounted(() => {
109
- if (readonly && showClear) {
110
- console.warn('[Select] readonly and showClear are mutually exclusive props. The clear button will not show up if required is present.')
111
- }
112
- })
113
-
114
- const dropdownRef = useTemplateRef('dropdown')
115
-
116
- function clearValue() {
117
- selected.value = undefined
118
- dropdownRef.value?.close()
119
- }
120
- </script>
121
-
122
- <template>
123
- <div class="vui-input-container vui-select" :class="{ expand, required, readonly }">
124
- <Dropdown ref="dropdown" :expand>
125
- <template #trigger="{ toggle, isOpen }">
126
- <div class="vui-input vui-select-trigger-content">
127
- <label v-if="label" for="id">{{ label }}</label>
128
- <p v-if="hint" class="vui-input-hint">
129
- {{ hint }}
130
- </p>
131
-
132
- <button class="vui-input-style vui-select-trigger-container" @click="toggle">
133
- <span>
134
- {{ renderPlaceholder }}
135
- </span>
136
- <Button
137
- v-if="showClear && !required && selected"
138
- plain
139
- icon="ph:x"
140
- square
141
- size="s"
142
- @click.stop="clearValue"
143
- />
144
- <Icon :icon="isOpen ? 'ph:caret-up' : 'ph:caret-down'" />
145
- </button>
146
- </div>
147
- </template>
148
-
149
- <template #default="{ close, isOpen }">
150
- <DropdownTitle v-if="search">
151
- <Input
152
- v-model="searchStr"
153
- placeholder="Search..."
154
- :focus="isOpen"
155
- />
156
- </DropdownTitle>
157
-
158
- <p v-if="filteredOptions.length === 0" class="vue-select-no-results">
159
- No results...
160
- </p>
161
-
162
- <DropdownItem
163
- v-for="option in filteredOptions"
164
- :key="option.value"
165
- :class="{ selected: selected?.find(v => v.value === option.value) }"
166
- :icon="selected?.find(v => v.value === option.value) ? 'ph:check-bold' : ''"
167
- @click="() => {
168
- setValue(option)
169
- // In single mode, close modal after clicking
170
- if (single && !(required && selected && selected[0].value === option.value)) {
171
- close()
172
- }
173
- }"
174
- >
175
- {{ option.label }}
176
- </DropdownItem>
177
- </template>
178
- </Dropdown>
179
- </div>
180
- </template>
1
+ <!-- eslint-disable ts/consistent-type-definitions -->
2
+ <script setup lang='ts' generic="T">
3
+ import { Icon } from '@iconify/vue'
4
+ import { computed, onMounted, ref, useTemplateRef } from 'vue'
5
+ import { searchString } from '../../shared/helpers'
6
+ import Button from '../Button/Button.vue'
7
+ import Dropdown from '../Dropdown/Dropdown.vue'
8
+ import DropdownItem from '../Dropdown/DropdownItem.vue'
9
+ import DropdownTitle from '../Dropdown/DropdownTitle.vue'
10
+ import Input from '../Input/Input.vue'
11
+ import '../Input/input.scss'
12
+ import './select.scss'
13
+
14
+ export type SelectOption = {
15
+ value: any
16
+ label: string
17
+ }
18
+
19
+ type Props = {
20
+ single?: boolean
21
+ readonly?: boolean
22
+ options: SelectOption[]
23
+ label?: string
24
+ placeholder?: string
25
+ required?: boolean
26
+ expand?: boolean
27
+ hint?: string
28
+ search?: boolean
29
+ maxActiveOptions?: number
30
+ showClear?: boolean
31
+ }
32
+
33
+ const {
34
+ expand,
35
+ readonly,
36
+ required,
37
+ hint,
38
+ placeholder,
39
+ options,
40
+ single = true,
41
+ search,
42
+ maxActiveOptions = 3,
43
+ showClear,
44
+ } = defineProps<Props>()
45
+
46
+ const selected = defineModel<SelectOption[] | undefined>()
47
+
48
+ //
49
+ function setValue(option: SelectOption) {
50
+ if (single) {
51
+ // Single
52
+ if (selected.value?.some(o => o.value === option.value) && !required) {
53
+ selected.value = undefined
54
+ }
55
+ else {
56
+ selected.value = [option]
57
+ }
58
+ }
59
+ else {
60
+ if (selected.value && selected.value?.some(o => o.value === option.value)) {
61
+ const values = selected.value.filter(o => o.value !== option.value)
62
+ // Cant remove the last value if it's required
63
+ if ((required && values.length > 0) || !required) {
64
+ selected.value = values.length > 0 ? values : undefined
65
+ }
66
+ }
67
+ else {
68
+ if (!selected.value) {
69
+ selected.value = [option]
70
+ }
71
+ else {
72
+ selected.value?.push(option)
73
+ }
74
+ }
75
+ }
76
+ }
77
+
78
+ // Search
79
+ const searchStr = ref()
80
+ const filteredOptions = computed(() => {
81
+ if (!searchStr.value || searchStr.value.length === 0)
82
+ return options
83
+
84
+ return options.filter((option) => {
85
+ return searchString(option.label, searchStr.value)
86
+ })
87
+ })
88
+
89
+ // Render text inside the button
90
+ const renderPlaceholder = computed(() => {
91
+ // Render placeholder or a default select option
92
+ if (!selected.value || selected.value.length === 0)
93
+ return placeholder ?? 'Select an option'
94
+
95
+ // Selected values
96
+ if (single)
97
+ return selected.value[0].label
98
+
99
+ // If amount of selected exceeds the active capacity
100
+ if (selected.value.length > maxActiveOptions) {
101
+ return `${selected.value.length} selected`
102
+ }
103
+
104
+ // Just list ALL selected optionsx
105
+ return selected.value.map(o => o.label).join(', ')
106
+ })
107
+
108
+ onMounted(() => {
109
+ if (readonly && showClear) {
110
+ console.warn('[Select] readonly and showClear are mutually exclusive props. The clear button will not show up if required is present.')
111
+ }
112
+ })
113
+
114
+ const dropdownRef = useTemplateRef('dropdown')
115
+
116
+ function clearValue() {
117
+ selected.value = undefined
118
+ dropdownRef.value?.close()
119
+ }
120
+ </script>
121
+
122
+ <template>
123
+ <div class="vui-input-container vui-select" :class="{ expand, required, readonly }">
124
+ <Dropdown ref="dropdown" :expand>
125
+ <template #trigger="{ toggle, isOpen }">
126
+ <div class="vui-input vui-select-trigger-content">
127
+ <label v-if="label" for="id">{{ label }}</label>
128
+ <p v-if="hint" class="vui-input-hint">
129
+ {{ hint }}
130
+ </p>
131
+
132
+ <button class="vui-input-style vui-select-trigger-container" @click="toggle">
133
+ <span>
134
+ {{ renderPlaceholder }}
135
+ </span>
136
+ <Button
137
+ v-if="showClear && !required && selected"
138
+ plain
139
+ icon="ph:x"
140
+ square
141
+ size="s"
142
+ @click.stop="clearValue"
143
+ />
144
+ <Icon :icon="isOpen ? 'ph:caret-up' : 'ph:caret-down'" />
145
+ </button>
146
+ </div>
147
+ </template>
148
+
149
+ <template #default="{ close, isOpen }">
150
+ <DropdownTitle v-if="search">
151
+ <Input
152
+ v-model="searchStr"
153
+ placeholder="Search..."
154
+ :focus="isOpen"
155
+ />
156
+ </DropdownTitle>
157
+
158
+ <p v-if="filteredOptions.length === 0" class="vue-select-no-results">
159
+ No results...
160
+ </p>
161
+
162
+ <DropdownItem
163
+ v-for="option in filteredOptions"
164
+ :key="option.value"
165
+ :class="{ selected: selected?.find(v => v.value === option.value) }"
166
+ :icon="selected?.find(v => v.value === option.value) ? 'ph:check-bold' : ''"
167
+ @click="() => {
168
+ setValue(option)
169
+ // In single mode, close modal after clicking
170
+ if (single && !(required && selected && selected[0].value === option.value)) {
171
+ close()
172
+ }
173
+ }"
174
+ >
175
+ {{ option.label }}
176
+ </DropdownItem>
177
+ </template>
178
+ </Dropdown>
179
+ </div>
180
+ </template>
@@ -1,44 +1,44 @@
1
- .vui-input-container {
2
- &.vui-select {
3
- &.expand {
4
- .vui-dropdown-trigger-wrap,
5
- .vui-dropdown-trigger-content {
6
- width: 100%;
7
- }
8
- }
9
-
10
- .vui-select-trigger-container {
11
- span {
12
- white-space: nowrap;
13
- text-overflow: ellipsis;
14
- overflow-x: hidden;
15
- }
16
- }
17
-
18
- .vue-select-no-results {
19
- text-align: center;
20
- padding-block: var(--space-xs);
21
- }
22
-
23
- .vui-input-style {
24
- display: flex;
25
- align-items: center;
26
- justify-content: space-between;
27
- gap: var(--space-s);
28
-
29
- & > button {
30
- margin-right: -6px;
31
-
32
- .vui-button-slot svg {
33
- width: 14px;
34
- height: 14px;
35
- color: var(--color-text-light);
36
- }
37
- }
38
-
39
- &:hover {
40
- border-color: var(--color-border-strong);
41
- }
42
- }
43
- }
44
- }
1
+ .vui-input-container {
2
+ &.vui-select {
3
+ &.expand {
4
+ .vui-dropdown-trigger-wrap,
5
+ .vui-dropdown-trigger-content {
6
+ width: 100%;
7
+ }
8
+ }
9
+
10
+ .vui-select-trigger-container {
11
+ span {
12
+ white-space: nowrap;
13
+ text-overflow: ellipsis;
14
+ overflow-x: hidden;
15
+ }
16
+ }
17
+
18
+ .vue-select-no-results {
19
+ text-align: center;
20
+ padding-block: var(--space-xs);
21
+ }
22
+
23
+ .vui-input-style {
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: space-between;
27
+ gap: var(--space-s);
28
+
29
+ & > button {
30
+ margin-right: -6px;
31
+
32
+ .vui-button-slot svg {
33
+ width: 14px;
34
+ height: 14px;
35
+ color: var(--color-text-light);
36
+ }
37
+ }
38
+
39
+ &:hover {
40
+ border-color: var(--color-border-strong);
41
+ }
42
+ }
43
+ }
44
+ }