windly-ui 1.0.2 → 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 (100) hide show
  1. package/{ui-library/dist → dist}/module.json +2 -2
  2. package/dist/module.mjs +26 -0
  3. package/dist/runtime/components/Accordion.d.vue.ts +39 -0
  4. package/dist/runtime/components/Accordion.vue +92 -0
  5. package/dist/runtime/components/Accordion.vue.d.ts +39 -0
  6. package/dist/runtime/components/Avatar.d.vue.ts +141 -0
  7. package/dist/runtime/components/Avatar.vue +72 -0
  8. package/dist/runtime/components/Avatar.vue.d.ts +141 -0
  9. package/dist/runtime/components/Badge.d.vue.ts +133 -0
  10. package/dist/runtime/components/Badge.vue +99 -0
  11. package/dist/runtime/components/Badge.vue.d.ts +133 -0
  12. package/dist/runtime/components/Breadcrumbs.d.vue.ts +83 -0
  13. package/dist/runtime/components/Breadcrumbs.vue +116 -0
  14. package/dist/runtime/components/Breadcrumbs.vue.d.ts +83 -0
  15. package/dist/runtime/components/Button.d.vue.ts +199 -0
  16. package/dist/runtime/components/Button.vue +125 -0
  17. package/dist/runtime/components/Button.vue.d.ts +199 -0
  18. package/dist/runtime/components/Card.d.vue.ts +83 -0
  19. package/dist/runtime/components/Card.vue +71 -0
  20. package/dist/runtime/components/Card.vue.d.ts +83 -0
  21. package/dist/runtime/components/Checkbox.d.vue.ts +190 -0
  22. package/dist/runtime/components/Checkbox.vue +125 -0
  23. package/dist/runtime/components/Checkbox.vue.d.ts +190 -0
  24. package/dist/runtime/components/CodeBlock.d.vue.ts +16 -0
  25. package/dist/runtime/components/CodeBlock.vue +75 -0
  26. package/dist/runtime/components/CodeBlock.vue.d.ts +16 -0
  27. package/dist/runtime/components/ColorPicker.d.vue.ts +91 -0
  28. package/dist/runtime/components/ColorPicker.vue +244 -0
  29. package/dist/runtime/components/ColorPicker.vue.d.ts +91 -0
  30. package/dist/runtime/components/Date.d.vue.ts +137 -0
  31. package/dist/runtime/components/Date.vue +201 -0
  32. package/dist/runtime/components/Date.vue.d.ts +137 -0
  33. package/dist/runtime/components/Dialog.d.vue.ts +103 -0
  34. package/dist/runtime/components/Dialog.vue +152 -0
  35. package/dist/runtime/components/Dialog.vue.d.ts +103 -0
  36. package/dist/runtime/components/Divider.d.vue.ts +51 -0
  37. package/dist/runtime/components/Divider.vue +52 -0
  38. package/dist/runtime/components/Divider.vue.d.ts +51 -0
  39. package/dist/runtime/components/Drawer.d.vue.ts +30 -0
  40. package/dist/runtime/components/Drawer.vue +43 -0
  41. package/dist/runtime/components/Drawer.vue.d.ts +30 -0
  42. package/dist/runtime/components/Dropdown.d.vue.ts +34 -0
  43. package/dist/runtime/components/Dropdown.vue +127 -0
  44. package/dist/runtime/components/Dropdown.vue.d.ts +34 -0
  45. package/dist/runtime/components/FileUploader.d.vue.ts +58 -0
  46. package/dist/runtime/components/FileUploader.vue +202 -0
  47. package/dist/runtime/components/FileUploader.vue.d.ts +58 -0
  48. package/dist/runtime/components/Icon.d.vue.ts +41 -0
  49. package/dist/runtime/components/Icon.vue +66 -0
  50. package/dist/runtime/components/Icon.vue.d.ts +41 -0
  51. package/dist/runtime/components/Image.d.vue.ts +77 -0
  52. package/dist/runtime/components/Image.vue +61 -0
  53. package/dist/runtime/components/Image.vue.d.ts +77 -0
  54. package/dist/runtime/components/Input.d.vue.ts +66 -0
  55. package/dist/runtime/components/Input.vue +233 -0
  56. package/dist/runtime/components/Input.vue.d.ts +66 -0
  57. package/dist/runtime/components/Radio.d.vue.ts +41 -0
  58. package/dist/runtime/components/Radio.vue +222 -0
  59. package/dist/runtime/components/Radio.vue.d.ts +41 -0
  60. package/dist/runtime/components/ScrollArea.d.vue.ts +79 -0
  61. package/dist/runtime/components/ScrollArea.vue +36 -0
  62. package/dist/runtime/components/ScrollArea.vue.d.ts +79 -0
  63. package/dist/runtime/components/Select.d.vue.ts +43 -0
  64. package/dist/runtime/components/Select.vue +200 -0
  65. package/dist/runtime/components/Select.vue.d.ts +43 -0
  66. package/dist/runtime/components/Stepper.d.vue.ts +46 -0
  67. package/dist/runtime/components/Stepper.vue +218 -0
  68. package/dist/runtime/components/Stepper.vue.d.ts +46 -0
  69. package/dist/runtime/components/TabPanel.d.vue.ts +17 -0
  70. package/dist/runtime/components/TabPanel.vue +21 -0
  71. package/dist/runtime/components/TabPanel.vue.d.ts +17 -0
  72. package/dist/runtime/components/Table.d.vue.ts +40 -0
  73. package/dist/runtime/components/Table.vue +92 -0
  74. package/dist/runtime/components/Table.vue.d.ts +40 -0
  75. package/dist/runtime/components/Tabs.d.vue.ts +20 -0
  76. package/dist/runtime/components/Tabs.vue +62 -0
  77. package/dist/runtime/components/Tabs.vue.d.ts +20 -0
  78. package/dist/runtime/components/Textarea.d.vue.ts +208 -0
  79. package/dist/runtime/components/Textarea.vue +185 -0
  80. package/dist/runtime/components/Textarea.vue.d.ts +208 -0
  81. package/dist/runtime/components/Toggle.d.vue.ts +36 -0
  82. package/dist/runtime/components/Toggle.vue +173 -0
  83. package/dist/runtime/components/Toggle.vue.d.ts +36 -0
  84. package/dist/runtime/components/Tooltip.d.vue.ts +63 -0
  85. package/dist/runtime/components/Tooltip.vue +144 -0
  86. package/dist/runtime/components/Tooltip.vue.d.ts +63 -0
  87. package/dist/runtime/components/uiProps.d.ts +38 -0
  88. package/dist/runtime/components/uiProps.js +11 -0
  89. package/dist/runtime/components/useUiClasses.d.ts +43 -0
  90. package/dist/runtime/components/useUiClasses.js +124 -0
  91. package/dist/runtime/composables/plugin.d.ts +2 -0
  92. package/dist/runtime/composables/plugin.js +3 -0
  93. package/dist/runtime/tailwind-color.d.ts +2 -0
  94. package/dist/runtime/tailwind-color.js +5859 -0
  95. package/package.json +12 -46
  96. package/LICENSE +0 -21
  97. package/README.md +0 -232
  98. package/ui-library/dist/module.mjs +0 -22
  99. /package/{ui-library/dist → dist}/module.d.mts +0 -0
  100. /package/{ui-library/dist → dist}/types.d.mts +0 -0
