windly-ui 1.0.2 → 1.0.4

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 (103) hide show
  1. package/{ui-library/dist → dist}/module.json +2 -2
  2. package/dist/module.mjs +33 -0
  3. package/dist/runtime/components/Accordion.d.vue.ts +39 -0
  4. package/dist/runtime/components/Accordion.vue +96 -0
  5. package/dist/runtime/components/Accordion.vue.d.ts +39 -0
  6. package/dist/runtime/components/Alert.d.vue.ts +83 -0
  7. package/dist/runtime/components/Alert.vue +78 -0
  8. package/dist/runtime/components/Alert.vue.d.ts +83 -0
  9. package/dist/runtime/components/Avatar.d.vue.ts +141 -0
  10. package/dist/runtime/components/Avatar.vue +72 -0
  11. package/dist/runtime/components/Avatar.vue.d.ts +141 -0
  12. package/dist/runtime/components/Badge.d.vue.ts +133 -0
  13. package/dist/runtime/components/Badge.vue +99 -0
  14. package/dist/runtime/components/Badge.vue.d.ts +133 -0
  15. package/dist/runtime/components/Breadcrumbs.d.vue.ts +83 -0
  16. package/dist/runtime/components/Breadcrumbs.vue +116 -0
  17. package/dist/runtime/components/Breadcrumbs.vue.d.ts +83 -0
  18. package/dist/runtime/components/Button.d.vue.ts +208 -0
  19. package/dist/runtime/components/Button.vue +126 -0
  20. package/dist/runtime/components/Button.vue.d.ts +208 -0
  21. package/dist/runtime/components/Card.d.vue.ts +83 -0
  22. package/dist/runtime/components/Card.vue +71 -0
  23. package/dist/runtime/components/Card.vue.d.ts +83 -0
  24. package/dist/runtime/components/Checkbox.d.vue.ts +190 -0
  25. package/dist/runtime/components/Checkbox.vue +125 -0
  26. package/dist/runtime/components/Checkbox.vue.d.ts +190 -0
  27. package/dist/runtime/components/CodeBlock.d.vue.ts +16 -0
  28. package/dist/runtime/components/CodeBlock.vue +75 -0
  29. package/dist/runtime/components/CodeBlock.vue.d.ts +16 -0
  30. package/dist/runtime/components/ColorPicker.d.vue.ts +91 -0
  31. package/dist/runtime/components/ColorPicker.vue +244 -0
  32. package/dist/runtime/components/ColorPicker.vue.d.ts +91 -0
  33. package/dist/runtime/components/Date.d.vue.ts +137 -0
  34. package/dist/runtime/components/Date.vue +201 -0
  35. package/dist/runtime/components/Date.vue.d.ts +137 -0
  36. package/dist/runtime/components/Dialog.d.vue.ts +63 -0
  37. package/dist/runtime/components/Dialog.vue +85 -0
  38. package/dist/runtime/components/Dialog.vue.d.ts +63 -0
  39. package/dist/runtime/components/Divider.d.vue.ts +51 -0
  40. package/dist/runtime/components/Divider.vue +52 -0
  41. package/dist/runtime/components/Divider.vue.d.ts +51 -0
  42. package/dist/runtime/components/Drawer.d.vue.ts +30 -0
  43. package/dist/runtime/components/Drawer.vue +43 -0
  44. package/dist/runtime/components/Drawer.vue.d.ts +30 -0
  45. package/dist/runtime/components/Dropdown.d.vue.ts +34 -0
  46. package/dist/runtime/components/Dropdown.vue +127 -0
  47. package/dist/runtime/components/Dropdown.vue.d.ts +34 -0
  48. package/dist/runtime/components/FileUploader.d.vue.ts +65 -0
  49. package/dist/runtime/components/FileUploader.vue +358 -0
  50. package/dist/runtime/components/FileUploader.vue.d.ts +65 -0
  51. package/dist/runtime/components/Icon.d.vue.ts +41 -0
  52. package/dist/runtime/components/Icon.vue +66 -0
  53. package/dist/runtime/components/Icon.vue.d.ts +41 -0
  54. package/dist/runtime/components/Image.d.vue.ts +77 -0
  55. package/dist/runtime/components/Image.vue +61 -0
  56. package/dist/runtime/components/Image.vue.d.ts +77 -0
  57. package/dist/runtime/components/Input.d.vue.ts +68 -0
  58. package/dist/runtime/components/Input.vue +241 -0
  59. package/dist/runtime/components/Input.vue.d.ts +68 -0
  60. package/dist/runtime/components/Radio.d.vue.ts +41 -0
  61. package/dist/runtime/components/Radio.vue +222 -0
  62. package/dist/runtime/components/Radio.vue.d.ts +41 -0
  63. package/dist/runtime/components/ScrollArea.d.vue.ts +79 -0
  64. package/dist/runtime/components/ScrollArea.vue +36 -0
  65. package/dist/runtime/components/ScrollArea.vue.d.ts +79 -0
  66. package/dist/runtime/components/Select.d.vue.ts +51 -0
  67. package/dist/runtime/components/Select.vue +271 -0
  68. package/dist/runtime/components/Select.vue.d.ts +51 -0
  69. package/dist/runtime/components/Stepper.d.vue.ts +46 -0
  70. package/dist/runtime/components/Stepper.vue +218 -0
  71. package/dist/runtime/components/Stepper.vue.d.ts +46 -0
  72. package/dist/runtime/components/TabPanel.d.vue.ts +17 -0
  73. package/dist/runtime/components/TabPanel.vue +21 -0
  74. package/dist/runtime/components/TabPanel.vue.d.ts +17 -0
  75. package/dist/runtime/components/Table.d.vue.ts +40 -0
  76. package/dist/runtime/components/Table.vue +92 -0
  77. package/dist/runtime/components/Table.vue.d.ts +40 -0
  78. package/dist/runtime/components/Tabs.d.vue.ts +20 -0
  79. package/dist/runtime/components/Tabs.vue +62 -0
  80. package/dist/runtime/components/Tabs.vue.d.ts +20 -0
  81. package/dist/runtime/components/Textarea.d.vue.ts +208 -0
  82. package/dist/runtime/components/Textarea.vue +185 -0
  83. package/dist/runtime/components/Textarea.vue.d.ts +208 -0
  84. package/dist/runtime/components/Toggle.d.vue.ts +36 -0
  85. package/dist/runtime/components/Toggle.vue +173 -0
  86. package/dist/runtime/components/Toggle.vue.d.ts +36 -0
  87. package/dist/runtime/components/Tooltip.d.vue.ts +63 -0
  88. package/dist/runtime/components/Tooltip.vue +144 -0
  89. package/dist/runtime/components/Tooltip.vue.d.ts +63 -0
  90. package/dist/runtime/components/uiProps.d.ts +38 -0
  91. package/dist/runtime/components/uiProps.js +11 -0
  92. package/dist/runtime/components/useUiClasses.d.ts +43 -0
  93. package/dist/runtime/components/useUiClasses.js +124 -0
  94. package/dist/runtime/composables/plugin.d.ts +2 -0
  95. package/dist/runtime/composables/plugin.js +3 -0
  96. package/dist/runtime/tailwind-color.d.ts +2 -0
  97. package/dist/runtime/tailwind-color.js +5859 -0
  98. package/package.json +12 -46
  99. package/LICENSE +0 -21
  100. package/README.md +0 -232
  101. package/ui-library/dist/module.mjs +0 -22
  102. /package/{ui-library/dist → dist}/module.d.mts +0 -0
  103. /package/{ui-library/dist → dist}/types.d.mts +0 -0
