windly-ui 1.0.1 → 1.0.2
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/LICENSE +21 -0
- package/README.md +57 -33
- package/package.json +47 -15
- package/ui-library/dist/module.d.mts +3 -0
- package/ui-library/dist/module.json +8 -0
- package/ui-library/dist/module.mjs +22 -0
- package/ui-library/dist/types.d.mts +7 -0
- package/ui-library/components/Accordion.vue +0 -118
- package/ui-library/components/Avatar.vue +0 -121
- package/ui-library/components/Badge.vue +0 -116
- package/ui-library/components/Breadcrumbs.vue +0 -138
- package/ui-library/components/Button.vue +0 -154
- package/ui-library/components/Card.vue +0 -84
- package/ui-library/components/Checkbox.vue +0 -148
- 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/Dialog.vue +0 -187
- 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/components/uiProps.ts +0 -11
- package/ui-library/components/useUiClasses.ts +0 -159
- package/ui-library/module.ts +0 -20
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
defineOptions({
|
|
3
|
-
name: 'UITooltip',
|
|
4
|
-
inheritAttrs: false,
|
|
5
|
-
})
|
|
6
|
-
|
|
7
|
-
import { computed, ref } from 'vue'
|
|
8
|
-
|
|
9
|
-
type TooltipPlacement =
|
|
10
|
-
| 'top'
|
|
11
|
-
| 'right'
|
|
12
|
-
| 'bottom'
|
|
13
|
-
| 'left'
|
|
14
|
-
|
|
15
|
-
const props = defineProps({
|
|
16
|
-
text: {
|
|
17
|
-
type: String,
|
|
18
|
-
required: true,
|
|
19
|
-
},
|
|
20
|
-
placement: {
|
|
21
|
-
type: String as () => TooltipPlacement,
|
|
22
|
-
default: 'top',
|
|
23
|
-
|
|
24
|
-
validator: (v: string) =>
|
|
25
|
-
['top', 'right', 'bottom', 'left'].includes(v),
|
|
26
|
-
},
|
|
27
|
-
arrow: {
|
|
28
|
-
type: Boolean,
|
|
29
|
-
default: true,
|
|
30
|
-
},
|
|
31
|
-
color: {
|
|
32
|
-
type: String,
|
|
33
|
-
default: 'gray-800',
|
|
34
|
-
},
|
|
35
|
-
textColor: {
|
|
36
|
-
type: String,
|
|
37
|
-
default: 'white',
|
|
38
|
-
},
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
const baseClasses = computed(() => ('px-3 py-2 text-sm rounded-lg shadow-lg whitespace-nowrap'))
|
|
42
|
-
|
|
43
|
-
const visible = ref(false)
|
|
44
|
-
|
|
45
|
-
const isHex = (val: string) => val.startsWith('#')
|
|
46
|
-
|
|
47
|
-
const showTooltip = () => {
|
|
48
|
-
visible.value = true
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const hideTooltip = () => {
|
|
52
|
-
visible.value = false
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const tooltipStyle = computed(() => {
|
|
56
|
-
const style: Record<string, string> = {}
|
|
57
|
-
|
|
58
|
-
if (isHex(props.color)) {
|
|
59
|
-
style.backgroundColor = props.color
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (isHex(props.textColor)) {
|
|
63
|
-
style.color = props.textColor
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return style
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
const tooltipClasses = computed(() => [
|
|
70
|
-
baseClasses.value,
|
|
71
|
-
|
|
72
|
-
!isHex(props.color)
|
|
73
|
-
? `bg-${props.color}`
|
|
74
|
-
: '',
|
|
75
|
-
|
|
76
|
-
!isHex(props.textColor)
|
|
77
|
-
? `text-${props.textColor}`
|
|
78
|
-
: '',
|
|
79
|
-
])
|
|
80
|
-
|
|
81
|
-
const placementClasses = computed(() => {
|
|
82
|
-
switch (props.placement) {
|
|
83
|
-
case 'top':
|
|
84
|
-
return 'bottom-full left-1/2 -translate-x-1/2 mb-3'
|
|
85
|
-
|
|
86
|
-
case 'right':
|
|
87
|
-
return 'left-full top-1/2 -translate-y-1/2 ml-3'
|
|
88
|
-
|
|
89
|
-
case 'bottom':
|
|
90
|
-
return 'top-full left-1/2 -translate-x-1/2 mt-3'
|
|
91
|
-
|
|
92
|
-
case 'left':
|
|
93
|
-
return 'right-full top-1/2 -translate-y-1/2 mr-3'
|
|
94
|
-
|
|
95
|
-
default:
|
|
96
|
-
return ''
|
|
97
|
-
}
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
const arrowClasses = computed(() => {
|
|
101
|
-
switch (props.placement) {
|
|
102
|
-
case 'top':
|
|
103
|
-
return 'left-1/2 -translate-x-1/2 bottom-0 -mb-3.5'
|
|
104
|
-
|
|
105
|
-
case 'right':
|
|
106
|
-
return 'top-1/2 -translate-y-1/2 left-0 -ml-3.5'
|
|
107
|
-
|
|
108
|
-
case 'bottom':
|
|
109
|
-
return 'left-1/2 -translate-x-1/2 top-0 -mt-3.5'
|
|
110
|
-
|
|
111
|
-
case 'left':
|
|
112
|
-
return 'top-1/2 -translate-y-1/2 right-0 -mr-3.5'
|
|
113
|
-
|
|
114
|
-
default:
|
|
115
|
-
return ''
|
|
116
|
-
}
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
const arrowIcon = computed(() => {
|
|
120
|
-
switch (props.placement) {
|
|
121
|
-
case 'top':
|
|
122
|
-
return 'arrow_drop_down'
|
|
123
|
-
|
|
124
|
-
case 'right':
|
|
125
|
-
return 'arrow_left'
|
|
126
|
-
|
|
127
|
-
case 'bottom':
|
|
128
|
-
return 'arrow_drop_up'
|
|
129
|
-
|
|
130
|
-
case 'left':
|
|
131
|
-
return 'arrow_right'
|
|
132
|
-
|
|
133
|
-
default:
|
|
134
|
-
return ''
|
|
135
|
-
}
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
const arrowStyle = computed(() => {
|
|
139
|
-
const style: Record<string, string> = {}
|
|
140
|
-
if (isHex(props.color))
|
|
141
|
-
style.color = props.color
|
|
142
|
-
return style
|
|
143
|
-
})
|
|
144
|
-
</script>
|
|
145
|
-
|
|
146
|
-
<template>
|
|
147
|
-
<div
|
|
148
|
-
class="relative inline-block"
|
|
149
|
-
tabindex="0"
|
|
150
|
-
@mouseenter="showTooltip"
|
|
151
|
-
@mouseleave="hideTooltip"
|
|
152
|
-
@focus="showTooltip"
|
|
153
|
-
@blur="hideTooltip"
|
|
154
|
-
>
|
|
155
|
-
<!-- Trigger -->
|
|
156
|
-
<slot />
|
|
157
|
-
|
|
158
|
-
<!-- Tooltip -->
|
|
159
|
-
<transition name="fade">
|
|
160
|
-
<div
|
|
161
|
-
v-if="visible"
|
|
162
|
-
role="tooltip"
|
|
163
|
-
class="absolute z-50"
|
|
164
|
-
:class="[tooltipClasses, placementClasses]"
|
|
165
|
-
:style="tooltipStyle"
|
|
166
|
-
v-bind="$attrs"
|
|
167
|
-
>
|
|
168
|
-
<!-- Arrow -->
|
|
169
|
-
<i
|
|
170
|
-
v-if="arrow"
|
|
171
|
-
class="material-icons tooltip-arrow"
|
|
172
|
-
:class="[ arrowClasses, !isHex(props.color) ? `text-${props.color}` : '', ]"
|
|
173
|
-
:style="arrowStyle"
|
|
174
|
-
>
|
|
175
|
-
{{ arrowIcon }}
|
|
176
|
-
</i>
|
|
177
|
-
|
|
178
|
-
{{ text }}
|
|
179
|
-
</div>
|
|
180
|
-
</transition>
|
|
181
|
-
</div>
|
|
182
|
-
</template>
|
|
183
|
-
|
|
184
|
-
<style scoped>
|
|
185
|
-
.fade-enter-active,
|
|
186
|
-
.fade-leave-active {
|
|
187
|
-
transition: opacity 0.2s ease;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
.fade-enter-from,
|
|
191
|
-
.fade-leave-to {
|
|
192
|
-
opacity: 0;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
.tooltip-arrow {
|
|
196
|
-
position: absolute;
|
|
197
|
-
font-size: 1.5rem;
|
|
198
|
-
line-height: 1;
|
|
199
|
-
}
|
|
200
|
-
</style>
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { defineNuxtPlugin } from '#app'
|
|
2
|
-
import Button from './Button.vue'
|
|
3
|
-
import Accordian from './Accordion.vue'
|
|
4
|
-
|
|
5
|
-
export default defineNuxtPlugin((nuxtApp) => {
|
|
6
|
-
nuxtApp.vueApp.component('UIButton', Button)
|
|
7
|
-
nuxtApp.vueApp.component('UIAccordian', Accordian)
|
|
8
|
-
})
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export const uiProps = {
|
|
2
|
-
contentClass: { type: String, default: "" },
|
|
3
|
-
contentStyle: { type: String, default: "" },
|
|
4
|
-
textColor: { type: String, default: "" },
|
|
5
|
-
disable: { type: Boolean, default: false },
|
|
6
|
-
loading: { type: Boolean, default: false },
|
|
7
|
-
color: { type: String, default: "blue-900" },
|
|
8
|
-
rounded: { type: String, default: "md" },
|
|
9
|
-
size: { type: String, default: "md" },
|
|
10
|
-
iconSize: { type: String, default: "lg" },
|
|
11
|
-
} as const;
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { computed, toRefs } from "vue";
|
|
2
|
-
import type { ExtractPropTypes } from "vue";
|
|
3
|
-
import { uiProps } from "./uiProps";
|
|
4
|
-
|
|
5
|
-
type UiProps = ExtractPropTypes<typeof uiProps>;
|
|
6
|
-
|
|
7
|
-
export function useUiClasses(props: Partial<UiProps>) {
|
|
8
|
-
const safeProps = {
|
|
9
|
-
contentClass: "",
|
|
10
|
-
contentStyle: "",
|
|
11
|
-
textColor: "",
|
|
12
|
-
disable: false,
|
|
13
|
-
loading: false,
|
|
14
|
-
color: "",
|
|
15
|
-
rounded: "md",
|
|
16
|
-
size: "md",
|
|
17
|
-
iconSize: "md",
|
|
18
|
-
...props,
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const {
|
|
22
|
-
contentClass,
|
|
23
|
-
contentStyle,
|
|
24
|
-
textColor,
|
|
25
|
-
disable,
|
|
26
|
-
loading,
|
|
27
|
-
color,
|
|
28
|
-
rounded,
|
|
29
|
-
size,
|
|
30
|
-
iconSize,
|
|
31
|
-
} = toRefs(safeProps);
|
|
32
|
-
|
|
33
|
-
// Classes maps
|
|
34
|
-
const roundedClass = {
|
|
35
|
-
none: "rounded-none",
|
|
36
|
-
xs: "rounded-xs",
|
|
37
|
-
sm: "rounded-sm",
|
|
38
|
-
md: "rounded",
|
|
39
|
-
lg: "rounded-lg",
|
|
40
|
-
xl: "rounded-xl",
|
|
41
|
-
full: "rounded-full",
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const sizeClass = {
|
|
45
|
-
sm: "text-xs",
|
|
46
|
-
md: "text-base",
|
|
47
|
-
lg: "text-xl",
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const iconSizeClasses = {
|
|
51
|
-
xs: "text-xs",
|
|
52
|
-
sm: "text-sm",
|
|
53
|
-
md: "text-base",
|
|
54
|
-
lg: "text-lg",
|
|
55
|
-
xl: "text-xl",
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// Computed for color class
|
|
59
|
-
const colorClass = computed(() => {
|
|
60
|
-
if (!color.value) return "";
|
|
61
|
-
return color.value.includes("#") ? `[${color.value}]` : color.value;
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// Computed for content class with ! prefix
|
|
65
|
-
const computedContentClass = computed(() => {
|
|
66
|
-
if (!contentClass.value) return "";
|
|
67
|
-
return contentClass.value
|
|
68
|
-
.split(" ")
|
|
69
|
-
.map((cls: string) => (cls.startsWith("!") ? cls : `!${cls}`))
|
|
70
|
-
.join(" ");
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
function isTailwindColorDark(color: string): boolean {
|
|
74
|
-
const match = color.match(/-(\d{2,3})$/);
|
|
75
|
-
if (!match) return false;
|
|
76
|
-
return Number(match[1]) >= 400;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function isHexColorDark(hex: string): boolean {
|
|
80
|
-
let c = hex.replace("#", "");
|
|
81
|
-
|
|
82
|
-
if (c.length === 3) {
|
|
83
|
-
c = c.split("").map(x => x + x).join("");
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const r = parseInt(c.substring(0, 2), 16);
|
|
87
|
-
const g = parseInt(c.substring(2, 4), 16);
|
|
88
|
-
const b = parseInt(c.substring(4, 6), 16);
|
|
89
|
-
|
|
90
|
-
const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
|
|
91
|
-
return luminance < 140;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function isHex(color: string) {
|
|
95
|
-
return /^#([0-9A-F]{3}){1,2}$/i.test(color);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function isTailwindColor(color: string) {
|
|
99
|
-
return /^[a-z]+-\d{2,3}$/.test(color);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const isColorDark = (color: string): boolean => {
|
|
103
|
-
if (!color) return false;
|
|
104
|
-
return color.startsWith("#")
|
|
105
|
-
? isHexColorDark(color)
|
|
106
|
-
: isTailwindColorDark(color);
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
function shadeTailwind(color: string, delta = 100) {
|
|
110
|
-
const [name, shade] = color.split("-");
|
|
111
|
-
const nextShade = Math.min(900, Math.max(100, Number(shade) + delta));
|
|
112
|
-
return `${name}-${nextShade}`;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function shadeHex(hex: string, amount = -10) {
|
|
116
|
-
let c = hex.substring(1);
|
|
117
|
-
if (c.length === 3) {
|
|
118
|
-
c = c.split("").map(x => x + x).join("");
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const num = parseInt(c, 16);
|
|
122
|
-
let r = (num >> 16) & 255;
|
|
123
|
-
let g = (num >> 8) & 255;
|
|
124
|
-
let b = num & 255;
|
|
125
|
-
|
|
126
|
-
r = Math.min(255, Math.max(0, r + amount));
|
|
127
|
-
g = Math.min(255, Math.max(0, g + amount));
|
|
128
|
-
b = Math.min(255, Math.max(0, b + amount));
|
|
129
|
-
|
|
130
|
-
return `#${((1 << 24) + (r << 16) + (g << 8) + b)
|
|
131
|
-
.toString(16)
|
|
132
|
-
.slice(1)}`;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return {
|
|
136
|
-
// props
|
|
137
|
-
contentClass,
|
|
138
|
-
contentStyle,
|
|
139
|
-
textColor,
|
|
140
|
-
disable,
|
|
141
|
-
loading,
|
|
142
|
-
color,
|
|
143
|
-
rounded,
|
|
144
|
-
size,
|
|
145
|
-
iconSize,
|
|
146
|
-
// class maps
|
|
147
|
-
roundedClass,
|
|
148
|
-
sizeClass,
|
|
149
|
-
iconSizeClasses,
|
|
150
|
-
// computed
|
|
151
|
-
colorClass,
|
|
152
|
-
computedContentClass,
|
|
153
|
-
isColorDark,
|
|
154
|
-
isHex,
|
|
155
|
-
isTailwindColor,
|
|
156
|
-
shadeTailwind,
|
|
157
|
-
shadeHex
|
|
158
|
-
};
|
|
159
|
-
}
|
package/ui-library/module.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { defineNuxtModule, addComponentsDir, createResolver } from '@nuxt/kit'
|
|
2
|
-
|
|
3
|
-
export default defineNuxtModule({
|
|
4
|
-
meta: {
|
|
5
|
-
name: 'ui-library',
|
|
6
|
-
configKey: 'uiLibrary'
|
|
7
|
-
},
|
|
8
|
-
setup(_, nuxt) {
|
|
9
|
-
const resolver = createResolver(import.meta.url)
|
|
10
|
-
|
|
11
|
-
// Auto-register all components from the ui-library/components folder
|
|
12
|
-
addComponentsDir({
|
|
13
|
-
path: resolver.resolve('./components'),
|
|
14
|
-
prefix: 'UI', // This will prefix components with <UIButton />, <UICard /> etc.
|
|
15
|
-
pathPrefix: false, // Don't include folder names as prefix
|
|
16
|
-
extensions: ['vue'],
|
|
17
|
-
watch: nuxt.options.dev
|
|
18
|
-
})
|
|
19
|
-
}
|
|
20
|
-
})
|