@@ -0,0 +1,43 @@
1
+ <script setup>
2
+ defineOptions({
3
+ name: "UIDrawer"
4
+ });
5
+ defineProps({
6
+ isOpen: { type: Boolean, required: true },
7
+ direction: { type: String, required: false, default: "right" },
8
+ background: { type: String, required: false, default: "bg-white dark:bg-gray-900" },
9
+ width: { type: String, required: false, default: "w-80" },
10
+ padding: { type: String, required: false, default: "p-6" }
11
+ });
12
+ const emit = defineEmits(["close"]);
13
+ </script>
14
+
15
+ <template>
16
+ <div
17
+ class="fixed inset-0 z-40 bg-black/40 transition-opacity duration-300"
18
+ :class="[
19
+ isOpen ? 'opacity-100 visible' : 'opacity-0 invisible'
20
+ ]"
21
+ @click="emit('close')"
22
+ />
23
+
24
+ <div
25
+ class="fixed top-0 bottom-0 z-50 shadow-2xl transition-transform duration-500 ease-in-out"
26
+ :class="[
27
+ width,
28
+ padding,
29
+ background,
30
+ direction === 'left' ? 'left-0' : 'right-0',
31
+ direction === 'left' ? isOpen ? 'translate-x-0' : '-translate-x-full' : isOpen ? 'translate-x-0' : 'translate-x-full'
32
+ ]"
33
+ >
34
+ <button
35
+ class="absolute top-4 right-4 text-xl font-bold"
36
+ @click="emit('close')"
37
+ >
38
+
39
+ </button>
40
+
41
+ <slot />
42
+ </div>
43
+ </template>
@@ -0,0 +1,30 @@
1
+ type DrawerDirection = 'left' | 'right';
2
+ interface Props {
3
+ isOpen: boolean;
4
+ direction?: DrawerDirection;
5
+ background?: string;
6
+ width?: string;
7
+ padding?: string;
8
+ }
9
+ declare var __VLS_1: {};
10
+ type __VLS_Slots = {} & {
11
+ default?: (props: typeof __VLS_1) => any;
12
+ };
13
+ declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
14
+ close: () => any;
15
+ }, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
16
+ onClose?: (() => any) | undefined;
17
+ }>, {
18
+ width: string;
19
+ background: string;
20
+ direction: DrawerDirection;
21
+ padding: string;
22
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
23
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
24
+ declare const _default: typeof __VLS_export;
25
+ export default _default;
26
+ type __VLS_WithSlots<T, S> = T & {
27
+ new (): {
28
+ $slots: S;
29
+ };
30
+ };
@@ -0,0 +1,34 @@
1
+ type DropdownAlign = 'left' | 'right';
2
+ type Rounded = 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
3
+ type __VLS_Props = {
4
+ align?: DropdownAlign;
5
+ width?: string;
6
+ menuBgClass?: string;
7
+ rounded?: Rounded;
8
+ bordered?: boolean;
9
+ borderColor?: string;
10
+ flat?: boolean;
11
+ };
12
+ declare var __VLS_1: {}, __VLS_9: {};
13
+ type __VLS_Slots = {} & {
14
+ trigger?: (props: typeof __VLS_1) => any;
15
+ } & {
16
+ menu?: (props: typeof __VLS_9) => any;
17
+ };
18
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
19
+ rounded: Rounded;
20
+ borderColor: string;
21
+ align: DropdownAlign;
22
+ flat: boolean;
23
+ bordered: boolean;
24
+ width: string;
25
+ menuBgClass: string;
26
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
28
+ declare const _default: typeof __VLS_export;
29
+ export default _default;
30
+ type __VLS_WithSlots<T, S> = T & {
31
+ new (): {
32
+ $slots: S;
33
+ };
34
+ };
@@ -0,0 +1,127 @@
1
+ <script setup>
2
+ defineOptions({
3
+ name: "UIDropdown"
4
+ });
5
+ import {
6
+ computed,
7
+ onBeforeUnmount,
8
+ onMounted,
9
+ ref
10
+ } from "vue";
11
+ const props = defineProps({
12
+ align: { type: String, required: false, default: "left" },
13
+ width: { type: String, required: false, default: "w-48" },
14
+ menuBgClass: { type: String, required: false, default: "bg-white dark:bg-gray-800" },
15
+ rounded: { type: String, required: false, default: "xl" },
16
+ bordered: { type: Boolean, required: false, default: false },
17
+ borderColor: { type: String, required: false, default: "gray-200" },
18
+ flat: { type: Boolean, required: false, default: false }
19
+ });
20
+ const isOpen = ref(false);
21
+ const dropdownRef = ref(null);
22
+ const isHex = (val) => {
23
+ return val.startsWith("#") || val.startsWith("rgb") || val.startsWith("hsl");
24
+ };
25
+ const toggle = () => {
26
+ isOpen.value = !isOpen.value;
27
+ };
28
+ const close = () => {
29
+ isOpen.value = false;
30
+ };
31
+ const handleClickOutside = (event) => {
32
+ const target = event.target;
33
+ if (dropdownRef.value && !dropdownRef.value.contains(
34
+ target
35
+ )) {
36
+ close();
37
+ }
38
+ };
39
+ onMounted(() => {
40
+ document.addEventListener(
41
+ "click",
42
+ handleClickOutside
43
+ );
44
+ });
45
+ onBeforeUnmount(() => {
46
+ document.removeEventListener(
47
+ "click",
48
+ handleClickOutside
49
+ );
50
+ });
51
+ const roundedClass = computed(
52
+ () => {
53
+ const map = {
54
+ none: "rounded-none",
55
+ sm: "rounded-sm",
56
+ md: "rounded-md",
57
+ lg: "rounded-lg",
58
+ xl: "rounded-xl",
59
+ full: "rounded-full"
60
+ };
61
+ return map[props.rounded];
62
+ }
63
+ );
64
+ const dropdownClasses = computed(() => [
65
+ "absolute mt-2 z-50 transition-all overflow-hidden",
66
+ props.align === "right" ? "right-0" : "left-0",
67
+ props.width,
68
+ roundedClass.value,
69
+ props.bordered && !isHex(props.borderColor) ? `border border-${props.borderColor}` : "",
70
+ props.flat ? "shadow-none" : "shadow-lg"
71
+ ]);
72
+ const dropdownStyle = computed(
73
+ () => {
74
+ const style = {};
75
+ if (props.bordered && isHex(props.borderColor)) {
76
+ style.border = `1px solid ${props.borderColor}`;
77
+ }
78
+ return style;
79
+ }
80
+ );
81
+ const menuClasses = computed(
82
+ () => [
83
+ "p-2",
84
+ roundedClass.value,
85
+ props.menuBgClass
86
+ ]
87
+ );
88
+ </script>
89
+
90
+ <template>
91
+ <div
92
+ ref="dropdownRef"
93
+ class="relative inline-block"
94
+ >
95
+ <!-- Trigger -->
96
+ <div @click="toggle">
97
+ <slot name="trigger" />
98
+ </div>
99
+
100
+ <!-- Dropdown -->
101
+ <transition
102
+ name="fade-slide"
103
+ >
104
+ <div
105
+ v-if="isOpen"
106
+ :class="
107
+ dropdownClasses
108
+ "
109
+ :style="
110
+ dropdownStyle
111
+ "
112
+ >
113
+ <div
114
+ :class="
115
+ menuClasses
116
+ "
117
+ >
118
+ <slot name="menu" />
119
+ </div>
120
+ </div>
121
+ </transition>
122
+ </div>
123
+ </template>
124
+
125
+ <style scoped>
126
+ .fade-slide-enter-active,.fade-slide-leave-active{transition:all .2s ease}.fade-slide-enter-from{opacity:0;transform:translateY(-8px)}.fade-slide-enter-to,.fade-slide-leave-from{opacity:1;transform:translateY(0)}.fade-slide-leave-to{opacity:0;transform:translateY(-8px)}
127
+ </style>
@@ -0,0 +1,34 @@
1
+ type DropdownAlign = 'left' | 'right';
2
+ type Rounded = 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
3
+ type __VLS_Props = {
4
+ align?: DropdownAlign;
5
+ width?: string;
6
+ menuBgClass?: string;
7
+ rounded?: Rounded;
8
+ bordered?: boolean;
9
+ borderColor?: string;
10
+ flat?: boolean;
11
+ };
12
+ declare var __VLS_1: {}, __VLS_9: {};
13
+ type __VLS_Slots = {} & {
14
+ trigger?: (props: typeof __VLS_1) => any;
15
+ } & {
16
+ menu?: (props: typeof __VLS_9) => any;
17
+ };
18
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
19
+ rounded: Rounded;
20
+ borderColor: string;
21
+ align: DropdownAlign;
22
+ flat: boolean;
23
+ bordered: boolean;
24
+ width: string;
25
+ menuBgClass: string;
26
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
28
+ declare const _default: typeof __VLS_export;
29
+ export default _default;
30
+ type __VLS_WithSlots<T, S> = T & {
31
+ new (): {
32
+ $slots: S;
33
+ };
34
+ };
@@ -0,0 +1,58 @@
1
+ interface UploadedFile {
2
+ file: File;
3
+ name: string;
4
+ size: number;
5
+ type: string;
6
+ }
7
+ type Separator = 'solid' | 'dashed' | 'dotted';
8
+ type Rounded = 'none' | 'sm' | 'md' | 'lg' | 'xl';
9
+ type __VLS_Props = {
10
+ modelValue?: UploadedFile[];
11
+ header?: string;
12
+ subHeader?: string;
13
+ fileType?: string;
14
+ multiple?: boolean;
15
+ disabled?: boolean;
16
+ bordered?: boolean;
17
+ flat?: boolean;
18
+ rounded?: Rounded;
19
+ borderColor?: string;
20
+ bgColor?: string;
21
+ separator?: Separator;
22
+ dense?: boolean;
23
+ fileRemoverIcon?: string;
24
+ fileSizeLimitKb?: number;
25
+ };
26
+ declare var __VLS_1: {};
27
+ type __VLS_Slots = {} & {
28
+ content?: (props: typeof __VLS_1) => any;
29
+ };
30
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
31
+ "update:modelValue": (value: UploadedFile[]) => any;
32
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
33
+ "onUpdate:modelValue"?: ((value: UploadedFile[]) => any) | undefined;
34
+ }>, {
35
+ modelValue: UploadedFile[];
36
+ disabled: boolean;
37
+ dense: boolean;
38
+ header: string;
39
+ rounded: Rounded;
40
+ borderColor: string;
41
+ separator: Separator;
42
+ flat: boolean;
43
+ bordered: boolean;
44
+ subHeader: string;
45
+ fileType: string;
46
+ multiple: boolean;
47
+ bgColor: string;
48
+ fileRemoverIcon: string;
49
+ fileSizeLimitKb: number;
50
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
51
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
52
+ declare const _default: typeof __VLS_export;
53
+ export default _default;
54
+ type __VLS_WithSlots<T, S> = T & {
55
+ new (): {
56
+ $slots: S;
57
+ };
58
+ };
@@ -0,0 +1,202 @@
1
+ <script setup>
2
+ import { computed, ref } from "vue";
3
+ defineOptions({
4
+ name: "UIFileUploader"
5
+ });
6
+ const props = defineProps({
7
+ modelValue: { type: Array, required: false, default: () => [] },
8
+ header: { type: String, required: false, default: "Upload Files" },
9
+ subHeader: { type: String, required: false, default: "Supports document uploads" },
10
+ fileType: { type: String, required: false, default: "*" },
11
+ multiple: { type: Boolean, required: false, default: true },
12
+ disabled: { type: Boolean, required: false, default: false },
13
+ bordered: { type: Boolean, required: false, default: true },
14
+ flat: { type: Boolean, required: false, default: false },
15
+ rounded: { type: String, required: false, default: "xl" },
16
+ borderColor: { type: String, required: false, default: "gray-300" },
17
+ bgColor: { type: String, required: false, default: "white" },
18
+ separator: { type: String, required: false, default: "dashed" },
19
+ dense: { type: Boolean, required: false, default: false },
20
+ fileRemoverIcon: { type: String, required: false, default: "delete" },
21
+ fileSizeLimitKb: { type: Number, required: false, default: 2048 }
22
+ });
23
+ const emit = defineEmits(["update:modelValue"]);
24
+ const fileInput = ref(
25
+ null
26
+ );
27
+ const errorMessage = ref("");
28
+ const files = computed({
29
+ get: () => props.modelValue,
30
+ set: (value) => emit(
31
+ "update:modelValue",
32
+ value
33
+ )
34
+ });
35
+ const isHex = (val) => val.startsWith("#");
36
+ const roundedClasses = computed(
37
+ () => {
38
+ const map = {
39
+ none: "",
40
+ sm: "rounded-sm",
41
+ md: "rounded-md",
42
+ lg: "rounded-lg",
43
+ xl: "rounded-xl"
44
+ };
45
+ return map[props.rounded];
46
+ }
47
+ );
48
+ const separatorClasses = computed(
49
+ () => {
50
+ switch (props.separator) {
51
+ case "solid":
52
+ return "border-solid";
53
+ case "dotted":
54
+ return "border-dotted";
55
+ case "dashed":
56
+ default:
57
+ return "border-dashed";
58
+ }
59
+ }
60
+ );
61
+ const uploaderClasses = computed(
62
+ () => [
63
+ "border-2 transition-all duration-300 flex flex-col items-center justify-center cursor-pointer",
64
+ roundedClasses.value,
65
+ separatorClasses.value,
66
+ props.bordered ? !isHex(props.borderColor) ? `border-${props.borderColor}` : "" : "border-transparent",
67
+ props.flat ? "shadow-none" : "shadow-md",
68
+ !isHex(props.bgColor) ? `bg-${props.bgColor}` : "",
69
+ props.dense ? "p-4" : "p-8",
70
+ props.disabled ? "opacity-50 pointer-events-none" : "hover:shadow-lg"
71
+ ]
72
+ );
73
+ const uploaderStyle = computed(
74
+ () => {
75
+ const style = {};
76
+ if (isHex(props.borderColor)) {
77
+ style.borderColor = props.borderColor;
78
+ }
79
+ if (isHex(props.bgColor)) {
80
+ style.backgroundColor = props.bgColor;
81
+ }
82
+ return style;
83
+ }
84
+ );
85
+ const triggerFileInput = () => {
86
+ fileInput.value?.click();
87
+ };
88
+ const createFileObject = (file) => ({
89
+ file,
90
+ name: file.name,
91
+ size: file.size,
92
+ type: file.type
93
+ });
94
+ const handleFiles = (event) => {
95
+ const selectedFiles = "dataTransfer" in event && event.dataTransfer ? Array.from(
96
+ event.dataTransfer.files
97
+ ) : Array.from(
98
+ event.target.files || []
99
+ );
100
+ const validFiles = selectedFiles.filter((file) => {
101
+ const fileSizeInKb = file.size / 1024;
102
+ if (fileSizeInKb > props.fileSizeLimitKb) {
103
+ errorMessage.value = `File "${file.name}" exceeds ${props.fileSizeLimitKb} KB`;
104
+ return false;
105
+ }
106
+ return true;
107
+ });
108
+ const mapped = validFiles.map(
109
+ createFileObject
110
+ );
111
+ files.value = props.multiple ? [
112
+ ...files.value,
113
+ ...mapped
114
+ ] : mapped;
115
+ if (mapped.length > 0) {
116
+ errorMessage.value = "";
117
+ }
118
+ };
119
+ const removeFile = (index) => {
120
+ files.value = files.value.filter(
121
+ (_, i) => i !== index
122
+ );
123
+ };
124
+ </script>
125
+
126
+ <template>
127
+ <div class="max-w-lg mx-auto">
128
+ <!-- Header -->
129
+ <div class="mb-6 text-center">
130
+ <h2 class="text-2xl font-bold text-gray-800 dark:text-white">
131
+ {{ header }}
132
+ </h2>
133
+
134
+ <p class="text-sm text-gray-500">
135
+ {{ subHeader }}
136
+ </p>
137
+ </div>
138
+
139
+ <!-- Hidden Input -->
140
+ <input ref="fileInput" type="file" class="hidden" :accept="fileType" :multiple="multiple" @change="handleFiles">
141
+
142
+ <!-- Dropzone -->
143
+ <div :class="uploaderClasses" :style="uploaderStyle" @click="triggerFileInput" @dragover.prevent @drop.prevent="
144
+ handleFiles($event)
145
+ ">
146
+ <slot name="content">
147
+ <p class="text-gray-600 mb-4">
148
+ {{
149
+ multiple ? "Drag & drop files here" : "Drag & drop file here"
150
+ }}
151
+ </p>
152
+
153
+ <button type="button" class="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
154
+ {{
155
+ multiple ? "Browse Files" : "Browse File"
156
+ }}
157
+ </button>
158
+ </slot>
159
+ </div>
160
+
161
+ <!-- Uploaded Files -->
162
+ <div v-if="files.length" class="mt-6">
163
+ <h3 class="text-lg font-semibold mb-4">
164
+ Uploaded Files
165
+ </h3>
166
+
167
+ <ul class="space-y-2">
168
+ <li v-for="(file, index) in files" :key="index"
169
+ class="flex items-center justify-between p-4 rounded-lg border border-gray-200 bg-gray-50">
170
+ <div class="flex items-center gap-3">
171
+ <span class="material-icons text-blue-500">
172
+ description
173
+ </span>
174
+
175
+ <span>
176
+ {{ file.name }}
177
+ </span>
178
+ </div>
179
+
180
+ <button type="button" class="text-red-500 hover:text-red-700" @click.stop="
181
+ removeFile(index)
182
+ ">
183
+ <span class="material-icons">
184
+ {{
185
+ fileRemoverIcon
186
+ }}
187
+ </span>
188
+ </button>
189
+ </li>
190
+ </ul>
191
+ </div>
192
+
193
+ <!-- Error -->
194
+ <div v-if="errorMessage" class="mt-4 text-sm text-red-500">
195
+ {{ errorMessage }}
196
+ </div>
197
+ </div>
198
+ </template>
199
+
200
+ <style scoped>
201
+ .material-icons{font-size:20px}
202
+ </style>
@@ -0,0 +1,58 @@
1
+ interface UploadedFile {
2
+ file: File;
3
+ name: string;
4
+ size: number;
5
+ type: string;
6
+ }
7
+ type Separator = 'solid' | 'dashed' | 'dotted';
8
+ type Rounded = 'none' | 'sm' | 'md' | 'lg' | 'xl';
9
+ type __VLS_Props = {
10
+ modelValue?: UploadedFile[];
11
+ header?: string;
12
+ subHeader?: string;
13
+ fileType?: string;
14
+ multiple?: boolean;
15
+ disabled?: boolean;
16
+ bordered?: boolean;
17
+ flat?: boolean;
18
+ rounded?: Rounded;
19
+ borderColor?: string;
20
+ bgColor?: string;
21
+ separator?: Separator;
22
+ dense?: boolean;
23
+ fileRemoverIcon?: string;
24
+ fileSizeLimitKb?: number;
25
+ };
26
+ declare var __VLS_1: {};
27
+ type __VLS_Slots = {} & {
28
+ content?: (props: typeof __VLS_1) => any;
29
+ };
30
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
31
+ "update:modelValue": (value: UploadedFile[]) => any;
32
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
33
+ "onUpdate:modelValue"?: ((value: UploadedFile[]) => any) | undefined;
34
+ }>, {
35
+ modelValue: UploadedFile[];
36
+ disabled: boolean;
37
+ dense: boolean;
38
+ header: string;
39
+ rounded: Rounded;
40
+ borderColor: string;
41
+ separator: Separator;
42
+ flat: boolean;
43
+ bordered: boolean;
44
+ subHeader: string;
45
+ fileType: string;
46
+ multiple: boolean;
47
+ bgColor: string;
48
+ fileRemoverIcon: string;
49
+ fileSizeLimitKb: number;
50
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
51
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
52
+ declare const _default: typeof __VLS_export;
53
+ export default _default;
54
+ type __VLS_WithSlots<T, S> = T & {
55
+ new (): {
56
+ $slots: S;
57
+ };
58
+ };
@@ -0,0 +1,41 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
2
+ name: {
3
+ type: StringConstructor;
4
+ required: true;
5
+ };
6
+ library: {
7
+ type: StringConstructor;
8
+ default: string;
9
+ };
10
+ color: {
11
+ type: StringConstructor;
12
+ default: string;
13
+ };
14
+ size: {
15
+ type: StringConstructor;
16
+ default: string;
17
+ };
18
+ }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
19
+ name: {
20
+ type: StringConstructor;
21
+ required: true;
22
+ };
23
+ library: {
24
+ type: StringConstructor;
25
+ default: string;
26
+ };
27
+ color: {
28
+ type: StringConstructor;
29
+ default: string;
30
+ };
31
+ size: {
32
+ type: StringConstructor;
33
+ default: string;
34
+ };
35
+ }>> & Readonly<{}>, {
36
+ color: string;
37
+ size: string;
38
+ library: string;
39
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
40
+ declare const _default: typeof __VLS_export;
41
+ export default _default;
@@ -0,0 +1,66 @@
1
+ <script setup>
2
+ defineOptions({
3
+ inheritAttrs: false
4
+ });
5
+ import { computed } from "vue";
6
+ const props = defineProps({
7
+ name: { type: String, required: true },
8
+ library: {
9
+ type: String,
10
+ default: "material"
11
+ },
12
+ color: {
13
+ type: String,
14
+ default: ""
15
+ },
16
+ size: {
17
+ type: String,
18
+ default: "md"
19
+ }
20
+ });
21
+ const isHex = (val) => val.startsWith("#");
22
+ const sizeMap = {
23
+ xs: "text-xs",
24
+ sm: "text-sm",
25
+ md: "text-base",
26
+ lg: "text-xl",
27
+ xl: "text-3xl"
28
+ };
29
+ const iconStyle = computed(() => {
30
+ const style = {};
31
+ if (isHex(props.color)) {
32
+ style.color = props.color;
33
+ }
34
+ return style;
35
+ });
36
+ const iconClass = computed(() => {
37
+ const classes = [
38
+ sizeMap[props.size]
39
+ ];
40
+ if (!isHex(props.color) && props.color) {
41
+ classes.push(`text-${props.color}`);
42
+ }
43
+ switch (props.library) {
44
+ case "material":
45
+ classes.push("material-icons");
46
+ break;
47
+ case "material-symbols":
48
+ classes.push("material-symbols-outlined");
49
+ break;
50
+ case "fontawesome":
51
+ classes.push(props.name);
52
+ break;
53
+ }
54
+ return classes;
55
+ });
56
+ </script>
57
+
58
+ <template>
59
+ <i
60
+ :class="iconClass"
61
+ :style="iconStyle"
62
+ v-bind="$attrs"
63
+ >
64
+ {{ library.includes("material") ? name : "" }}
65
+ </i>
66
+ </template>