windly-ui 1.0.1 → 1.0.3
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/dist/module.d.mts +3 -0
- package/dist/module.json +8 -0
- package/dist/module.mjs +26 -0
- package/dist/runtime/components/Accordion.d.vue.ts +39 -0
- package/{ui-library → dist/runtime}/components/Accordion.vue +44 -70
- package/dist/runtime/components/Accordion.vue.d.ts +39 -0
- package/dist/runtime/components/Avatar.d.vue.ts +141 -0
- package/dist/runtime/components/Avatar.vue +72 -0
- package/dist/runtime/components/Avatar.vue.d.ts +141 -0
- package/dist/runtime/components/Badge.d.vue.ts +133 -0
- package/dist/runtime/components/Badge.vue +99 -0
- package/dist/runtime/components/Badge.vue.d.ts +133 -0
- package/dist/runtime/components/Breadcrumbs.d.vue.ts +83 -0
- package/{ui-library → dist/runtime}/components/Breadcrumbs.vue +37 -59
- package/dist/runtime/components/Breadcrumbs.vue.d.ts +83 -0
- package/dist/runtime/components/Button.d.vue.ts +199 -0
- package/dist/runtime/components/Button.vue +125 -0
- package/dist/runtime/components/Button.vue.d.ts +199 -0
- package/dist/runtime/components/Card.d.vue.ts +83 -0
- package/{ui-library → dist/runtime}/components/Card.vue +26 -39
- package/dist/runtime/components/Card.vue.d.ts +83 -0
- package/dist/runtime/components/Checkbox.d.vue.ts +190 -0
- package/{ui-library → dist/runtime}/components/Checkbox.vue +45 -68
- package/dist/runtime/components/Checkbox.vue.d.ts +190 -0
- package/dist/runtime/components/CodeBlock.d.vue.ts +16 -0
- package/dist/runtime/components/CodeBlock.vue +75 -0
- package/dist/runtime/components/CodeBlock.vue.d.ts +16 -0
- package/dist/runtime/components/ColorPicker.d.vue.ts +91 -0
- package/dist/runtime/components/ColorPicker.vue +244 -0
- package/dist/runtime/components/ColorPicker.vue.d.ts +91 -0
- package/dist/runtime/components/Date.d.vue.ts +137 -0
- package/dist/runtime/components/Date.vue +201 -0
- package/dist/runtime/components/Date.vue.d.ts +137 -0
- package/dist/runtime/components/Dialog.d.vue.ts +103 -0
- package/{ui-library → dist/runtime}/components/Dialog.vue +30 -65
- package/dist/runtime/components/Dialog.vue.d.ts +103 -0
- package/dist/runtime/components/Divider.d.vue.ts +51 -0
- package/dist/runtime/components/Divider.vue +52 -0
- package/dist/runtime/components/Divider.vue.d.ts +51 -0
- package/dist/runtime/components/Drawer.d.vue.ts +30 -0
- package/dist/runtime/components/Drawer.vue +43 -0
- package/dist/runtime/components/Drawer.vue.d.ts +30 -0
- package/dist/runtime/components/Dropdown.d.vue.ts +34 -0
- package/dist/runtime/components/Dropdown.vue +127 -0
- package/dist/runtime/components/Dropdown.vue.d.ts +34 -0
- package/dist/runtime/components/FileUploader.d.vue.ts +58 -0
- package/dist/runtime/components/FileUploader.vue +202 -0
- package/dist/runtime/components/FileUploader.vue.d.ts +58 -0
- package/dist/runtime/components/Icon.d.vue.ts +41 -0
- package/dist/runtime/components/Icon.vue +66 -0
- package/dist/runtime/components/Icon.vue.d.ts +41 -0
- package/dist/runtime/components/Image.d.vue.ts +77 -0
- package/dist/runtime/components/Image.vue +61 -0
- package/dist/runtime/components/Image.vue.d.ts +77 -0
- package/dist/runtime/components/Input.d.vue.ts +66 -0
- package/dist/runtime/components/Input.vue +233 -0
- package/dist/runtime/components/Input.vue.d.ts +66 -0
- package/dist/runtime/components/Radio.d.vue.ts +41 -0
- package/dist/runtime/components/Radio.vue +222 -0
- package/dist/runtime/components/Radio.vue.d.ts +41 -0
- package/dist/runtime/components/ScrollArea.d.vue.ts +79 -0
- package/dist/runtime/components/ScrollArea.vue +36 -0
- package/dist/runtime/components/ScrollArea.vue.d.ts +79 -0
- package/dist/runtime/components/Select.d.vue.ts +43 -0
- package/dist/runtime/components/Select.vue +200 -0
- package/dist/runtime/components/Select.vue.d.ts +43 -0
- package/dist/runtime/components/Stepper.d.vue.ts +46 -0
- package/dist/runtime/components/Stepper.vue +218 -0
- package/dist/runtime/components/Stepper.vue.d.ts +46 -0
- package/dist/runtime/components/TabPanel.d.vue.ts +17 -0
- package/dist/runtime/components/TabPanel.vue +21 -0
- package/dist/runtime/components/TabPanel.vue.d.ts +17 -0
- package/dist/runtime/components/Table.d.vue.ts +40 -0
- package/dist/runtime/components/Table.vue +92 -0
- package/dist/runtime/components/Table.vue.d.ts +40 -0
- package/dist/runtime/components/Tabs.d.vue.ts +20 -0
- package/dist/runtime/components/Tabs.vue +62 -0
- package/dist/runtime/components/Tabs.vue.d.ts +20 -0
- package/dist/runtime/components/Textarea.d.vue.ts +208 -0
- package/dist/runtime/components/Textarea.vue +185 -0
- package/dist/runtime/components/Textarea.vue.d.ts +208 -0
- package/dist/runtime/components/Toggle.d.vue.ts +36 -0
- package/dist/runtime/components/Toggle.vue +173 -0
- package/dist/runtime/components/Toggle.vue.d.ts +36 -0
- package/dist/runtime/components/Tooltip.d.vue.ts +63 -0
- package/dist/runtime/components/Tooltip.vue +144 -0
- package/dist/runtime/components/Tooltip.vue.d.ts +63 -0
- package/dist/runtime/components/uiProps.d.ts +38 -0
- package/{ui-library/components/uiProps.ts → dist/runtime/components/uiProps.js} +2 -2
- package/dist/runtime/components/useUiClasses.d.ts +43 -0
- package/{ui-library/components/useUiClasses.ts → dist/runtime/components/useUiClasses.js} +25 -60
- package/dist/runtime/composables/plugin.d.ts +2 -0
- package/dist/runtime/composables/plugin.js +3 -0
- package/dist/runtime/tailwind-color.d.ts +2 -0
- package/dist/runtime/tailwind-color.js +5859 -0
- package/dist/types.d.mts +7 -0
- package/package.json +14 -16
- package/README.md +0 -208
- package/ui-library/components/Avatar.vue +0 -121
- package/ui-library/components/Badge.vue +0 -116
- package/ui-library/components/Button.vue +0 -154
- package/ui-library/components/CodeBlock.vue +0 -99
- package/ui-library/components/ColorPicker.vue +0 -302
- package/ui-library/components/Date.vue +0 -240
- package/ui-library/components/Divider.vue +0 -78
- package/ui-library/components/Drawer.vue +0 -67
- package/ui-library/components/Dropdown.vue +0 -248
- package/ui-library/components/FileUploader.vue +0 -330
- package/ui-library/components/Icon.vue +0 -82
- package/ui-library/components/Image.vue +0 -78
- package/ui-library/components/Input.vue +0 -531
- package/ui-library/components/Radio.vue +0 -356
- package/ui-library/components/ScrollArea.vue +0 -43
- package/ui-library/components/Select.vue +0 -309
- package/ui-library/components/Stepper.vue +0 -361
- package/ui-library/components/TabPanel.vue +0 -25
- package/ui-library/components/Table.vue +0 -152
- package/ui-library/components/Tabs.vue +0 -71
- package/ui-library/components/Textarea.vue +0 -233
- package/ui-library/components/Toggle.vue +0 -319
- package/ui-library/components/Tooltip.vue +0 -200
- package/ui-library/components/plugin.ts +0 -8
- package/ui-library/module.ts +0 -20
package/dist/types.d.mts
ADDED
package/package.json
CHANGED
|
@@ -1,27 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "windly-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"
|
|
6
|
-
|
|
5
|
+
"main": "./dist/module.mjs",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./dist/module.mjs"
|
|
8
|
+
},
|
|
7
9
|
"files": [
|
|
8
|
-
"
|
|
9
|
-
"README.md"
|
|
10
|
+
"dist"
|
|
10
11
|
],
|
|
11
|
-
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "nuxt build",
|
|
14
|
-
"
|
|
15
|
-
"generate": "nuxt generate",
|
|
16
|
-
"preview": "nuxt preview",
|
|
17
|
-
"postinstall": "nuxt prepare"
|
|
13
|
+
"build": "nuxt-module-build build",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
18
15
|
},
|
|
19
|
-
"
|
|
20
|
-
"nuxt": "^4.
|
|
21
|
-
"vue": "^3.5.26",
|
|
22
|
-
"vue-router": "^4.6.4"
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"nuxt": "^4.0.0"
|
|
23
18
|
},
|
|
24
19
|
"devDependencies": {
|
|
25
|
-
"@
|
|
20
|
+
"@nuxt/module-builder": "^1.0.0",
|
|
21
|
+
"@nuxt/kit": "^4.0.0",
|
|
22
|
+
"typescript": "^5.8.0",
|
|
23
|
+
"vue-tsc": "^2.2.0"
|
|
26
24
|
}
|
|
27
25
|
}
|
package/README.md
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
# Tailwind-Based UI Library for Nuxt 4
|
|
2
|
-
|
|
3
|
-
A lightweight, modular UI component library built specifically for Nuxt 4 applications, powered by Tailwind CSS.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Overview
|
|
8
|
-
|
|
9
|
-
This UI library is designed to accelerate frontend development by providing reusable, customizable, and auto-imported components. It focuses on simplicity, flexibility, and a smooth developer experience while staying fully aligned with Tailwind CSS principles.
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Key Features
|
|
14
|
-
|
|
15
|
-
### Tailwind-First Design
|
|
16
|
-
|
|
17
|
-
All components accept Tailwind utility classes directly via:
|
|
18
|
-
|
|
19
|
-
* `class`
|
|
20
|
-
* `:class`
|
|
21
|
-
|
|
22
|
-
This gives full control over styling without requiring overrides or complex theming systems.
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
### Auto Import (Nuxt 4 Native)
|
|
27
|
-
|
|
28
|
-
Components are automatically available across your application.
|
|
29
|
-
|
|
30
|
-
Example:
|
|
31
|
-
|
|
32
|
-
```vue
|
|
33
|
-
<UIButton label="Click Me" />
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
### Fully Reactive Components
|
|
39
|
-
|
|
40
|
-
Built using the Vue 3 Composition API:
|
|
41
|
-
|
|
42
|
-
* `ref`
|
|
43
|
-
* `computed`
|
|
44
|
-
* `watch`
|
|
45
|
-
* `provide / inject`
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
### Consistent API Design
|
|
50
|
-
|
|
51
|
-
All components follow predictable and consistent patterns:
|
|
52
|
-
|
|
53
|
-
* `v-model` support where applicable
|
|
54
|
-
* Props for variants such as color, size, and state
|
|
55
|
-
* Slots for flexible customization
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## Component Categories
|
|
60
|
-
|
|
61
|
-
### Form Controls
|
|
62
|
-
|
|
63
|
-
* UIInput
|
|
64
|
-
* UITextarea
|
|
65
|
-
* UIButton
|
|
66
|
-
* UIToggle
|
|
67
|
-
* UICheckbox
|
|
68
|
-
* UIRadio
|
|
69
|
-
* UIDropdown
|
|
70
|
-
* UIChip
|
|
71
|
-
|
|
72
|
-
---
|
|
73
|
-
|
|
74
|
-
### Navigation
|
|
75
|
-
|
|
76
|
-
* UIBreadcrumbs
|
|
77
|
-
* UITabs + UITabPanel
|
|
78
|
-
* UIAccordion
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
### Feedback and Popups
|
|
83
|
-
|
|
84
|
-
* UITooltip
|
|
85
|
-
* UIDialog
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
### Data Display
|
|
90
|
-
|
|
91
|
-
* UICard
|
|
92
|
-
* UIAvatar
|
|
93
|
-
* UIBadge
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
### Planned Components
|
|
98
|
-
|
|
99
|
-
* UIList
|
|
100
|
-
* UITable
|
|
101
|
-
* UIScrollArea
|
|
102
|
-
* UIImage
|
|
103
|
-
* UIIcon
|
|
104
|
-
* UIDivider
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
## Design Philosophy
|
|
109
|
-
|
|
110
|
-
### Minimal but Powerful
|
|
111
|
-
|
|
112
|
-
Components are intentionally lightweight while still supporting complex use cases through composition.
|
|
113
|
-
|
|
114
|
-
---
|
|
115
|
-
|
|
116
|
-
### Developer Control First
|
|
117
|
-
|
|
118
|
-
There is no rigid styling system. Tailwind utilities are used directly for full flexibility.
|
|
119
|
-
|
|
120
|
-
---
|
|
121
|
-
|
|
122
|
-
### Composition over Configuration
|
|
123
|
-
|
|
124
|
-
Instead of relying on large sets of props, the library encourages:
|
|
125
|
-
|
|
126
|
-
* Slots
|
|
127
|
-
* Composition patterns
|
|
128
|
-
* Vue reactivity
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
### Framework-Native Experience
|
|
133
|
-
|
|
134
|
-
Built specifically for:
|
|
135
|
-
|
|
136
|
-
* Nuxt 4
|
|
137
|
-
* Vue 3
|
|
138
|
-
|
|
139
|
-
No unnecessary abstractions or overhead.
|
|
140
|
-
|
|
141
|
-
---
|
|
142
|
-
|
|
143
|
-
## Example Usage
|
|
144
|
-
|
|
145
|
-
```vue
|
|
146
|
-
<template>
|
|
147
|
-
<UICard bordered>
|
|
148
|
-
<template #header>
|
|
149
|
-
<h3 class="text-lg font-semibold">Welcome</h3>
|
|
150
|
-
</template>
|
|
151
|
-
|
|
152
|
-
<p>This is a simple card using the UI library.</p>
|
|
153
|
-
|
|
154
|
-
<template #footer>
|
|
155
|
-
<UIButton label="Action" />
|
|
156
|
-
</template>
|
|
157
|
-
</UICard>
|
|
158
|
-
</template>
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
---
|
|
162
|
-
|
|
163
|
-
## Advanced Example
|
|
164
|
-
|
|
165
|
-
```vue
|
|
166
|
-
<UITabs v-model="activeTab">
|
|
167
|
-
<UITabPanel name="first" label="Overview">
|
|
168
|
-
<p>Overview content</p>
|
|
169
|
-
</UITabPanel>
|
|
170
|
-
|
|
171
|
-
<UITabPanel name="second" label="Details">
|
|
172
|
-
<p>Details content</p>
|
|
173
|
-
</UITabPanel>
|
|
174
|
-
</UITabs>
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
---
|
|
178
|
-
|
|
179
|
-
## Goals
|
|
180
|
-
|
|
181
|
-
* Provide a clean alternative to heavy UI frameworks
|
|
182
|
-
* Showcase advanced Vue patterns in a simple way
|
|
183
|
-
* Enable rapid prototyping with Tailwind
|
|
184
|
-
* Keep the system small, composable, and extensible
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## Future Improvements
|
|
189
|
-
|
|
190
|
-
* Theme system (dark mode, tokens)
|
|
191
|
-
* Component playground with live prop editing
|
|
192
|
-
* Accessibility improvements (ARIA support)
|
|
193
|
-
* Animation utilities
|
|
194
|
-
* Plugin system for extending components
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
## Summary
|
|
199
|
-
|
|
200
|
-
This UI library is a developer-focused toolkit for building modern Nuxt applications quickly without sacrificing flexibility or control.
|
|
201
|
-
|
|
202
|
-
It combines:
|
|
203
|
-
|
|
204
|
-
* Vue 3 reactivity
|
|
205
|
-
* Tailwind CSS flexibility
|
|
206
|
-
* Clean and consistent component design
|
|
207
|
-
|
|
208
|
-
Build fast, customize freely, and stay in control.
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
defineOptions({
|
|
3
|
-
inheritAttrs: false,
|
|
4
|
-
})
|
|
5
|
-
|
|
6
|
-
import { computed } from 'vue'
|
|
7
|
-
import { useUiClasses } from './useUiClasses'
|
|
8
|
-
import { uiProps } from "./uiProps";
|
|
9
|
-
|
|
10
|
-
const props = defineProps({
|
|
11
|
-
image: { type: String, default: '' },
|
|
12
|
-
altText: { type: String, default: 'Avatar' },
|
|
13
|
-
initials: { type: String, default: '' },
|
|
14
|
-
borderColor: { type: String, default: '#fff' },
|
|
15
|
-
borderThickness: { type: Number, default: 2 },
|
|
16
|
-
shadow: { type: Boolean, default: false },
|
|
17
|
-
...uiProps
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
// Use composable
|
|
21
|
-
const {
|
|
22
|
-
// props
|
|
23
|
-
contentClass,
|
|
24
|
-
contentStyle,
|
|
25
|
-
textColor,
|
|
26
|
-
color,
|
|
27
|
-
size,
|
|
28
|
-
// computed
|
|
29
|
-
colorClass,
|
|
30
|
-
computedContentClass,
|
|
31
|
-
isColorDark,
|
|
32
|
-
isHex,
|
|
33
|
-
isTailwindColor
|
|
34
|
-
} = useUiClasses(props)
|
|
35
|
-
|
|
36
|
-
const sizeClass = computed(() => {
|
|
37
|
-
const map = {
|
|
38
|
-
sm: 'avatar-sm',
|
|
39
|
-
md: 'avatar-md',
|
|
40
|
-
lg: 'avatar-lg'
|
|
41
|
-
} as const
|
|
42
|
-
|
|
43
|
-
return map[size.value as keyof typeof map]
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
const shadowClass = computed(() =>
|
|
47
|
-
props.shadow ? 'shadow-lg' : ''
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
const avatarClass = computed(() => {
|
|
51
|
-
return [
|
|
52
|
-
computedContentClass.value,
|
|
53
|
-
sizeClass.value,
|
|
54
|
-
shadowClass.value,
|
|
55
|
-
isTailwindColor(textColor.value) ? `text-${textColor.value}` : `text-${isColorDark(color.value) ? 'white' : 'gray-700'}`,
|
|
56
|
-
isTailwindColor(color.value) ? `bg-${color.value}` : ""
|
|
57
|
-
].filter((c) => !["", "!"].includes(c))
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
const avatarStyle = computed(() => ({
|
|
61
|
-
backgroundColor: isHex(color.value) && color.value,
|
|
62
|
-
color: isHex(textColor.value) && textColor.value,
|
|
63
|
-
borderColor: props.borderColor,
|
|
64
|
-
borderWidth: `${props.borderThickness}px`,
|
|
65
|
-
borderStyle: 'solid',
|
|
66
|
-
...contentStyle.value
|
|
67
|
-
}))
|
|
68
|
-
</script>
|
|
69
|
-
|
|
70
|
-
<template>
|
|
71
|
-
<div class="avatar" :class="avatarClass" :style="avatarStyle">
|
|
72
|
-
<img v-if="image" :src="image" :alt="altText" class="avatar-image" />
|
|
73
|
-
<span v-else class="avatar-initials">
|
|
74
|
-
{{ initials || '..' }}
|
|
75
|
-
</span>
|
|
76
|
-
</div>
|
|
77
|
-
</template>
|
|
78
|
-
|
|
79
|
-
<style scoped>
|
|
80
|
-
.avatar {
|
|
81
|
-
display: flex;
|
|
82
|
-
justify-content: center;
|
|
83
|
-
align-items: center;
|
|
84
|
-
border-radius: 50%;
|
|
85
|
-
overflow: hidden;
|
|
86
|
-
position: relative;
|
|
87
|
-
text-align: center;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.avatar-sm {
|
|
91
|
-
width: 40px;
|
|
92
|
-
height: 40px;
|
|
93
|
-
font-size: 0.875rem;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.avatar-md {
|
|
97
|
-
width: 60px;
|
|
98
|
-
height: 60px;
|
|
99
|
-
font-size: 1rem;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
.avatar-lg {
|
|
103
|
-
width: 80px;
|
|
104
|
-
height: 80px;
|
|
105
|
-
font-size: 1.25rem;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
.avatar-image {
|
|
109
|
-
width: 100%;
|
|
110
|
-
height: 100%;
|
|
111
|
-
object-fit: cover;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.avatar-initials {
|
|
115
|
-
font-weight: bold;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
.shadow-lg {
|
|
119
|
-
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
|
120
|
-
}
|
|
121
|
-
</style>
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
defineOptions({
|
|
3
|
-
inheritAttrs: false,
|
|
4
|
-
})
|
|
5
|
-
|
|
6
|
-
import { useSlots, computed } from 'vue'
|
|
7
|
-
import { useUiClasses } from './useUiClasses'
|
|
8
|
-
import { uiProps } from "./uiProps";
|
|
9
|
-
|
|
10
|
-
const slots = useSlots()
|
|
11
|
-
|
|
12
|
-
const props = defineProps({
|
|
13
|
-
content: { type: String, default: '' },
|
|
14
|
-
icon: { type: String, default: '' },
|
|
15
|
-
position: { type: String, default: 'superscript' },
|
|
16
|
-
show: { type: Boolean, default: true },
|
|
17
|
-
...uiProps
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
// Use composable
|
|
21
|
-
const {
|
|
22
|
-
// props
|
|
23
|
-
contentClass,
|
|
24
|
-
contentStyle,
|
|
25
|
-
color,
|
|
26
|
-
size,
|
|
27
|
-
rounded,
|
|
28
|
-
// computed
|
|
29
|
-
colorClass,
|
|
30
|
-
computedContentClass,
|
|
31
|
-
isColorDark,
|
|
32
|
-
isHex,
|
|
33
|
-
isTailwindColor
|
|
34
|
-
} = useUiClasses(props)
|
|
35
|
-
|
|
36
|
-
const hasSlots = computed(() => {
|
|
37
|
-
return !!slots.default?.()
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
const sizeClass = computed(() => {
|
|
41
|
-
const map = {
|
|
42
|
-
xs: 'w-auto min-w-2 h-2.5 text-[7px]',
|
|
43
|
-
sm: 'w-auto min-w-3 h-3 text-[10px]',
|
|
44
|
-
md: 'w-auto min-w-4 h-4 text-xs',
|
|
45
|
-
lg: 'w-auto min-w-6 h-6 text-sm'
|
|
46
|
-
} as const
|
|
47
|
-
|
|
48
|
-
return map[size.value as keyof typeof map]
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
const roundedClass = computed(() => {
|
|
52
|
-
const map = {
|
|
53
|
-
xs: 'rounded-xs',
|
|
54
|
-
sm: 'rounded-sm',
|
|
55
|
-
md: 'rounded',
|
|
56
|
-
lg: 'rounded-lg',
|
|
57
|
-
full: 'rounded-full'
|
|
58
|
-
} as const
|
|
59
|
-
|
|
60
|
-
return map[rounded.value as keyof typeof map]
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
const positionClasses = computed(() =>
|
|
64
|
-
props.position === 'superscript' && hasSlots.value
|
|
65
|
-
? 'absolute top-0 right-0 transform translate-x-1/2 -translate-y-1/2'
|
|
66
|
-
: ''
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
const badgeClass = computed(() => {
|
|
70
|
-
return [
|
|
71
|
-
'inline-flex items-center justify-center font-bold',
|
|
72
|
-
computedContentClass.value,
|
|
73
|
-
sizeClass.value,
|
|
74
|
-
roundedClass.value,
|
|
75
|
-
positionClasses.value,
|
|
76
|
-
isColorDark(color.value) ? 'text-white' : 'text-gray-700',
|
|
77
|
-
isTailwindColor(color.value) ? `bg-${color.value}` : ""
|
|
78
|
-
].filter((c) => !["", "!"].includes(c))
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
const badgeStyle = computed(() => {
|
|
82
|
-
const style = contentStyle.value
|
|
83
|
-
return {
|
|
84
|
-
backgroundColor: isHex(color.value) ? color.value : undefined,
|
|
85
|
-
...(typeof style === 'object' && style ? style : {})
|
|
86
|
-
}
|
|
87
|
-
})
|
|
88
|
-
</script>
|
|
89
|
-
|
|
90
|
-
<template>
|
|
91
|
-
<div class="flex">
|
|
92
|
-
<div v-if="hasSlots" class="relative">
|
|
93
|
-
<slot />
|
|
94
|
-
<span v-if="show" :class="[
|
|
95
|
-
badgeClass
|
|
96
|
-
]" :style="[badgeStyle]">
|
|
97
|
-
<span v-if="icon" class="p-1 material-icons">{{ icon }}</span>
|
|
98
|
-
<span v-if="content" class="p-1">{{ content }}</span>
|
|
99
|
-
</span>
|
|
100
|
-
</div>
|
|
101
|
-
<div v-else>
|
|
102
|
-
<span v-if="show" :class="[
|
|
103
|
-
badgeClass
|
|
104
|
-
]" :style="[badgeStyle]">
|
|
105
|
-
<span v-if="icon" class="p-1 material-icons">{{ icon }}</span>
|
|
106
|
-
<span v-if="content" class="p-1">{{ content }}</span>
|
|
107
|
-
</span>
|
|
108
|
-
</div>
|
|
109
|
-
</div>
|
|
110
|
-
</template>
|
|
111
|
-
|
|
112
|
-
<style scoped>
|
|
113
|
-
.material-icons {
|
|
114
|
-
font-size: 1em;
|
|
115
|
-
}
|
|
116
|
-
</style>
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
defineOptions({
|
|
3
|
-
inheritAttrs: false,
|
|
4
|
-
})
|
|
5
|
-
|
|
6
|
-
import { computed } from 'vue'
|
|
7
|
-
import { useUiClasses } from './useUiClasses'
|
|
8
|
-
import { uiProps } from "./uiProps";
|
|
9
|
-
|
|
10
|
-
// Props
|
|
11
|
-
const props = defineProps({
|
|
12
|
-
label: { type: String, default: null },
|
|
13
|
-
to: { type: [String, Object], default: null },
|
|
14
|
-
outline: { type: Boolean, default: false },
|
|
15
|
-
flat: { type: Boolean, default: false },
|
|
16
|
-
unelevated: { type: Boolean, default: false },
|
|
17
|
-
dense: { type: Boolean, default: false },
|
|
18
|
-
stacked: { type: Boolean, default: false },
|
|
19
|
-
gradient: { type: Boolean, default: false },
|
|
20
|
-
color2: { type: String, default: '' },
|
|
21
|
-
icon: { type: String, default: null },
|
|
22
|
-
iconColor: { type: String, default: null },
|
|
23
|
-
iconPosition: { type: String, default: 'start' },
|
|
24
|
-
...uiProps
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
// Use composable
|
|
28
|
-
const {
|
|
29
|
-
// props
|
|
30
|
-
contentClass,
|
|
31
|
-
contentStyle,
|
|
32
|
-
textColor,
|
|
33
|
-
disable,
|
|
34
|
-
loading,
|
|
35
|
-
color,
|
|
36
|
-
rounded,
|
|
37
|
-
size,
|
|
38
|
-
iconSize,
|
|
39
|
-
// class maps
|
|
40
|
-
roundedClass,
|
|
41
|
-
sizeClass,
|
|
42
|
-
iconSizeClasses,
|
|
43
|
-
// computed
|
|
44
|
-
colorClass,
|
|
45
|
-
computedContentClass,
|
|
46
|
-
isColorDark,
|
|
47
|
-
isHex,
|
|
48
|
-
isTailwindColor,
|
|
49
|
-
shadeTailwind,
|
|
50
|
-
shadeHex
|
|
51
|
-
} = useUiClasses(props)
|
|
52
|
-
|
|
53
|
-
const paddingClass = {
|
|
54
|
-
default: {
|
|
55
|
-
sm: "py-1 px-3 min-h-8 h-auto w-auto" + (props.label ? " min-w-16" : ""),
|
|
56
|
-
md: "py-2 px-6 min-h-10 h-auto w-auto" + (props.label ? " min-w-28":""),
|
|
57
|
-
lg: "py-3 px-8 min-h-12 h-auto w-auto" + (props.label ? " min-w-36":""),
|
|
58
|
-
},
|
|
59
|
-
dense: {
|
|
60
|
-
sm: "py-0.5 px-2 min-h-6 h-auto w-auto" + (props.label ? " min-w-16":""),
|
|
61
|
-
md: "py-1 px-4 min-h-8 h-auto w-auto" + (props.label ? " min-w-24":""),
|
|
62
|
-
lg: "py-1.5 px-6 min-h-10 h-auto w-auto" + (props.label ? " min-w-32":""),
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const computedClass = computed(() => {
|
|
67
|
-
let cls = `transition-all duration-300 text-nowrap ${roundedClass[(rounded.value as keyof typeof roundedClass)]} ${sizeClass[(size.value as keyof typeof sizeClass)]}`;
|
|
68
|
-
|
|
69
|
-
if (props.outline)
|
|
70
|
-
cls += ` border bg-white border-${colorClass.value} text-${colorClass.value} hover:bg-${colorClass.value} hover:text-white`;
|
|
71
|
-
|
|
72
|
-
if (props.flat)
|
|
73
|
-
cls += ` bg-transparent text-${colorClass.value} hover:bg-${colorClass.value} hover:bg-opacity-10 shadow-none`;
|
|
74
|
-
|
|
75
|
-
cls += props.dense ? ` ${paddingClass.dense[size.value as keyof typeof paddingClass.dense]}` : ` ${paddingClass.default[size.value as keyof typeof paddingClass.default]}`;
|
|
76
|
-
cls += props.unelevated ? " no-shadow" : " shadow-md";
|
|
77
|
-
cls += props.stacked ? " flex flex-col items-center justify-center gap-2" : " flex items-center justify-center gap-2";
|
|
78
|
-
cls += disable.value ? " opacity-50 cursor-not-allowed" : " cursor-pointer";
|
|
79
|
-
cls += loading.value ? " opacity-75 cursor-progress" : "";
|
|
80
|
-
cls += props.gradient
|
|
81
|
-
? ` bg-gradient-to-br from-${color.value} to-${computedColor2.value} hover:bg-gradient-to-tl text-${computedTextColor.value}`
|
|
82
|
-
: !props.flat && !props.outline
|
|
83
|
-
? ` bg-${color.value} hover:bg-${computedColor2.value} text-${computedTextColor.value}`
|
|
84
|
-
: "";
|
|
85
|
-
|
|
86
|
-
return cls;
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
const computedIconClass = computed(() => {
|
|
90
|
-
return `material-icons ${iconSizeClasses[props.iconPosition === 'start' ? 'lg' : 'md']} ${props.iconColor ? `text-${props.iconColor}` : ''}`
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
// Computed props for v-bind
|
|
94
|
-
const computedProps = computed(() => ({
|
|
95
|
-
class: computedClass.value,
|
|
96
|
-
disabled: disable.value || loading.value
|
|
97
|
-
}))
|
|
98
|
-
|
|
99
|
-
const computedTextColor = computed(() => {
|
|
100
|
-
if (textColor.value) {
|
|
101
|
-
return textColor.value;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (props.outline || props.flat) {
|
|
105
|
-
return color.value;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const darkBg = isColorDark(color.value);
|
|
109
|
-
return darkBg ? "white" : "gray-900"
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
const computedColor2 = computed(() => {
|
|
113
|
-
if (props.color2) return props.color2
|
|
114
|
-
|
|
115
|
-
if (isTailwindColor(color.value)) {
|
|
116
|
-
return shadeTailwind(color.value, 100)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (isHex(color.value)) {
|
|
120
|
-
return shadeHex(color.value, -20)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return color.value
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
// Click handler
|
|
127
|
-
function onClick() {
|
|
128
|
-
if (!loading.value && !disable.value && !props.to) {
|
|
129
|
-
emit('click')
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Emit function for script setup
|
|
134
|
-
const emit = defineEmits(['click'])
|
|
135
|
-
</script>
|
|
136
|
-
|
|
137
|
-
<template>
|
|
138
|
-
<!-- Router Link if "to" prop is provided -->
|
|
139
|
-
<router-link v-if="to" v-bind="computedProps" :to="to">
|
|
140
|
-
<!-- Icon (start position) -->
|
|
141
|
-
<i v-if="icon && iconPosition === 'start'" :class="computedIconClass">{{ icon }}</i>
|
|
142
|
-
<!-- Label -->
|
|
143
|
-
<span v-if="label" class="label">{{ label }}</span>
|
|
144
|
-
<!-- Icon (end position) -->
|
|
145
|
-
<i v-if="icon && iconPosition === 'end'" :class="computedIconClass">{{ icon }}</i>
|
|
146
|
-
</router-link>
|
|
147
|
-
|
|
148
|
-
<!-- Normal button if no "to" prop -->
|
|
149
|
-
<button v-else v-bind="computedProps" @click="onClick">
|
|
150
|
-
<i v-if="icon && iconPosition === 'start'" :class="computedIconClass">{{ icon }}</i>
|
|
151
|
-
<span v-if="label" class="label">{{ label }}</span>
|
|
152
|
-
<i v-if="icon && iconPosition === 'end'" :class="computedIconClass">{{ icon }}</i>
|
|
153
|
-
</button>
|
|
154
|
-
</template>
|