@@ -0,0 +1,358 @@
1
+ <script setup>
2
+ defineOptions({
3
+ name: "UIFileUploader"
4
+ });
5
+ import { computed, ref } from "vue";
6
+ const props = defineProps({
7
+ modelValue: { type: Array, required: false, default: () => [] },
8
+ label: { type: String, required: false, default: "" },
9
+ hint: { type: String, required: false, default: "" },
10
+ fileType: { type: String, required: false, default: "*" },
11
+ multiple: { type: Boolean, required: false, default: true },
12
+ size: { type: String, required: false, default: "md" },
13
+ color: { type: String, required: false, default: "" },
14
+ rounded: { type: String, required: false, default: "md" },
15
+ dense: { type: Boolean, required: false, default: false },
16
+ width: { type: String, required: false, default: "" },
17
+ outlined: { type: Boolean, required: false, default: true },
18
+ borderless: { type: Boolean, required: false, default: false },
19
+ flat: { type: Boolean, required: false, default: false },
20
+ separator: { type: String, required: false, default: "dashed" },
21
+ disabled: { type: Boolean, required: false, default: false },
22
+ readonly: { type: Boolean, required: false, default: false },
23
+ fileRemoverIcon: { type: String, required: false, default: "close" },
24
+ fileSizeLimitKb: { type: Number, required: false, default: 2048 }
25
+ });
26
+ const emit = defineEmits(["update:modelValue"]);
27
+ const fileInput = ref(null);
28
+ const errorMessage = ref("");
29
+ const isDragging = ref(false);
30
+ const files = computed({
31
+ get: () => props.modelValue,
32
+ set: (value) => emit(
33
+ "update:modelValue",
34
+ value
35
+ )
36
+ });
37
+ const isHex = (val) => val.startsWith("#");
38
+ const roundedMap = {
39
+ none: "rounded-none",
40
+ sm: "rounded-sm",
41
+ md: "rounded-md",
42
+ lg: "rounded-lg",
43
+ xl: "rounded-xl",
44
+ full: "rounded-full"
45
+ };
46
+ const separatorClass = computed(() => {
47
+ switch (props.separator) {
48
+ case "solid":
49
+ return "border-solid";
50
+ case "dotted":
51
+ return "border-dotted";
52
+ default:
53
+ return "border-dashed";
54
+ }
55
+ });
56
+ const computedClass = computed(() => {
57
+ let classes = "input block transition-all duration-300 border ";
58
+ if (props.borderless) {
59
+ classes += " border-none bg-transparent";
60
+ } else if (props.outlined) {
61
+ classes += " border";
62
+ } else {
63
+ classes += " border-0 border-b";
64
+ }
65
+ if (!props.borderless) {
66
+ classes += ` ${separatorClass.value}`;
67
+ }
68
+ classes += ` ${roundedMap[props.rounded] ?? roundedMap.md}`;
69
+ if (!props.flat) {
70
+ classes += " shadow-sm";
71
+ }
72
+ if (props.disabled) {
73
+ classes += " opacity-50 cursor-not-allowed";
74
+ } else {
75
+ classes += " cursor-pointer";
76
+ }
77
+ if (props.readonly) {
78
+ classes += " pointer-events-none";
79
+ }
80
+ switch (props.size) {
81
+ case "sm":
82
+ classes += " text-sm";
83
+ break;
84
+ case "lg":
85
+ classes += " text-lg";
86
+ break;
87
+ default:
88
+ classes += " text-base";
89
+ }
90
+ if (props.color && !isHex(props.color)) {
91
+ classes += ` border-${props.color} focus:ring-${props.color}`;
92
+ }
93
+ if (props.width && !CSS.supports(
94
+ "width",
95
+ props.width
96
+ )) {
97
+ classes += ` w-${props.width}`;
98
+ }
99
+ if (!props.width) {
100
+ classes += " w-full";
101
+ }
102
+ if (isDragging.value) {
103
+ classes += " scale-[1.01]";
104
+ }
105
+ return classes;
106
+ });
107
+ const computedStyle = computed(() => {
108
+ const styles = {};
109
+ if (props.width && CSS.supports(
110
+ "width",
111
+ props.width
112
+ )) {
113
+ styles.width = props.width;
114
+ }
115
+ if (props.color && isHex(props.color)) {
116
+ styles.borderColor = props.color;
117
+ styles["--tw-ring-color"] = props.color;
118
+ }
119
+ return styles;
120
+ });
121
+ const triggerFileInput = () => {
122
+ if (props.disabled || props.readonly) {
123
+ return;
124
+ }
125
+ fileInput.value?.click();
126
+ };
127
+ const createFileObject = (file) => ({
128
+ file,
129
+ name: file.name,
130
+ size: file.size,
131
+ type: file.type
132
+ });
133
+ const validateFile = (file) => {
134
+ errorMessage.value = "";
135
+ const sizeKb = file.size / 1024;
136
+ if (sizeKb > props.fileSizeLimitKb) {
137
+ errorMessage.value = `"${file.name}" exceeds ${props.fileSizeLimitKb} KB.`;
138
+ return false;
139
+ }
140
+ if (props.fileType && props.fileType !== "*") {
141
+ const accepted = props.fileType.split(",").map((t) => t.trim());
142
+ const valid = accepted.some(
143
+ (type) => {
144
+ if (type.endsWith("/*")) {
145
+ return file.type.startsWith(
146
+ type.replace(
147
+ "/*",
148
+ "/"
149
+ )
150
+ );
151
+ }
152
+ if (type.startsWith(".")) {
153
+ return file.name.toLowerCase().endsWith(
154
+ type.toLowerCase()
155
+ );
156
+ }
157
+ return file.type === type;
158
+ }
159
+ );
160
+ if (!valid) {
161
+ errorMessage.value = `"${file.name}" is not a supported file type.`;
162
+ return false;
163
+ }
164
+ }
165
+ return true;
166
+ };
167
+ const addFiles = (selectedFiles) => {
168
+ const validFiles = selectedFiles.filter(validateFile).map(createFileObject);
169
+ if (!validFiles.length)
170
+ return;
171
+ files.value = props.multiple ? [
172
+ ...files.value,
173
+ ...validFiles
174
+ ] : validFiles;
175
+ errorMessage.value = "";
176
+ };
177
+ const handleFiles = (event) => {
178
+ const target = event.target;
179
+ if (!target.files)
180
+ return;
181
+ addFiles(
182
+ Array.from(target.files)
183
+ );
184
+ target.value = "";
185
+ };
186
+ const handleDrop = (event) => {
187
+ isDragging.value = false;
188
+ if (props.disabled || props.readonly) {
189
+ return;
190
+ }
191
+ if (!event.dataTransfer) {
192
+ return;
193
+ }
194
+ addFiles(
195
+ Array.from(
196
+ event.dataTransfer.files
197
+ )
198
+ );
199
+ };
200
+ const handleDragOver = (event) => {
201
+ event.preventDefault();
202
+ if (props.disabled || props.readonly) {
203
+ return;
204
+ }
205
+ isDragging.value = true;
206
+ };
207
+ const handleDragLeave = () => {
208
+ isDragging.value = false;
209
+ };
210
+ const removeFile = (index) => {
211
+ files.value = files.value.filter(
212
+ (_, i) => i !== index
213
+ );
214
+ };
215
+ const formattedFiles = computed(
216
+ () => files.value.map(
217
+ (file) => ({
218
+ ...file,
219
+ formattedSize: file.size >= 1024 * 1024 ? `${(file.size / 1024 / 1024).toFixed(
220
+ 2
221
+ )} MB` : `${(file.size / 1024).toFixed(
222
+ 1
223
+ )} KB`
224
+ })
225
+ )
226
+ );
227
+ </script>
228
+
229
+ <template>
230
+ <div
231
+ :class="[
232
+ 'relative',
233
+ dense ? 'my-2.5' : 'mt-5 mb-2.5',
234
+ size && `input-${size}`
235
+ ]"
236
+ >
237
+ <!-- Hidden Input -->
238
+ <input
239
+ ref="fileInput"
240
+ type="file"
241
+ class="hidden"
242
+ :accept="fileType"
243
+ :multiple="multiple"
244
+ @change="handleFiles"
245
+ />
246
+
247
+ <!-- Floating Label -->
248
+ <label
249
+ class="absolute -top-6 px-1 pointer-events-none transition-all duration-200
250
+ dark:text-gray-300"
251
+ :class="color && !isHex(color) ? `text-${color}` : 'text-gray-400 input-' + size"
252
+ :style="
253
+ color && isHex(color) ? { color } : void 0
254
+ "
255
+ >
256
+ {{ label }}
257
+ </label>
258
+
259
+ <!-- Hint -->
260
+ <p
261
+ v-if="hint"
262
+ class="ml-1 text-[10px] text-gray-500 dark:text-gray-400"
263
+ >
264
+ {{ hint }}
265
+ </p>
266
+
267
+ <!-- Dropzone -->
268
+ <div
269
+ :class="computedClass"
270
+ :style="computedStyle"
271
+ class="mt-1 p-1 flex flex-col items-center justify-center
272
+ select-none text-center text-xs
273
+ transition-all duration-200
274
+ hover:bg-black/5
275
+ dark:hover:bg-white/5"
276
+ @click="triggerFileInput"
277
+ @dragover.prevent="handleDragOver"
278
+ @dragleave="handleDragLeave"
279
+ @drop.prevent="handleDrop"
280
+ >
281
+ <slot name="content">
282
+ <p class="text-xs text-gray-500">
283
+ {{
284
+ multiple ? "Drop files here or click to browse" : "Drop file here or click to browse"
285
+ }}
286
+ </p>
287
+ <p
288
+ v-if="fileType && fileType !== '*'"
289
+ class="text-[10px] text-gray-500"
290
+ >
291
+ Accepted: {{ fileType }}
292
+ </p>
293
+ <p class="text-[10px] text-gray-500">
294
+ Maximum size: {{ fileSizeLimitKb }} KB
295
+ </p>
296
+ </slot>
297
+ </div>
298
+ <!-- Uploaded Files -->
299
+ <div
300
+ v-if="formattedFiles.length"
301
+ class="mt-3 overflow-hidden rounded-lg border border-gray-200
302
+ dark:border-gray-700"
303
+ >
304
+ <div
305
+ v-for="(file, index) in formattedFiles"
306
+ :key="file.name"
307
+ class="flex items-start justify-between
308
+ border-b border-gray-100 p-1
309
+ last:border-b-0
310
+ dark:border-gray-700"
311
+ >
312
+ <div class="flex min-w-0 items-start gap-3">
313
+ <span class="material-icons text-base text-gray-500">
314
+ insert_drive_file
315
+ </span>
316
+
317
+ <div class="min-w-0">
318
+ <div
319
+ class="truncate text-xs font-medium dark:text-gray-50"
320
+ >
321
+ {{ file.name }}
322
+ </div>
323
+
324
+ <div class="text-[10px] text-gray-400">
325
+ {{ file.formattedSize }}
326
+ </div>
327
+ </div>
328
+ </div>
329
+
330
+ <button
331
+ type="button"
332
+ class="flex h-5 w-5 items-center justify-center rounded-full
333
+ text-gray-400 transition-colors
334
+ hover:bg-red-500/10
335
+ hover:text-red-500
336
+ dark:hover:bg-red-500/20"
337
+ @click.stop="removeFile(index)"
338
+ >
339
+ <span class="material-icons text-xs">
340
+ {{ fileRemoverIcon }}
341
+ </span>
342
+ </button>
343
+ </div>
344
+ </div>
345
+
346
+ <!-- Error -->
347
+ <p
348
+ v-if="errorMessage"
349
+ class="ml-1 mt-1 text-xs text-red-500"
350
+ >
351
+ {{ errorMessage }}
352
+ </p>
353
+ </div>
354
+ </template>
355
+
356
+ <style scoped>
357
+ .input-sm label{font-size:12px}.input-md label{font-size:14px}.input-lg label{font-size:16px}
358
+ </style>
@@ -0,0 +1,65 @@
1
+ interface UploadedFile {
2
+ file: File;
3
+ name: string;
4
+ size: number;
5
+ type: string;
6
+ }
7
+ type Rounded = "none" | "sm" | "md" | "lg" | "xl" | "full";
8
+ type Separator = "solid" | "dashed" | "dotted";
9
+ type Size = "sm" | "md" | "lg";
10
+ type __VLS_Props = {
11
+ modelValue?: UploadedFile[];
12
+ label?: string;
13
+ hint?: string;
14
+ fileType?: string;
15
+ multiple?: boolean;
16
+ size?: Size;
17
+ color?: string;
18
+ rounded?: Rounded;
19
+ dense?: boolean;
20
+ width?: string;
21
+ outlined?: boolean;
22
+ borderless?: boolean;
23
+ flat?: boolean;
24
+ separator?: Separator;
25
+ disabled?: boolean;
26
+ readonly?: boolean;
27
+ fileRemoverIcon?: string;
28
+ fileSizeLimitKb?: number;
29
+ };
30
+ declare var __VLS_1: {};
31
+ type __VLS_Slots = {} & {
32
+ content?: (props: typeof __VLS_1) => any;
33
+ };
34
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
35
+ "update:modelValue": (value: UploadedFile[]) => any;
36
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
37
+ "onUpdate:modelValue"?: ((value: UploadedFile[]) => any) | undefined;
38
+ }>, {
39
+ modelValue: UploadedFile[];
40
+ disabled: boolean;
41
+ dense: boolean;
42
+ label: string;
43
+ color: string;
44
+ rounded: Rounded;
45
+ size: Size;
46
+ separator: Separator;
47
+ flat: boolean;
48
+ width: string;
49
+ readonly: boolean;
50
+ hint: string;
51
+ fileType: string;
52
+ multiple: boolean;
53
+ outlined: boolean;
54
+ borderless: boolean;
55
+ fileRemoverIcon: string;
56
+ fileSizeLimitKb: number;
57
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
58
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
59
+ declare const _default: typeof __VLS_export;
60
+ export default _default;
61
+ type __VLS_WithSlots<T, S> = T & {
62
+ new (): {
63
+ $slots: S;
64
+ };
65
+ };
@@ -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>
@@ -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,77 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
2
+ src: {
3
+ type: StringConstructor;
4
+ required: true;
5
+ };
6
+ alt: {
7
+ type: StringConstructor;
8
+ default: string;
9
+ };
10
+ placeholder: {
11
+ type: StringConstructor;
12
+ default: string;
13
+ };
14
+ width: {
15
+ type: StringConstructor;
16
+ default: string;
17
+ };
18
+ height: {
19
+ type: StringConstructor;
20
+ default: string;
21
+ };
22
+ fit: {
23
+ type: StringConstructor;
24
+ default: string;
25
+ };
26
+ borderColor: {
27
+ type: StringConstructor;
28
+ default: string;
29
+ };
30
+ borderType: {
31
+ type: StringConstructor;
32
+ default: string;
33
+ };
34
+ }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
35
+ src: {
36
+ type: StringConstructor;
37
+ required: true;
38
+ };
39
+ alt: {
40
+ type: StringConstructor;
41
+ default: string;
42
+ };
43
+ placeholder: {
44
+ type: StringConstructor;
45
+ default: string;
46
+ };
47
+ width: {
48
+ type: StringConstructor;
49
+ default: string;
50
+ };
51
+ height: {
52
+ type: StringConstructor;
53
+ default: string;
54
+ };
55
+ fit: {
56
+ type: StringConstructor;
57
+ default: string;
58
+ };
59
+ borderColor: {
60
+ type: StringConstructor;
61
+ default: string;
62
+ };
63
+ borderType: {
64
+ type: StringConstructor;
65
+ default: string;
66
+ };
67
+ }>> & Readonly<{}>, {
68
+ borderColor: string;
69
+ alt: string;
70
+ placeholder: string;
71
+ width: string;
72
+ height: string;
73
+ fit: string;
74
+ borderType: string;
75
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
76
+ declare const _default: typeof __VLS_export;
77
+ export default _default;
@@ -0,0 +1,61 @@
1
+ <script setup>
2
+ defineOptions({
3
+ inheritAttrs: false
4
+ });
5
+ import { computed, ref } from "vue";
6
+ const props = defineProps({
7
+ src: { type: String, required: true },
8
+ alt: { type: String, default: "" },
9
+ placeholder: {
10
+ type: String,
11
+ default: "/images/placeholder.png"
12
+ },
13
+ width: { type: String, default: "100%" },
14
+ height: { type: String, default: "auto" },
15
+ fit: {
16
+ type: String,
17
+ default: "cover"
18
+ },
19
+ borderColor: {
20
+ type: String,
21
+ default: ""
22
+ },
23
+ borderType: {
24
+ type: String,
25
+ default: "none"
26
+ }
27
+ });
28
+ const imageSrc = ref(props.src);
29
+ const isHex = (val) => val.startsWith("#");
30
+ const imageStyle = computed(() => {
31
+ const style = {
32
+ width: props.width,
33
+ height: props.height,
34
+ objectFit: props.fit
35
+ };
36
+ if (isHex(props.borderColor)) {
37
+ style.borderColor = props.borderColor;
38
+ }
39
+ return style;
40
+ });
41
+ const imageClass = computed(() => [
42
+ props.borderType !== "none" ? "border" : "",
43
+ props.borderType === "dashed" ? "border-dashed" : "",
44
+ props.borderType === "dotted" ? "border-dotted" : "",
45
+ !isHex(props.borderColor) ? `border-${props.borderColor}` : ""
46
+ ]);
47
+ function onError() {
48
+ imageSrc.value = props.placeholder;
49
+ }
50
+ </script>
51
+
52
+ <template>
53
+ <img
54
+ :src="imageSrc"
55
+ :alt="alt"
56
+ :class="imageClass"
57
+ :style="imageStyle"
58
+ @error="onError"
59
+ v-bind="$attrs"
60
+ >
61
+ </template>