@proj-airi/ui 0.8.0 → 0.8.1-beta.10
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.
- package/package.json +4 -3
- package/src/components/animations/index.ts +9 -0
- package/src/components/{Form/Checkbox/Checkbox.vue → form/checkbox/checkbox.vue} +1 -0
- package/src/components/form/checkbox/index.ts +1 -0
- package/src/components/form/combobox/combobox.vue +138 -0
- package/src/components/form/combobox/index.ts +1 -0
- package/src/components/{Form/Field/FieldCheckbox.vue → form/field/field-checkbox.vue} +1 -1
- package/src/components/{Form/Field/FieldInput.vue → form/field/field-input.vue} +20 -9
- package/src/components/{Form/Field/FieldKeyValues.vue → form/field/field-key-values.vue} +2 -2
- package/src/components/{Form/Field/FieldRange.vue → form/field/field-range.vue} +1 -1
- package/src/components/{Form/Field/FieldSelect.vue → form/field/field-select.vue} +1 -1
- package/src/components/{Form/Field/FieldTextArea.vue → form/field/field-text-area.vue} +2 -2
- package/src/components/{Form/Field/FieldValues.vue → form/field/field-values.vue} +1 -1
- package/src/components/form/field/index.ts +7 -0
- package/src/components/form/index.ts +9 -0
- package/src/components/form/input/index.ts +4 -0
- package/src/components/{Form/Input/InputFile.vue → form/input/input-file.vue} +1 -1
- package/src/components/{Form/Input/InputKeyValue.vue → form/input/input-key-value.vue} +1 -1
- package/src/components/form/input/input.vue +88 -0
- package/src/components/form/radio/index.ts +1 -0
- package/src/components/form/range/index.ts +3 -0
- package/src/components/form/select/index.ts +2 -0
- package/src/components/{Form/Select/Select.vue → form/select/select.vue} +1 -1
- package/src/components/form/select-tab/index.ts +1 -0
- package/src/components/{Form/SelectTab/SelectTab.vue → form/select-tab/select-tab.vue} +1 -0
- package/src/components/form/textarea/index.ts +2 -0
- package/src/components/{Form/Textarea/Textarea.vue → form/textarea/textarea.vue} +1 -1
- package/src/components/layouts/collapsible.vue +39 -0
- package/src/components/layouts/index.ts +3 -0
- package/src/components/layouts/screen.vue +72 -0
- package/src/components/layouts/skeleton.vue +75 -0
- package/src/components/misc/button.vue +174 -0
- package/src/components/misc/callout.vue +77 -0
- package/src/components/{Misc/DoubleCheckButton.vue → misc/double-check-button.vue} +1 -1
- package/src/components/misc/index.ts +4 -0
- package/src/components/misc/progress.vue +44 -0
- package/src/fallback.css +4 -0
- package/src/index.ts +4 -3
- package/src/components/Animations/index.ts +0 -3
- package/src/components/Form/Checkbox/index.ts +0 -1
- package/src/components/Form/Combobox/Combobox.vue +0 -130
- package/src/components/Form/Combobox/index.ts +0 -1
- package/src/components/Form/Field/index.ts +0 -7
- package/src/components/Form/Input/Input.vue +0 -23
- package/src/components/Form/Input/index.ts +0 -4
- package/src/components/Form/Radio/index.ts +0 -1
- package/src/components/Form/Range/index.ts +0 -3
- package/src/components/Form/Select/index.ts +0 -2
- package/src/components/Form/SelectTab/index.ts +0 -1
- package/src/components/Form/Textarea/index.ts +0 -2
- package/src/components/Form/index.ts +0 -9
- package/src/components/Misc/Button.vue +0 -118
- package/src/components/Misc/index.ts +0 -2
- /package/src/components/{Animations/BidirectionalTransition.vue → animations/transition-bidirectional.vue} +0 -0
- /package/src/components/{Animations/TransitionHorizontal.vue → animations/transition-horizontal.vue} +0 -0
- /package/src/components/{Animations/TransitionVertical.vue → animations/transition-vertical.vue} +0 -0
- /package/src/components/{Form/Input/BasicInputFile.vue → form/input/basic-input-file.vue} +0 -0
- /package/src/components/{Form/Radio/Radio.vue → form/radio/radio.vue} +0 -0
- /package/src/components/{Form/Range/ColorHueRange.vue → form/range/color-hue-range.vue} +0 -0
- /package/src/components/{Form/Range/Range.vue → form/range/range.vue} +0 -0
- /package/src/components/{Form/Range/RoundRange.vue → form/range/round-range.vue} +0 -0
- /package/src/components/{Form/Select/Option.vue → form/select/option.vue} +0 -0
- /package/src/components/{Form/Textarea/Basic.vue → form/textarea/basic-text-area.vue} +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = withDefaults(defineProps<{
|
|
3
|
+
animation?: 'pulse' | 'wave' | 'none'
|
|
4
|
+
}>(), {
|
|
5
|
+
animation: 'pulse',
|
|
6
|
+
})
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<div
|
|
11
|
+
class="skeleton"
|
|
12
|
+
:class="props.animation !== 'none' ? `skeleton-${props.animation}` : ''"
|
|
13
|
+
bg="neutral-200 dark:neutral-800"
|
|
14
|
+
overflow="hidden"
|
|
15
|
+
>
|
|
16
|
+
<slot />
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<style scoped>
|
|
21
|
+
.skeleton {
|
|
22
|
+
position: relative;
|
|
23
|
+
transition: all 0.2s ease-in-out;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Pulse animation */
|
|
27
|
+
.skeleton-pulse {
|
|
28
|
+
animation: skeleton-pulse 2s ease-in-out 0.5s infinite;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@keyframes skeleton-pulse {
|
|
32
|
+
0% {
|
|
33
|
+
opacity: 1;
|
|
34
|
+
}
|
|
35
|
+
50% {
|
|
36
|
+
opacity: 0.5;
|
|
37
|
+
}
|
|
38
|
+
100% {
|
|
39
|
+
opacity: 1;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Wave animation */
|
|
44
|
+
.skeleton-wave::after {
|
|
45
|
+
content: '';
|
|
46
|
+
position: absolute;
|
|
47
|
+
top: 0;
|
|
48
|
+
right: 0;
|
|
49
|
+
bottom: 0;
|
|
50
|
+
left: 0;
|
|
51
|
+
transform: translateX(-100%);
|
|
52
|
+
background: linear-gradient(90deg, transparent, rgb(255, 255, 255), transparent);
|
|
53
|
+
animation: skeleton-wave 2s ease-in-out infinite;
|
|
54
|
+
border-radius: inherit;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.dark .skeleton-wave::after {
|
|
58
|
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@keyframes skeleton-wave {
|
|
62
|
+
0% {
|
|
63
|
+
transform: translateX(-100%);
|
|
64
|
+
opacity: 0;
|
|
65
|
+
}
|
|
66
|
+
60% {
|
|
67
|
+
transform: translateX(100%);
|
|
68
|
+
opacity: 1;
|
|
69
|
+
}
|
|
70
|
+
100% {
|
|
71
|
+
transform: translateX(100%);
|
|
72
|
+
opacity: 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
</style>
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
|
|
4
|
+
import { TransitionBidirectional } from '../animations'
|
|
5
|
+
|
|
6
|
+
// Define button variants for better type safety and maintainability
|
|
7
|
+
type ButtonVariant = 'primary' | 'secondary' | 'secondary-muted' | 'danger' | 'caution' | 'pure' | 'ghost'
|
|
8
|
+
|
|
9
|
+
type ButtonTheme = 'default'
|
|
10
|
+
|
|
11
|
+
// Define size options for better flexibility
|
|
12
|
+
type ButtonSize = 'sm' | 'md' | 'lg'
|
|
13
|
+
|
|
14
|
+
interface ButtonProps {
|
|
15
|
+
toggled?: boolean // Optional toggled state for toggle buttons
|
|
16
|
+
icon?: string // Icon class name
|
|
17
|
+
label?: string // Button text label
|
|
18
|
+
disabled?: boolean // Disabled state
|
|
19
|
+
loading?: boolean // Loading state
|
|
20
|
+
variant?: ButtonVariant // Button style variant
|
|
21
|
+
size?: ButtonSize // Button size variant
|
|
22
|
+
theme?: ButtonTheme // Button theme
|
|
23
|
+
block?: boolean // Full width button
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const props = withDefaults(defineProps<ButtonProps>(), {
|
|
27
|
+
toggled: false,
|
|
28
|
+
variant: 'primary',
|
|
29
|
+
disabled: false,
|
|
30
|
+
loading: false,
|
|
31
|
+
size: 'md',
|
|
32
|
+
theme: 'default',
|
|
33
|
+
block: false,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const isDisabled = computed(() => props.disabled || props.loading)
|
|
37
|
+
|
|
38
|
+
// Extract variant styles for better organization
|
|
39
|
+
const variantClasses: Record<ButtonVariant, Record<ButtonTheme, {
|
|
40
|
+
default: string[]
|
|
41
|
+
nonToggled?: string
|
|
42
|
+
toggled?: string
|
|
43
|
+
}>> = {
|
|
44
|
+
'primary': {
|
|
45
|
+
default: {
|
|
46
|
+
default: [
|
|
47
|
+
'rounded-lg',
|
|
48
|
+
'backdrop-blur-md',
|
|
49
|
+
'bg-primary-500/15 hover:bg-primary-500/20 active:bg-primary-500/30 dark:bg-primary-700/30 dark:hover:bg-primary-700/40 dark:active:bg-primary-700/30',
|
|
50
|
+
'focus:ring-primary-300/60 dark:focus:ring-primary-600/30',
|
|
51
|
+
'border-2 border-solid border-primary-500/5 dark:border-primary-900/40',
|
|
52
|
+
'text-primary-950 dark:text-primary-100',
|
|
53
|
+
'focus:ring-2',
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
'secondary': {
|
|
58
|
+
default: {
|
|
59
|
+
default: [
|
|
60
|
+
'rounded-lg',
|
|
61
|
+
'backdrop-blur-md',
|
|
62
|
+
'bg-neutral-100/55 hover:bg-neutral-400/20 active:bg-neutral-400/30 dark:bg-neutral-700/60 dark:hover:bg-neutral-700/80 dark:active:bg-neutral-700/60',
|
|
63
|
+
'focus:ring-neutral-300/30 dark:focus:ring-neutral-600/60 dark:focus:ring-neutral-600/30',
|
|
64
|
+
'border-2 border-solid border-neutral-300/30 dark:border-neutral-700/30',
|
|
65
|
+
'text-neutral-950 dark:text-neutral-100',
|
|
66
|
+
'focus:ring-2',
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
'secondary-muted': {
|
|
71
|
+
default: {
|
|
72
|
+
default: [
|
|
73
|
+
'rounded-lg',
|
|
74
|
+
'backdrop-blur-md',
|
|
75
|
+
'hover:bg-neutral-50/50 active:bg-neutral-50/90 hover:dark:bg-neutral-800/50 active:dark:bg-neutral-800/90',
|
|
76
|
+
'border-2 border-solid border-neutral-100/60 dark:border-neutral-800/30',
|
|
77
|
+
'focus:ring-2 focus:ring-neutral-300/30 dark:focus:ring-neutral-600/60 dark:focus:ring-neutral-600/30',
|
|
78
|
+
],
|
|
79
|
+
nonToggled: 'bg-neutral-50/70 dark:bg-neutral-800/70 text-neutral-500 dark:text-neutral-400',
|
|
80
|
+
toggled: 'bg-white/90 dark:bg-neutral-500/70 ring-neutral-300/30 dark:ring-neutral-600/60 ring-2 dark:ring-neutral-600/30 text-primary-500 dark:text-primary-100',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
'danger': {
|
|
84
|
+
default: {
|
|
85
|
+
default: [
|
|
86
|
+
'rounded-lg',
|
|
87
|
+
'backdrop-blur-md',
|
|
88
|
+
'bg-red-500/15 hover:bg-red-500/20 active:bg-red-500/30 dark:bg-red-700/30 dark:hover:bg-red-700/40 dark:active:bg-red-700/30',
|
|
89
|
+
'focus:ring-2 focus:ring-red-300/30 dark:focus:ring-red-600/60 dark:focus:ring-red-600/30',
|
|
90
|
+
'border-2 border-solid border-red-200/30 dark:border-red-900/30',
|
|
91
|
+
'text-red-950 dark:text-red-100',
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
'caution': {
|
|
96
|
+
default: {
|
|
97
|
+
default: [
|
|
98
|
+
'rounded-lg',
|
|
99
|
+
'backdrop-blur-md',
|
|
100
|
+
'bg-amber-400/20 hover:bg-amber-400/25 active:bg-amber-400/35 dark:bg-amber-500/20 dark:hover:bg-amber-500/30 dark:active:bg-amber-500/35',
|
|
101
|
+
'focus:ring-2 focus:ring-amber-300/40 dark:focus:ring-amber-400/40',
|
|
102
|
+
'border-2 border-solid border-amber-300/40 dark:border-amber-500/40',
|
|
103
|
+
'text-amber-900 dark:text-amber-50',
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
'pure': {
|
|
108
|
+
default: {
|
|
109
|
+
default: [
|
|
110
|
+
'bg-transparent',
|
|
111
|
+
'text-neutral-900 dark:text-neutral-50',
|
|
112
|
+
'!px-0 !py-0',
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
'ghost': {
|
|
117
|
+
default: {
|
|
118
|
+
default: [
|
|
119
|
+
'bg-transparent',
|
|
120
|
+
'hover:bg-neutral-100/50 dark:hover:bg-neutral-800/50',
|
|
121
|
+
'text-neutral-500 dark:text-neutral-400',
|
|
122
|
+
'focus:ring-2 focus:ring-neutral-300/30 dark:focus:ring-neutral-600/30',
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Extract size styles for better organization
|
|
129
|
+
const sizeClasses: Record<ButtonSize, string> = {
|
|
130
|
+
sm: 'px-3 py-1.5 text-xs',
|
|
131
|
+
md: 'px-4 py-2 text-sm',
|
|
132
|
+
lg: 'px-6 py-3 text-base',
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Base classes that are always applied
|
|
136
|
+
const baseClasses = computed(() => {
|
|
137
|
+
const variant = variantClasses[props.variant] || variantClasses.primary
|
|
138
|
+
const theme = variant[props.theme] || variant.default
|
|
139
|
+
|
|
140
|
+
return [
|
|
141
|
+
'rounded-lg font-medium outline-none',
|
|
142
|
+
'transition-all duration-200 ease-in-out',
|
|
143
|
+
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
144
|
+
'backdrop-blur-md',
|
|
145
|
+
props.block ? 'w-full' : '',
|
|
146
|
+
sizeClasses[props.size],
|
|
147
|
+
theme.default,
|
|
148
|
+
props.toggled ? theme.toggled || '' : theme.nonToggled || '',
|
|
149
|
+
{ 'opacity-50 cursor-not-allowed': isDisabled.value },
|
|
150
|
+
'focus:ring-2',
|
|
151
|
+
]
|
|
152
|
+
})
|
|
153
|
+
</script>
|
|
154
|
+
|
|
155
|
+
<template>
|
|
156
|
+
<button
|
|
157
|
+
:disabled="isDisabled"
|
|
158
|
+
:class="baseClasses"
|
|
159
|
+
>
|
|
160
|
+
<div class="flex flex-row items-center justify-center gap-2">
|
|
161
|
+
<TransitionBidirectional
|
|
162
|
+
from-class="opacity-0 mr-0! w-0!"
|
|
163
|
+
active-class="transition-[width,margin] ease-in-out overflow-hidden transition-100"
|
|
164
|
+
>
|
|
165
|
+
<div v-if="loading || icon" class="w-4">
|
|
166
|
+
<div v-if="loading" class="i-svg-spinners:ring-resize h-4 w-4" />
|
|
167
|
+
<div v-else-if="icon" class="h-4 w-4" :class="icon" />
|
|
168
|
+
</div>
|
|
169
|
+
</TransitionBidirectional>
|
|
170
|
+
<span v-if="label">{{ label }}</span>
|
|
171
|
+
<slot v-else />
|
|
172
|
+
</div>
|
|
173
|
+
</button>
|
|
174
|
+
</template>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
type ThemeVariant = 'primary' | 'violet' | 'lime' | 'orange'
|
|
3
|
+
|
|
4
|
+
const props = withDefaults(defineProps<{
|
|
5
|
+
theme?: ThemeVariant
|
|
6
|
+
label?: string
|
|
7
|
+
}>(), {
|
|
8
|
+
theme: 'primary',
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
const themeClasses: Record<ThemeVariant, {
|
|
12
|
+
container: string[]
|
|
13
|
+
label?: string[]
|
|
14
|
+
}> = {
|
|
15
|
+
primary: {
|
|
16
|
+
container: [
|
|
17
|
+
'text-neutral-900/80 dark:text-neutral-100/80',
|
|
18
|
+
'bg-primary-50/80 dark:bg-primary-900/50 backdrop-blur-md',
|
|
19
|
+
`before:bg-primary-500/30 before:content-[''] before:dark:bg-primary-200/20`,
|
|
20
|
+
],
|
|
21
|
+
label: [
|
|
22
|
+
'text-primary-500 dark:text-primary-200 font-semibold',
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
lime: {
|
|
26
|
+
container: [
|
|
27
|
+
'text-neutral-900/80 dark:text-neutral-100/80',
|
|
28
|
+
'bg-lime-50/80 dark:bg-lime-900/50 backdrop-blur-md',
|
|
29
|
+
`before:bg-lime-500/30 before:content-[''] before:dark:bg-lime-200/20`,
|
|
30
|
+
],
|
|
31
|
+
label: [
|
|
32
|
+
'text-lime-500 dark:text-lime-200 font-semibold',
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
violet: {
|
|
36
|
+
container: [
|
|
37
|
+
'text-neutral-900/80 dark:text-neutral-100/80',
|
|
38
|
+
'bg-violet-50/80 dark:bg-violet-900/50 backdrop-blur-md',
|
|
39
|
+
`before:bg-violet-500/30 before:content-[''] before:dark:bg-violet-200/20`,
|
|
40
|
+
],
|
|
41
|
+
label: [
|
|
42
|
+
'text-violet-500 dark:text-violet-200 font-semibold',
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
orange: {
|
|
46
|
+
container: [
|
|
47
|
+
'text-neutral-900/80 dark:text-neutral-100/80',
|
|
48
|
+
'bg-orange-100/60 dark:bg-orange-900/50 backdrop-blur-md',
|
|
49
|
+
`before:bg-orange-500/30 before:content-[''] before:dark:bg-orange-200/20`,
|
|
50
|
+
],
|
|
51
|
+
label: [
|
|
52
|
+
'text-orange-500 dark:text-orange-200 font-semibold',
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<template>
|
|
59
|
+
<div
|
|
60
|
+
relative
|
|
61
|
+
flex flex-col gap-1
|
|
62
|
+
rounded-lg
|
|
63
|
+
py="2.5" pl="5" pr-3
|
|
64
|
+
:class="[
|
|
65
|
+
...themeClasses[props.theme || 'violet'].container,
|
|
66
|
+
// eslint-disable-next-line vue/prefer-separate-static-class
|
|
67
|
+
'before-position-absolute before:left-2 before:right-0 before:h-[calc(100%-1rem)] before:top-50% before:translate-y--50% before:w-1 before:rounded-full',
|
|
68
|
+
]"
|
|
69
|
+
>
|
|
70
|
+
<div text="font-semibold" :class="[...(themeClasses[props.theme || 'violet'].label || [])]">
|
|
71
|
+
<slot name="label">
|
|
72
|
+
{{ props.label || 'Callout' }}
|
|
73
|
+
</slot>
|
|
74
|
+
</div>
|
|
75
|
+
<slot />
|
|
76
|
+
</div>
|
|
77
|
+
</template>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, ref, watch } from 'vue'
|
|
3
3
|
|
|
4
|
-
import Button from './
|
|
4
|
+
import Button from './button.vue'
|
|
5
5
|
|
|
6
6
|
type ButtonVariant = 'primary' | 'secondary' | 'secondary-muted' | 'danger' | 'caution'
|
|
7
7
|
type ButtonSize = 'sm' | 'md' | 'lg'
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineProps<{
|
|
3
|
+
progress: number
|
|
4
|
+
barClass?: string
|
|
5
|
+
}>()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<div relative overflow-hidden rounded-md>
|
|
10
|
+
<div
|
|
11
|
+
:class="[barClass ? barClass : 'bg-primary-300 dark:bg-primary-300/50']"
|
|
12
|
+
absolute h-4 min-w-2 rounded-md will-change-width
|
|
13
|
+
:style="{ width: `${progress}%` }"
|
|
14
|
+
transition="width duration-500 ease-in-out"
|
|
15
|
+
>
|
|
16
|
+
<div
|
|
17
|
+
v-if="progress < 100"
|
|
18
|
+
absolute inset-0 origin-left rounded-md bg-white
|
|
19
|
+
class="progress-shine-animation"
|
|
20
|
+
/>
|
|
21
|
+
</div>
|
|
22
|
+
<div
|
|
23
|
+
bg="neutral-100 dark:neutral-900" h-4 w-full rounded-md
|
|
24
|
+
/>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<style scoped>
|
|
29
|
+
.progress-shine-animation {
|
|
30
|
+
animation: progress-shine 2s cubic-bezier(0.35, 0.08, 0.04, 0.99) infinite;
|
|
31
|
+
will-change: transform, opacity;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@keyframes progress-shine {
|
|
35
|
+
0% {
|
|
36
|
+
opacity: 0.4;
|
|
37
|
+
transform: scale(0, 1);
|
|
38
|
+
}
|
|
39
|
+
100% {
|
|
40
|
+
opacity: 0;
|
|
41
|
+
transform: scale(1, 1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
</style>
|
package/src/fallback.css
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import './fallback.css'
|
|
2
2
|
|
|
3
|
-
export * from './components/
|
|
4
|
-
export * from './components/
|
|
5
|
-
export * from './components/
|
|
3
|
+
export * from './components/animations'
|
|
4
|
+
export * from './components/form'
|
|
5
|
+
export * from './components/layouts'
|
|
6
|
+
export * from './components/misc'
|
|
6
7
|
export * from './composables/use-deferred-mount'
|
|
7
8
|
export * from './composables/use-theme'
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as Checkbox } from './Checkbox.vue'
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts" generic="T extends AcceptableValue">
|
|
2
|
-
import type { AcceptableValue } from 'reka-ui'
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
ComboboxAnchor,
|
|
6
|
-
ComboboxContent,
|
|
7
|
-
ComboboxEmpty,
|
|
8
|
-
ComboboxGroup,
|
|
9
|
-
ComboboxInput,
|
|
10
|
-
ComboboxItem,
|
|
11
|
-
ComboboxItemIndicator,
|
|
12
|
-
ComboboxLabel,
|
|
13
|
-
ComboboxRoot,
|
|
14
|
-
ComboboxSeparator,
|
|
15
|
-
ComboboxTrigger,
|
|
16
|
-
ComboboxViewport,
|
|
17
|
-
} from 'reka-ui'
|
|
18
|
-
|
|
19
|
-
const props = defineProps<{
|
|
20
|
-
options: { groupLabel: string, children?: { label: string, value: T }[] }[]
|
|
21
|
-
placeholder?: string
|
|
22
|
-
}>()
|
|
23
|
-
|
|
24
|
-
const modelValue = defineModel<T>({ required: false })
|
|
25
|
-
|
|
26
|
-
function toDisplayValue(value: T): string {
|
|
27
|
-
const option = props.options.flatMap(group => group.children).find(option => option?.value === value)
|
|
28
|
-
return option ? option.label : props.placeholder || ''
|
|
29
|
-
}
|
|
30
|
-
</script>
|
|
31
|
-
|
|
32
|
-
<template>
|
|
33
|
-
<ComboboxRoot v-model="modelValue" :class="['relative', 'w-full']">
|
|
34
|
-
<ComboboxAnchor
|
|
35
|
-
:class="[
|
|
36
|
-
'w-full inline-flex items-center justify-between rounded-xl border px-3 leading-none h-10 gap-[5px] outline-none',
|
|
37
|
-
'text-sm text-neutral-700 dark:text-neutral-200 data-[placeholder]:text-neutral-200',
|
|
38
|
-
'bg-white dark:bg-neutral-900 disabled:bg-neutral-100 hover:bg-neutral-50 dark:disabled:bg-neutral-900 dark:hover:bg-neutral-700',
|
|
39
|
-
'border-neutral-200 dark:border-neutral-800 border-solid border-2 focus:border-primary-300 dark:focus:border-primary-400/50',
|
|
40
|
-
'shadow-sm focus:shadow-[0_0_0_2px] focus:shadow-black',
|
|
41
|
-
'transition-colors duration-200 ease-in-out',
|
|
42
|
-
]"
|
|
43
|
-
>
|
|
44
|
-
<ComboboxInput
|
|
45
|
-
:class="[
|
|
46
|
-
'!bg-transparent outline-none h-full selection:bg-grass5 placeholder-stone-400 w-full',
|
|
47
|
-
'text-neutral-700 dark:text-neutral-200',
|
|
48
|
-
'transition-colors duration-200 ease-in-out',
|
|
49
|
-
]"
|
|
50
|
-
:placeholder="props.placeholder"
|
|
51
|
-
:display-value="(val) => toDisplayValue(val)"
|
|
52
|
-
/>
|
|
53
|
-
<ComboboxTrigger>
|
|
54
|
-
<div
|
|
55
|
-
i-solar:alt-arrow-down-linear
|
|
56
|
-
:class="[
|
|
57
|
-
'h-4 w-4',
|
|
58
|
-
'text-neutral-700 dark:text-neutral-200',
|
|
59
|
-
'transition-colors duration-200 ease-in-out',
|
|
60
|
-
]"
|
|
61
|
-
/>
|
|
62
|
-
</ComboboxTrigger>
|
|
63
|
-
</ComboboxAnchor>
|
|
64
|
-
|
|
65
|
-
<ComboboxContent
|
|
66
|
-
:avoid-collisions="true"
|
|
67
|
-
:class="[
|
|
68
|
-
'absolute z-10 w-full mt-1 min-w-[160px] overflow-hidden rounded-xl shadow-sm border will-change-[opacity,transform] max-h-50dvh',
|
|
69
|
-
'data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade',
|
|
70
|
-
'bg-white dark:bg-neutral-900',
|
|
71
|
-
'border-neutral-200 dark:border-neutral-800 border-solid border-2 focus:border-neutral-300 dark:focus:border-neutral-600',
|
|
72
|
-
]"
|
|
73
|
-
>
|
|
74
|
-
<ComboboxViewport class="p-[2px]">
|
|
75
|
-
<ComboboxEmpty
|
|
76
|
-
:class="[
|
|
77
|
-
'font-medium py-2 px-2',
|
|
78
|
-
'text-xs text-neutral-700 dark:text-neutral-200',
|
|
79
|
-
'transition-colors duration-200 ease-in-out',
|
|
80
|
-
]"
|
|
81
|
-
/>
|
|
82
|
-
|
|
83
|
-
<template
|
|
84
|
-
v-for="(group, index) in options"
|
|
85
|
-
:key="group.groupLabel"
|
|
86
|
-
>
|
|
87
|
-
<ComboboxGroup :class="['overflow-x-hidden']">
|
|
88
|
-
<ComboboxSeparator
|
|
89
|
-
v-if="index !== 0"
|
|
90
|
-
:class="['m-[5px]', 'h-[1px]', 'bg-neutral-400']"
|
|
91
|
-
/>
|
|
92
|
-
|
|
93
|
-
<ComboboxLabel
|
|
94
|
-
:class="[
|
|
95
|
-
'px-[25px] text-xs leading-[25px]',
|
|
96
|
-
'text-neutral-500 dark:text-neutral-400',
|
|
97
|
-
'transition-colors duration-200 ease-in-out',
|
|
98
|
-
]"
|
|
99
|
-
>
|
|
100
|
-
{{ group.groupLabel }}
|
|
101
|
-
</ComboboxLabel>
|
|
102
|
-
|
|
103
|
-
<ComboboxItem
|
|
104
|
-
v-for="option in group.children"
|
|
105
|
-
:key="option.label"
|
|
106
|
-
:text-value="option.label"
|
|
107
|
-
:value="option.value"
|
|
108
|
-
:class="[
|
|
109
|
-
'leading-none rounded-lg flex items-center h-8 pr-[0.5rem] pl-[1.5rem] relative select-none data-[disabled]:pointer-events-none data-[highlighted]:outline-none',
|
|
110
|
-
'data-[highlighted]:bg-neutral-100 dark:data-[highlighted]:bg-neutral-800',
|
|
111
|
-
'text-sm text-neutral-700 dark:text-neutral-200 data-[disabled]:text-neutral-400 dark:data-[disabled]:text-neutral-600 data-[highlighted]:text-grass1',
|
|
112
|
-
'transition-colors duration-200 ease-in-out',
|
|
113
|
-
'cursor-pointer',
|
|
114
|
-
]"
|
|
115
|
-
>
|
|
116
|
-
<ComboboxItemIndicator
|
|
117
|
-
:class="['absolute', 'left-0', 'w-[25px]', 'inline-flex', 'items-center', 'justify-center', 'opacity-30']"
|
|
118
|
-
>
|
|
119
|
-
<div i-solar:alt-arrow-right-outline />
|
|
120
|
-
</ComboboxItemIndicator>
|
|
121
|
-
<span :class="['line-clamp-1', 'overflow-hidden', 'text-ellipsis', 'whitespace-nowrap']">
|
|
122
|
-
{{ option.label }}
|
|
123
|
-
</span>
|
|
124
|
-
</ComboboxItem>
|
|
125
|
-
</ComboboxGroup>
|
|
126
|
-
</template>
|
|
127
|
-
</ComboboxViewport>
|
|
128
|
-
</ComboboxContent>
|
|
129
|
-
</ComboboxRoot>
|
|
130
|
-
</template>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as Combobox } from './Combobox.vue'
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { default as FieldCheckbox } from './FieldCheckbox.vue'
|
|
2
|
-
export { default as FieldInput } from './FieldInput.vue'
|
|
3
|
-
export { default as FieldKeyValues } from './FieldKeyValues.vue'
|
|
4
|
-
export { default as FieldRange } from './FieldRange.vue'
|
|
5
|
-
export { default as FieldSelect } from './FieldSelect.vue'
|
|
6
|
-
export { default as FieldTextArea } from './FieldTextArea.vue'
|
|
7
|
-
export { default as FieldValues } from './FieldValues.vue'
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
const props = defineProps<{
|
|
3
|
-
type?: string
|
|
4
|
-
}>()
|
|
5
|
-
|
|
6
|
-
const modelValue = defineModel<string>({ required: false })
|
|
7
|
-
</script>
|
|
8
|
-
|
|
9
|
-
<template>
|
|
10
|
-
<input
|
|
11
|
-
v-model="modelValue"
|
|
12
|
-
:type="props.type || 'text'"
|
|
13
|
-
:class="[
|
|
14
|
-
'focus:border-primary-300 dark:focus:border-primary-400/50 border-2 border-solid border-neutral-100 dark:border-neutral-900',
|
|
15
|
-
'transition-all duration-200 ease-in-out',
|
|
16
|
-
'text-disabled:neutral-400 dark:text-disabled:neutral-600',
|
|
17
|
-
'cursor-disabled:not-allowed',
|
|
18
|
-
'w-full rounded-lg px-2 py-1 text-nowrap text-sm outline-none',
|
|
19
|
-
'shadow-sm',
|
|
20
|
-
'bg-neutral-50 dark:bg-neutral-950 focus:bg-neutral-50 dark:focus:bg-neutral-900',
|
|
21
|
-
]"
|
|
22
|
-
>
|
|
23
|
-
</template>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as Radio } from './Radio.vue'
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as SelectTab } from './SelectTab.vue'
|