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.
Files changed (123) hide show
  1. package/dist/module.d.mts +3 -0
  2. package/dist/module.json +8 -0
  3. package/dist/module.mjs +26 -0
  4. package/dist/runtime/components/Accordion.d.vue.ts +39 -0
  5. package/{ui-library → dist/runtime}/components/Accordion.vue +44 -70
  6. package/dist/runtime/components/Accordion.vue.d.ts +39 -0
  7. package/dist/runtime/components/Avatar.d.vue.ts +141 -0
  8. package/dist/runtime/components/Avatar.vue +72 -0
  9. package/dist/runtime/components/Avatar.vue.d.ts +141 -0
  10. package/dist/runtime/components/Badge.d.vue.ts +133 -0
  11. package/dist/runtime/components/Badge.vue +99 -0
  12. package/dist/runtime/components/Badge.vue.d.ts +133 -0
  13. package/dist/runtime/components/Breadcrumbs.d.vue.ts +83 -0
  14. package/{ui-library → dist/runtime}/components/Breadcrumbs.vue +37 -59
  15. package/dist/runtime/components/Breadcrumbs.vue.d.ts +83 -0
  16. package/dist/runtime/components/Button.d.vue.ts +199 -0
  17. package/dist/runtime/components/Button.vue +125 -0
  18. package/dist/runtime/components/Button.vue.d.ts +199 -0
  19. package/dist/runtime/components/Card.d.vue.ts +83 -0
  20. package/{ui-library → dist/runtime}/components/Card.vue +26 -39
  21. package/dist/runtime/components/Card.vue.d.ts +83 -0
  22. package/dist/runtime/components/Checkbox.d.vue.ts +190 -0
  23. package/{ui-library → dist/runtime}/components/Checkbox.vue +45 -68
  24. package/dist/runtime/components/Checkbox.vue.d.ts +190 -0
  25. package/dist/runtime/components/CodeBlock.d.vue.ts +16 -0
  26. package/dist/runtime/components/CodeBlock.vue +75 -0
  27. package/dist/runtime/components/CodeBlock.vue.d.ts +16 -0
  28. package/dist/runtime/components/ColorPicker.d.vue.ts +91 -0
  29. package/dist/runtime/components/ColorPicker.vue +244 -0
  30. package/dist/runtime/components/ColorPicker.vue.d.ts +91 -0
  31. package/dist/runtime/components/Date.d.vue.ts +137 -0
  32. package/dist/runtime/components/Date.vue +201 -0
  33. package/dist/runtime/components/Date.vue.d.ts +137 -0
  34. package/dist/runtime/components/Dialog.d.vue.ts +103 -0
  35. package/{ui-library → dist/runtime}/components/Dialog.vue +30 -65
  36. package/dist/runtime/components/Dialog.vue.d.ts +103 -0
  37. package/dist/runtime/components/Divider.d.vue.ts +51 -0
  38. package/dist/runtime/components/Divider.vue +52 -0
  39. package/dist/runtime/components/Divider.vue.d.ts +51 -0
  40. package/dist/runtime/components/Drawer.d.vue.ts +30 -0
  41. package/dist/runtime/components/Drawer.vue +43 -0
  42. package/dist/runtime/components/Drawer.vue.d.ts +30 -0
  43. package/dist/runtime/components/Dropdown.d.vue.ts +34 -0
  44. package/dist/runtime/components/Dropdown.vue +127 -0
  45. package/dist/runtime/components/Dropdown.vue.d.ts +34 -0
  46. package/dist/runtime/components/FileUploader.d.vue.ts +58 -0
  47. package/dist/runtime/components/FileUploader.vue +202 -0
  48. package/dist/runtime/components/FileUploader.vue.d.ts +58 -0
  49. package/dist/runtime/components/Icon.d.vue.ts +41 -0
  50. package/dist/runtime/components/Icon.vue +66 -0
  51. package/dist/runtime/components/Icon.vue.d.ts +41 -0
  52. package/dist/runtime/components/Image.d.vue.ts +77 -0
  53. package/dist/runtime/components/Image.vue +61 -0
  54. package/dist/runtime/components/Image.vue.d.ts +77 -0
  55. package/dist/runtime/components/Input.d.vue.ts +66 -0
  56. package/dist/runtime/components/Input.vue +233 -0
  57. package/dist/runtime/components/Input.vue.d.ts +66 -0
  58. package/dist/runtime/components/Radio.d.vue.ts +41 -0
  59. package/dist/runtime/components/Radio.vue +222 -0
  60. package/dist/runtime/components/Radio.vue.d.ts +41 -0
  61. package/dist/runtime/components/ScrollArea.d.vue.ts +79 -0
  62. package/dist/runtime/components/ScrollArea.vue +36 -0
  63. package/dist/runtime/components/ScrollArea.vue.d.ts +79 -0
  64. package/dist/runtime/components/Select.d.vue.ts +43 -0
  65. package/dist/runtime/components/Select.vue +200 -0
  66. package/dist/runtime/components/Select.vue.d.ts +43 -0
  67. package/dist/runtime/components/Stepper.d.vue.ts +46 -0
  68. package/dist/runtime/components/Stepper.vue +218 -0
  69. package/dist/runtime/components/Stepper.vue.d.ts +46 -0
  70. package/dist/runtime/components/TabPanel.d.vue.ts +17 -0
  71. package/dist/runtime/components/TabPanel.vue +21 -0
  72. package/dist/runtime/components/TabPanel.vue.d.ts +17 -0
  73. package/dist/runtime/components/Table.d.vue.ts +40 -0
  74. package/dist/runtime/components/Table.vue +92 -0
  75. package/dist/runtime/components/Table.vue.d.ts +40 -0
  76. package/dist/runtime/components/Tabs.d.vue.ts +20 -0
  77. package/dist/runtime/components/Tabs.vue +62 -0
  78. package/dist/runtime/components/Tabs.vue.d.ts +20 -0
  79. package/dist/runtime/components/Textarea.d.vue.ts +208 -0
  80. package/dist/runtime/components/Textarea.vue +185 -0
  81. package/dist/runtime/components/Textarea.vue.d.ts +208 -0
  82. package/dist/runtime/components/Toggle.d.vue.ts +36 -0
  83. package/dist/runtime/components/Toggle.vue +173 -0
  84. package/dist/runtime/components/Toggle.vue.d.ts +36 -0
  85. package/dist/runtime/components/Tooltip.d.vue.ts +63 -0
  86. package/dist/runtime/components/Tooltip.vue +144 -0
  87. package/dist/runtime/components/Tooltip.vue.d.ts +63 -0
  88. package/dist/runtime/components/uiProps.d.ts +38 -0
  89. package/{ui-library/components/uiProps.ts → dist/runtime/components/uiProps.js} +2 -2
  90. package/dist/runtime/components/useUiClasses.d.ts +43 -0
  91. package/{ui-library/components/useUiClasses.ts → dist/runtime/components/useUiClasses.js} +25 -60
  92. package/dist/runtime/composables/plugin.d.ts +2 -0
  93. package/dist/runtime/composables/plugin.js +3 -0
  94. package/dist/runtime/tailwind-color.d.ts +2 -0
  95. package/dist/runtime/tailwind-color.js +5859 -0
  96. package/dist/types.d.mts +7 -0
  97. package/package.json +14 -16
  98. package/README.md +0 -208
  99. package/ui-library/components/Avatar.vue +0 -121
  100. package/ui-library/components/Badge.vue +0 -116
  101. package/ui-library/components/Button.vue +0 -154
  102. package/ui-library/components/CodeBlock.vue +0 -99
  103. package/ui-library/components/ColorPicker.vue +0 -302
  104. package/ui-library/components/Date.vue +0 -240
  105. package/ui-library/components/Divider.vue +0 -78
  106. package/ui-library/components/Drawer.vue +0 -67
  107. package/ui-library/components/Dropdown.vue +0 -248
  108. package/ui-library/components/FileUploader.vue +0 -330
  109. package/ui-library/components/Icon.vue +0 -82
  110. package/ui-library/components/Image.vue +0 -78
  111. package/ui-library/components/Input.vue +0 -531
  112. package/ui-library/components/Radio.vue +0 -356
  113. package/ui-library/components/ScrollArea.vue +0 -43
  114. package/ui-library/components/Select.vue +0 -309
  115. package/ui-library/components/Stepper.vue +0 -361
  116. package/ui-library/components/TabPanel.vue +0 -25
  117. package/ui-library/components/Table.vue +0 -152
  118. package/ui-library/components/Tabs.vue +0 -71
  119. package/ui-library/components/Textarea.vue +0 -233
  120. package/ui-library/components/Toggle.vue +0 -319
  121. package/ui-library/components/Tooltip.vue +0 -200
  122. package/ui-library/components/plugin.ts +0 -8
  123. package/ui-library/module.ts +0 -20
@@ -0,0 +1,7 @@
1
+ import type { NuxtModule } from '@nuxt/schema'
2
+
3
+ import type { default as Module } from './module.mjs'
4
+
5
+ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
6
+
7
+ export { default } from './module.mjs'
package/package.json CHANGED
@@ -1,27 +1,25 @@
1
1
  {
2
2
  "name": "windly-ui",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "type": "module",
5
- "private": false,
6
-
5
+ "main": "./dist/module.mjs",
6
+ "exports": {
7
+ ".": "./dist/module.mjs"
8
+ },
7
9
  "files": [
8
- "ui-library",
9
- "README.md"
10
+ "dist"
10
11
  ],
11
-
12
12
  "scripts": {
13
- "build": "nuxt build",
14
- "dev": "nuxt dev",
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
- "dependencies": {
20
- "nuxt": "^4.2.2",
21
- "vue": "^3.5.26",
22
- "vue-router": "^4.6.4"
16
+ "peerDependencies": {
17
+ "nuxt": "^4.0.0"
23
18
  },
24
19
  "devDependencies": {
25
- "@nuxtjs/tailwindcss": "^6.14.0"
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>