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.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -33
  3. package/package.json +47 -15
  4. package/ui-library/dist/module.d.mts +3 -0
  5. package/ui-library/dist/module.json +8 -0
  6. package/ui-library/dist/module.mjs +22 -0
  7. package/ui-library/dist/types.d.mts +7 -0
  8. package/ui-library/components/Accordion.vue +0 -118
  9. package/ui-library/components/Avatar.vue +0 -121
  10. package/ui-library/components/Badge.vue +0 -116
  11. package/ui-library/components/Breadcrumbs.vue +0 -138
  12. package/ui-library/components/Button.vue +0 -154
  13. package/ui-library/components/Card.vue +0 -84
  14. package/ui-library/components/Checkbox.vue +0 -148
  15. package/ui-library/components/CodeBlock.vue +0 -99
  16. package/ui-library/components/ColorPicker.vue +0 -302
  17. package/ui-library/components/Date.vue +0 -240
  18. package/ui-library/components/Dialog.vue +0 -187
  19. package/ui-library/components/Divider.vue +0 -78
  20. package/ui-library/components/Drawer.vue +0 -67
  21. package/ui-library/components/Dropdown.vue +0 -248
  22. package/ui-library/components/FileUploader.vue +0 -330
  23. package/ui-library/components/Icon.vue +0 -82
  24. package/ui-library/components/Image.vue +0 -78
  25. package/ui-library/components/Input.vue +0 -531
  26. package/ui-library/components/Radio.vue +0 -356
  27. package/ui-library/components/ScrollArea.vue +0 -43
  28. package/ui-library/components/Select.vue +0 -309
  29. package/ui-library/components/Stepper.vue +0 -361
  30. package/ui-library/components/TabPanel.vue +0 -25
  31. package/ui-library/components/Table.vue +0 -152
  32. package/ui-library/components/Tabs.vue +0 -71
  33. package/ui-library/components/Textarea.vue +0 -233
  34. package/ui-library/components/Toggle.vue +0 -319
  35. package/ui-library/components/Tooltip.vue +0 -200
  36. package/ui-library/components/plugin.ts +0 -8
  37. package/ui-library/components/uiProps.ts +0 -11
  38. package/ui-library/components/useUiClasses.ts +0 -159
  39. package/ui-library/module.ts +0 -20
@@ -1,187 +0,0 @@
1
- <template>
2
- <transition name="fade">
3
- <div
4
- v-if="isOpen"
5
- class="fixed inset-0 z-50 flex bg-black bg-opacity-60"
6
- role="dialog"
7
- aria-modal="true"
8
- @click.self="handleOutsideClick"
9
- :class="positionClasses"
10
- >
11
- <div class="bg-white rounded-lg shadow-lg w-96 p-6">
12
- <!-- Header -->
13
- <div class="flex justify-between items-center mb-4">
14
- <slot name="title">
15
- <h3 class="text-lg font-semibold">
16
- {{ title }}
17
- </h3>
18
- </slot>
19
-
20
- <button
21
- v-if="showCloseIcon"
22
- @click="close"
23
- class="text-gray-500 hover:text-gray-700"
24
- aria-label="Close modal"
25
- >
26
- <span class="material-icons">close</span>
27
- </button>
28
- </div>
29
-
30
- <!-- Message -->
31
- <slot name="message">
32
- <p class="text-gray-600 mb-6">
33
- {{ message }}
34
- </p>
35
- </slot>
36
-
37
- <!-- Actions -->
38
- <div class="flex justify-end">
39
- <button
40
- @click="close"
41
- class="mr-2 px-4 py-2 bg-gray-200 text-gray-700 rounded-lg transition hover:bg-gray-300"
42
- >
43
- {{ cancelBtnText }}
44
- </button>
45
-
46
- <button
47
- v-if="showConfirmBtn"
48
- @click="handleConfirm"
49
- class="px-4 py-2 bg-blue-500 text-white rounded-lg transition hover:bg-blue-600"
50
- >
51
- {{ confirmBtnText }}
52
- </button>
53
- </div>
54
- </div>
55
- </div>
56
- </transition>
57
- </template>
58
-
59
- <script setup>
60
- import { computed, watch, onBeforeUnmount } from 'vue';
61
- import { useRouter } from 'vue-router';
62
-
63
- const props = defineProps({
64
- isOpen: {
65
- type: Boolean,
66
- required: true,
67
- },
68
- title: {
69
- type: String,
70
- default: 'Modal Title',
71
- },
72
- message: {
73
- type: String,
74
- default: '',
75
- },
76
- confirmBtnText: {
77
- type: String,
78
- default: 'Confirm',
79
- },
80
- cancelBtnText: {
81
- type: String,
82
- default: 'Cancel',
83
- },
84
- showConfirmBtn: {
85
- type: Boolean,
86
- default: false,
87
- },
88
- showCloseIcon: {
89
- type: Boolean,
90
- default: false,
91
- },
92
- persistent: {
93
- type: Boolean,
94
- default: false,
95
- },
96
- position: {
97
- type: String,
98
- default: 'center',
99
- validator: (val) =>
100
- ['center', 'top', 'bottom', 'left', 'right'].includes(val),
101
- },
102
- });
103
-
104
- const emit = defineEmits(['update:isOpen', 'confirm']);
105
- const router = useRouter();
106
-
107
- const close = () => emit('update:isOpen', false);
108
-
109
- const handleConfirm = () => {
110
- emit('confirm');
111
- close();
112
- };
113
-
114
- const handleOutsideClick = () => {
115
- if (!props.persistent) close();
116
- };
117
-
118
- const handleEscKey = (event) => {
119
- if (event.key === 'Escape' && !props.persistent) {
120
- close();
121
- }
122
- };
123
-
124
- const positionClasses = computed(() => {
125
- switch (props.position) {
126
- case 'top':
127
- return 'items-start justify-center p-6';
128
- case 'bottom':
129
- return 'items-end justify-center p-6';
130
- case 'left':
131
- return 'items-center justify-start p-6';
132
- case 'right':
133
- return 'items-center justify-end p-6';
134
- default:
135
- return 'items-center justify-center p-6';
136
- }
137
- });
138
-
139
- /* Handle ESC key */
140
- watch(
141
- () => props.isOpen,
142
- (open) => {
143
- if (open) {
144
- document.addEventListener('keydown', handleEscKey);
145
- } else {
146
- document.removeEventListener('keydown', handleEscKey);
147
- }
148
- }
149
- );
150
-
151
- /* Close modal on route change */
152
- const removeGuard = router.beforeEach((to, from, next) => {
153
- if (props.isOpen && !props.persistent) close();
154
- next();
155
- });
156
-
157
- onBeforeUnmount(() => {
158
- document.removeEventListener('keydown', handleEscKey);
159
- removeGuard?.();
160
- });
161
- </script>
162
-
163
- <style scoped>
164
- .fade-enter-active {
165
- animation: fadeInScale 0.3s ease forwards;
166
- }
167
-
168
- .fade-leave-active {
169
- transition: opacity 0.3s ease, transform 0.3s ease;
170
- }
171
-
172
- @keyframes fadeInScale {
173
- from {
174
- opacity: 0;
175
- transform: scale(0.9);
176
- }
177
- to {
178
- opacity: 1;
179
- transform: scale(1);
180
- }
181
- }
182
-
183
- .fade-leave-to {
184
- opacity: 0;
185
- transform: scale(0.9);
186
- }
187
- </style>
@@ -1,78 +0,0 @@
1
- <script setup lang="ts">
2
- defineOptions({
3
- inheritAttrs: false,
4
- })
5
-
6
- import { computed } from 'vue'
7
-
8
- const props = defineProps({
9
- color: {
10
- type: String,
11
- default: 'gray-300',
12
- },
13
-
14
- type: {
15
- type: String,
16
- default: 'solid',
17
- },
18
-
19
- vertical: {
20
- type: Boolean,
21
- default: false,
22
- },
23
-
24
- inset: {
25
- type: Boolean,
26
- default: false,
27
- },
28
-
29
- thickness: {
30
- type: String,
31
- default: '1px',
32
- },
33
- })
34
-
35
- const isHex = (val: string) => val.startsWith('#')
36
-
37
- const dividerStyle = computed(() => {
38
- const style: Record<string, string> = {}
39
-
40
- if (isHex(props.color)) {
41
- style.borderColor = props.color
42
- }
43
-
44
- style.borderWidth = props.thickness
45
-
46
- return style
47
- })
48
-
49
- const dividerClass = computed(() => [
50
- props.vertical
51
- ? 'h-full border-l'
52
- : 'w-full border-t',
53
-
54
- props.type === 'dashed'
55
- ? 'border-dashed'
56
- : '',
57
-
58
- props.type === 'dotted'
59
- ? 'border-dotted'
60
- : '',
61
-
62
- props.inset
63
- ? 'mx-4'
64
- : '',
65
-
66
- !isHex(props.color)
67
- ? `border-${props.color}`
68
- : '',
69
- ])
70
- </script>
71
-
72
- <template>
73
- <div
74
- :class="dividerClass"
75
- :style="dividerStyle"
76
- v-bind="$attrs"
77
- />
78
- </template>
@@ -1,67 +0,0 @@
1
- <script setup lang="ts">
2
- defineOptions({
3
- name: 'UIDrawer',
4
- })
5
-
6
- type DrawerDirection = 'left' | 'right'
7
-
8
- interface Props {
9
- isOpen: boolean
10
- direction?: DrawerDirection
11
- background?: string
12
- width?: string
13
- padding?: string
14
- }
15
-
16
- withDefaults(defineProps<Props>(), {
17
- direction: 'right',
18
- background: 'bg-white dark:bg-gray-900',
19
- width: 'w-80',
20
- padding: 'p-6',
21
- })
22
-
23
- const emit = defineEmits<{
24
- close: []
25
- }>()
26
- </script>
27
-
28
- <template>
29
- <div
30
- class="fixed inset-0 z-40 bg-black/40 transition-opacity duration-300"
31
- :class="[
32
- isOpen
33
- ? 'opacity-100 visible'
34
- : 'opacity-0 invisible',
35
- ]"
36
- @click="emit('close')"
37
- />
38
-
39
- <div
40
- class="fixed top-0 bottom-0 z-50 shadow-2xl transition-transform duration-500 ease-in-out"
41
- :class="[
42
- width,
43
- padding,
44
- background,
45
- direction === 'left'
46
- ? 'left-0'
47
- : 'right-0',
48
-
49
- direction === 'left'
50
- ? isOpen
51
- ? 'translate-x-0'
52
- : '-translate-x-full'
53
- : isOpen
54
- ? 'translate-x-0'
55
- : 'translate-x-full',
56
- ]"
57
- >
58
- <button
59
- class="absolute top-4 right-4 text-xl font-bold"
60
- @click="emit('close')"
61
- >
62
-
63
- </button>
64
-
65
- <slot />
66
- </div>
67
- </template>
@@ -1,248 +0,0 @@
1
- <script setup lang="ts">
2
- defineOptions({
3
- name: 'UIDropdown',
4
- })
5
-
6
- import {
7
- computed,
8
- onBeforeUnmount,
9
- onMounted,
10
- ref,
11
- } from 'vue'
12
-
13
- type DropdownAlign =
14
- | 'left'
15
- | 'right'
16
-
17
- type Rounded =
18
- | 'none'
19
- | 'sm'
20
- | 'md'
21
- | 'lg'
22
- | 'xl'
23
- | 'full'
24
-
25
- const props = withDefaults(
26
- defineProps<{
27
- align?: DropdownAlign
28
-
29
- width?: string
30
-
31
- menuBgClass?: string
32
-
33
- rounded?: Rounded
34
-
35
- bordered?: boolean
36
-
37
- borderColor?: string
38
-
39
- flat?: boolean
40
- }>(),
41
- {
42
- align: 'left',
43
-
44
- width: 'w-48',
45
-
46
- menuBgClass:
47
- 'bg-white dark:bg-gray-800',
48
-
49
- rounded: 'xl',
50
-
51
- bordered: false,
52
-
53
- borderColor: 'gray-200',
54
-
55
- flat: false,
56
- },
57
- )
58
-
59
- const isOpen = ref(false)
60
-
61
- const dropdownRef =
62
- ref<HTMLElement | null>(null)
63
-
64
- const isHex = (
65
- val: string,
66
- ): boolean => {
67
- return (
68
- val.startsWith('#') ||
69
- val.startsWith('rgb') ||
70
- val.startsWith('hsl')
71
- )
72
- }
73
-
74
- const toggle = (): void => {
75
- isOpen.value = !isOpen.value
76
- }
77
-
78
- const close = (): void => {
79
- isOpen.value = false
80
- }
81
-
82
- const handleClickOutside = (
83
- event: MouseEvent,
84
- ): void => {
85
- const target =
86
- event.target as Node
87
-
88
- if (
89
- dropdownRef.value &&
90
- !dropdownRef.value.contains(
91
- target,
92
- )
93
- ) {
94
- close()
95
- }
96
- }
97
-
98
- onMounted(() => {
99
- document.addEventListener(
100
- 'click',
101
- handleClickOutside,
102
- )
103
- })
104
-
105
- onBeforeUnmount(() => {
106
- document.removeEventListener(
107
- 'click',
108
- handleClickOutside,
109
- )
110
- })
111
-
112
- const roundedClass = computed(
113
- () => {
114
- const map: Record<
115
- Rounded,
116
- string
117
- > = {
118
- none: 'rounded-none',
119
-
120
- sm: 'rounded-sm',
121
-
122
- md: 'rounded-md',
123
-
124
- lg: 'rounded-lg',
125
-
126
- xl: 'rounded-xl',
127
-
128
- full: 'rounded-full',
129
- }
130
-
131
- return map[props.rounded]
132
- },
133
- )
134
-
135
- const dropdownClasses =
136
- computed(() => [
137
- 'absolute mt-2 z-50 transition-all overflow-hidden',
138
-
139
- props.align === 'right'
140
- ? 'right-0'
141
- : 'left-0',
142
-
143
- props.width,
144
-
145
- roundedClass.value,
146
-
147
- props.bordered &&
148
- !isHex(props.borderColor)
149
- ? `border border-${props.borderColor}`
150
- : '',
151
-
152
- props.flat
153
- ? 'shadow-none'
154
- : 'shadow-lg',
155
- ])
156
-
157
- const dropdownStyle = computed(
158
- () => {
159
- const style: Record<
160
- string,
161
- string
162
- > = {}
163
-
164
- if (
165
- props.bordered &&
166
- isHex(props.borderColor)
167
- ) {
168
- style.border =
169
- `1px solid ${props.borderColor}`
170
- }
171
-
172
- return style
173
- },
174
- )
175
-
176
- const menuClasses = computed(
177
- () => [
178
- 'p-2',
179
-
180
- roundedClass.value,
181
-
182
- props.menuBgClass,
183
- ],
184
- )
185
- </script>
186
-
187
- <template>
188
- <div
189
- ref="dropdownRef"
190
- class="relative inline-block"
191
- >
192
- <!-- Trigger -->
193
- <div @click="toggle">
194
- <slot name="trigger" />
195
- </div>
196
-
197
- <!-- Dropdown -->
198
- <transition
199
- name="fade-slide"
200
- >
201
- <div
202
- v-if="isOpen"
203
- :class="
204
- dropdownClasses
205
- "
206
- :style="
207
- dropdownStyle
208
- "
209
- >
210
- <div
211
- :class="
212
- menuClasses
213
- "
214
- >
215
- <slot name="menu" />
216
- </div>
217
- </div>
218
- </transition>
219
- </div>
220
- </template>
221
-
222
- <style scoped>
223
- .fade-slide-enter-active,
224
- .fade-slide-leave-active {
225
- transition:
226
- all 200ms ease;
227
- }
228
-
229
- .fade-slide-enter-from {
230
- opacity: 0;
231
- transform: translateY(-8px);
232
- }
233
-
234
- .fade-slide-enter-to {
235
- opacity: 1;
236
- transform: translateY(0);
237
- }
238
-
239
- .fade-slide-leave-from {
240
- opacity: 1;
241
- transform: translateY(0);
242
- }
243
-
244
- .fade-slide-leave-to {
245
- opacity: 0;
246
- transform: translateY(-8px);
247
- }
248
- </style>