plugin-ui-for-kzt 0.0.16 → 0.0.18
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/dist/components/BaseBadge/BaseBadge.vue.d.ts +49 -0
- package/dist/components/BaseBadge/BaseBadgeGroup.vue.d.ts +30 -0
- package/dist/components/BaseButton/BaseButton.vue.d.ts +3 -3
- package/dist/components/BaseCheckbox/BaseCheckbox.vue.d.ts +4 -4
- package/dist/components/BaseChips/BaseChips.vue.d.ts +27 -0
- package/dist/components/BaseDropdown/BaseDropdown.vue.d.ts +3 -3
- package/dist/components/BaseInput/BaseInput.vue.d.ts +5 -5
- package/dist/components/BaseInputCalendar/BaseInputCalendar.vue.d.ts +5 -5
- package/dist/components/BaseInputCurrency/BaseInputCurrency.vue.d.ts +5 -5
- package/dist/components/BaseInputEmail/BaseInputEmail.vue.d.ts +5 -5
- package/dist/components/BaseInputPhone/BaseInputPhone.vue.d.ts +5 -5
- package/dist/components/BaseModal/BaseModal.vue.d.ts +4 -0
- package/dist/components/BaseOpenedListItem/BaseOpenedListItem.vue.d.ts +3 -3
- package/dist/components/BasePagination/BasePagination.vue.d.ts +1 -1
- package/dist/components/BaseRadio/BaseRadio.vue.d.ts +4 -4
- package/dist/components/BaseSegmentedButtons/BaseSegmentedButtons.vue.d.ts +3 -3
- package/dist/components/BaseSelect/BaseSelect.vue.d.ts +4 -4
- package/dist/components/BaseSiteInput/BaseSiteInput.vue.d.ts +1 -1
- package/dist/components/BaseSwiper/BaseSwiper.vue.d.ts +57 -0
- package/dist/components/BaseTag/BaseTag.vue.d.ts +61 -0
- package/dist/components/BaseTextarea/BaseTextarea.vue.d.ts +5 -5
- package/dist/components/BaseToggle/BaseToggle.vue.d.ts +4 -4
- package/dist/components/BaseUpload/BaseUpload.vue.d.ts +31 -0
- package/dist/components/{Modal/Modal.vue.d.ts → BaseUpload/ImageModal.vue.d.ts} +2 -10
- package/dist/components/Toaster/Toaster.vue.d.ts +4 -4
- package/dist/composables/useModal.d.ts +7 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +1 -1
- package/dist/plugins/modalPlugin.d.ts +0 -13
- package/dist/sprite.svg +1 -1
- package/dist/store/modal.d.ts +154 -9
- package/example/App.vue +129 -295
- package/example/MyCustomModal.vue +37 -0
- package/package.json +1 -1
- package/src/assets/icons/add.svg +4 -0
- package/src/assets/icons/arrow-left-circle.svg +3 -0
- package/src/assets/icons/arrow-right-circle.svg +3 -0
- package/src/assets/icons/arrow-up.svg +4 -0
- package/src/assets/icons/close-circle.svg +5 -0
- package/src/assets/icons/close.svg +4 -0
- package/src/assets/icons/document-text.svg +4 -0
- package/src/assets/icons/export.svg +5 -0
- package/src/assets/icons/gallery.svg +5 -0
- package/src/assets/icons/notification-icon.svg +7 -0
- package/src/assets/icons/search-zoom-in.svg +6 -0
- package/src/assets/icons/star.svg +3 -0
- package/src/assets/icons/trash.svg +7 -0
- package/src/assets/icons/upload.svg +5 -0
- package/src/components/BaseBadge/BaseBadge.vue +188 -0
- package/src/components/BaseBadge/BaseBadgeGroup.vue +120 -0
- package/src/components/BaseBadge/README.md +127 -0
- package/src/components/BaseBreadCrumbs/BaseBreadCrumbs.vue +3 -3
- package/src/components/BaseButton/BaseButton.vue +29 -122
- package/src/components/BaseChips/BaseChips.vue +182 -0
- package/src/components/BaseChips/README.md +64 -0
- package/src/components/BaseInput/BaseInput.vue +5 -3
- package/src/components/BaseModal/BaseModal.vue +189 -0
- package/src/components/BaseOpenedListItem/BaseOpenedListItem.vue +4 -4
- package/src/components/BasePagination/BasePagination.vue +146 -123
- package/src/components/BaseSiteInput/BaseSiteInput.vue +26 -9
- package/src/components/BaseSwiper/BaseSwiper.vue +229 -0
- package/src/components/BaseTag/BaseTag.vue +245 -0
- package/src/components/BaseTag/README.md +125 -0
- package/src/components/BaseTextarea/BaseTextarea.vue +8 -14
- package/src/components/BaseUpload/BaseUpload.vue +392 -0
- package/src/components/BaseUpload/ImageModal.vue +25 -0
- package/src/composables/useModal.ts +14 -0
- package/src/index.ts +38 -19
- package/src/plugins/modalPlugin.ts +92 -76
- package/src/store/modal.ts +39 -16
- package/src/styles/root.scss +3 -0
- package/src/types/badge.d.ts +19 -0
- package/src/types/chips.d.ts +10 -0
- package/src/types/modal.d.ts +8 -0
- package/src/types/pagination.d.ts +2 -2
- package/src/types/swiper.d.ts +17 -0
- package/src/types/tag.d.ts +14 -0
- package/src/types/uploadedFile.d.ts +13 -0
- package/src/types/utils.d.ts +1 -1
- package/dist/types/index.d.ts +0 -5
- package/src/components/Modal/Modal.vue +0 -149
- package/src/components/Modal/README.md +0 -47
- package/src/types/index.ts +0 -7
|
@@ -65,7 +65,8 @@ function handleInput(event: Event) {
|
|
|
65
65
|
@import '../../styles/root';
|
|
66
66
|
|
|
67
67
|
.base-textarea {
|
|
68
|
-
width:
|
|
68
|
+
width: 100%;
|
|
69
|
+
height: 100%;
|
|
69
70
|
$textarea: &;
|
|
70
71
|
|
|
71
72
|
textarea {
|
|
@@ -80,14 +81,17 @@ function handleInput(event: Event) {
|
|
|
80
81
|
&__wrapper {
|
|
81
82
|
display: flex;
|
|
82
83
|
position: relative;
|
|
84
|
+
width: 100%;
|
|
85
|
+
height: 100%;
|
|
83
86
|
}
|
|
84
87
|
|
|
85
88
|
&__field {
|
|
89
|
+
width: 100%;
|
|
86
90
|
min-width: 320px;
|
|
87
|
-
max-width: calc(-16px + 50vw);
|
|
88
91
|
color: var(--primary-text-primary);
|
|
89
92
|
background: var(--bg-light);
|
|
90
93
|
border: 1px solid var(--primary-black-300);
|
|
94
|
+
transition: all var(--transition);
|
|
91
95
|
|
|
92
96
|
&::placeholder {
|
|
93
97
|
color: var(--primary-text-tertiary);
|
|
@@ -127,6 +131,8 @@ function handleInput(event: Event) {
|
|
|
127
131
|
flex-direction: column;
|
|
128
132
|
gap: 6px;
|
|
129
133
|
align-items: center;
|
|
134
|
+
width: 100%;
|
|
135
|
+
height: 100%;
|
|
130
136
|
}
|
|
131
137
|
|
|
132
138
|
&__label-text {
|
|
@@ -151,10 +157,6 @@ function handleInput(event: Event) {
|
|
|
151
157
|
|
|
152
158
|
&.--small-size {
|
|
153
159
|
#{$textarea} {
|
|
154
|
-
&__wrapper {
|
|
155
|
-
height: 40px;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
160
|
&__field {
|
|
159
161
|
padding: var(--spacing-s) calc(var(--spacing-2l) + 35px) var(--spacing-s) var(--spacing-2l);
|
|
160
162
|
font: var(--typography-text-m-regular);
|
|
@@ -171,10 +173,6 @@ function handleInput(event: Event) {
|
|
|
171
173
|
|
|
172
174
|
&.--medium-size {
|
|
173
175
|
#{$textarea} {
|
|
174
|
-
&__wrapper {
|
|
175
|
-
height: 48px;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
176
|
&__field {
|
|
179
177
|
padding: var(--spacing-m) calc(var(--spacing-2l) + 35px) var(--spacing-m) var(--spacing-2l);
|
|
180
178
|
font: var(--typography-text-m-regular);
|
|
@@ -191,10 +189,6 @@ function handleInput(event: Event) {
|
|
|
191
189
|
|
|
192
190
|
&.--large-size {
|
|
193
191
|
#{$textarea} {
|
|
194
|
-
&__wrapper {
|
|
195
|
-
height: 56px;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
192
|
&__field {
|
|
199
193
|
padding: var(--spacing-2l) calc(var(--spacing-l) + 35px) var(--spacing-2l) var(--spacing-l);
|
|
200
194
|
font: var(--typography-text-l-regular);
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="base-file-upload">
|
|
3
|
+
<input
|
|
4
|
+
type="file"
|
|
5
|
+
ref="fileInput"
|
|
6
|
+
:multiple="multiple"
|
|
7
|
+
@change="handleFileUpload"
|
|
8
|
+
class="base-file-upload__input"
|
|
9
|
+
:accept="acceptedFormats.join(',')"
|
|
10
|
+
/>
|
|
11
|
+
<div class="base-file-upload__wrapper" @click="triggerFileInput">
|
|
12
|
+
<base-icon
|
|
13
|
+
name="upload"
|
|
14
|
+
class="base-file-upload__icon-upload"
|
|
15
|
+
size="large"
|
|
16
|
+
/>
|
|
17
|
+
<p class="base-file-upload__title">
|
|
18
|
+
<slot name="title">Перетащите или кликните для загрузки</slot>
|
|
19
|
+
</p>
|
|
20
|
+
<p class="base-file-upload__description">
|
|
21
|
+
<slot name="description">Допустимый формат файлов: pdf, docx, jpeg до 25 MB</slot>
|
|
22
|
+
</p>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div v-if="uploadedFiles.length > 0" class="base-file-upload__files">
|
|
26
|
+
<!-- Медиафайлы (изображения) в ряд -->
|
|
27
|
+
<div v-if="mediaFiles.length > 0" class="base-file-upload__media-row">
|
|
28
|
+
<div
|
|
29
|
+
v-for="(file, index) in mediaFiles"
|
|
30
|
+
:key="index"
|
|
31
|
+
class="base-file-upload__media-item"
|
|
32
|
+
>
|
|
33
|
+
<img :src="getImagePreview(file.file)" alt="Preview" class="base-file-upload__media-preview" />
|
|
34
|
+
<base-button
|
|
35
|
+
class="base-file-upload__zoom"
|
|
36
|
+
size="custom"
|
|
37
|
+
color="custom"
|
|
38
|
+
@click="openImageModal(file.file)"
|
|
39
|
+
>
|
|
40
|
+
<base-icon name="search-zoom-in" size="custom" class="base-file-upload__zoom-icon" />
|
|
41
|
+
</base-button>
|
|
42
|
+
<base-button
|
|
43
|
+
class="base-file-upload__remove"
|
|
44
|
+
size="custom"
|
|
45
|
+
color="custom"
|
|
46
|
+
@click="removeFile(index, true)"
|
|
47
|
+
>
|
|
48
|
+
<base-icon name="trash" size="custom" class="base-file-upload__zoom-icon" />
|
|
49
|
+
</base-button>
|
|
50
|
+
</div>
|
|
51
|
+
<!-- Заглушка для загрузки дополнительных медиафайлов -->
|
|
52
|
+
<div
|
|
53
|
+
v-if="mediaFiles.length > 0"
|
|
54
|
+
class="base-file-upload__media-item base-file-upload__media-placeholder"
|
|
55
|
+
@click="triggerFileInput"
|
|
56
|
+
>
|
|
57
|
+
<base-icon name="gallery" size="medium" class="base-file-upload__placeholder-icon" />
|
|
58
|
+
<p class="base-file-upload__placeholder-text"><span>Загрузить</span> <br /> фото</p>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<!-- Остальные файлы в колонках -->
|
|
63
|
+
<div v-if="otherFiles.length > 0" class="base-file-upload__file-list">
|
|
64
|
+
<div
|
|
65
|
+
v-for="(file, index) in otherFiles"
|
|
66
|
+
:key="index"
|
|
67
|
+
class="base-file-upload__file-item"
|
|
68
|
+
>
|
|
69
|
+
<div class="base-file-upload__file-item-wrapper">
|
|
70
|
+
<base-icon name="document-text" size="medium" />
|
|
71
|
+
<span>{{ file.name }} ({{ formatFileSize(file.size) }})</span>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="base-file-upload__file-item-wrapper">
|
|
74
|
+
<base-button
|
|
75
|
+
class="base-file-upload__file-item-button"
|
|
76
|
+
size="custom"
|
|
77
|
+
color="custom"
|
|
78
|
+
@click="downloadFile(file.file, index, false)"
|
|
79
|
+
>
|
|
80
|
+
<base-icon
|
|
81
|
+
name="export"
|
|
82
|
+
size="medium"
|
|
83
|
+
class="base-file-upload__file-item-icon"
|
|
84
|
+
/>
|
|
85
|
+
</base-button>
|
|
86
|
+
<base-button
|
|
87
|
+
class="base-file-upload__file-item-button base-file-upload__file-item-button-trash"
|
|
88
|
+
size="custom"
|
|
89
|
+
color="custom"
|
|
90
|
+
@click="removeFile(index, false)"
|
|
91
|
+
>
|
|
92
|
+
<base-icon
|
|
93
|
+
name="trash"
|
|
94
|
+
size="medium"
|
|
95
|
+
class="base-file-upload__file-item-icon"
|
|
96
|
+
/>
|
|
97
|
+
</base-button>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<p v-if="errorMessage" class="base-file-upload__error">{{ errorMessage }}</p>
|
|
104
|
+
</div>
|
|
105
|
+
</template>
|
|
106
|
+
|
|
107
|
+
<script setup lang="ts">
|
|
108
|
+
import { ref, computed, watch } from 'vue';
|
|
109
|
+
import BaseButton from '../BaseButton/BaseButton.vue';
|
|
110
|
+
import BaseIcon from '../BaseIcon/BaseIcon.vue';
|
|
111
|
+
import { useModal } from '../../composables/useModal';
|
|
112
|
+
import type { UploadedFile, IpropsUpload } from '../../types/uploadedFile.d';
|
|
113
|
+
import ImageModal from './ImageModal.vue';
|
|
114
|
+
|
|
115
|
+
const props = withDefaults(defineProps<IpropsUpload>(), {
|
|
116
|
+
multiple: true,
|
|
117
|
+
maxFileSize: 25 * 1024 * 1024, // 25 MB в байтах
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const emit = defineEmits(['update:files']);
|
|
121
|
+
|
|
122
|
+
const fileInput = ref<HTMLInputElement | null>(null);
|
|
123
|
+
const uploadedFiles = ref<UploadedFile[]>([]);
|
|
124
|
+
const isUploading = ref(false);
|
|
125
|
+
const errorMessage = ref<string | null>(null);
|
|
126
|
+
const modal = useModal();
|
|
127
|
+
|
|
128
|
+
const mediaExtensions = ['.jpg', '.jpeg', '.png'];
|
|
129
|
+
const mediaFiles = computed(() =>
|
|
130
|
+
uploadedFiles.value.filter((file) =>
|
|
131
|
+
mediaExtensions.includes(`.${file.name.split('.').pop()?.toLowerCase() || ''}`)
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
const otherFiles = computed(() =>
|
|
135
|
+
uploadedFiles.value.filter((file) =>
|
|
136
|
+
!mediaExtensions.includes(`.${file.name.split('.').pop()?.toLowerCase() || ''}`)
|
|
137
|
+
)
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const triggerFileInput = () => {
|
|
141
|
+
fileInput.value?.click();
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const handleFileUpload = (event: Event) => {
|
|
145
|
+
const target = event.target as HTMLInputElement;
|
|
146
|
+
const files = target.files;
|
|
147
|
+
|
|
148
|
+
if (files) {
|
|
149
|
+
isUploading.value = true;
|
|
150
|
+
errorMessage.value = null;
|
|
151
|
+
|
|
152
|
+
Array.from(files).forEach((file) => {
|
|
153
|
+
const fileExtension = `.${file.name.split('.').pop()?.toLowerCase() || ''}`;
|
|
154
|
+
if (!props.acceptedFormats.includes(fileExtension)) {
|
|
155
|
+
errorMessage.value = `Недопустимый формат файла: ${file.name}. Допустимы: ${props.acceptedFormats.join(', ')}.`;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (file.size > props.maxFileSize) {
|
|
160
|
+
errorMessage.value = `Файл ${file.name} превышает максимальный размер ${formatFileSize(props.maxFileSize)}.`;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
uploadedFiles.value.push({ name: file.name, size: file.size, file });
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
isUploading.value = false;
|
|
168
|
+
target.value = '';
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const removeFile = (index: number, isMedia: boolean) => {
|
|
173
|
+
const files = isMedia ? mediaFiles.value : otherFiles.value;
|
|
174
|
+
const globalIndex = uploadedFiles.value.indexOf(files[index]);
|
|
175
|
+
if (globalIndex !== -1) {
|
|
176
|
+
uploadedFiles.value.splice(globalIndex, 1);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const downloadFile = (file: File, index: number, isMedia: boolean) => {
|
|
181
|
+
const url = URL.createObjectURL(file);
|
|
182
|
+
const link = document.createElement('a');
|
|
183
|
+
link.href = url;
|
|
184
|
+
link.download = file.name;
|
|
185
|
+
document.body.appendChild(link);
|
|
186
|
+
link.click();
|
|
187
|
+
document.body.removeChild(link);
|
|
188
|
+
URL.revokeObjectURL(url);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const openImageModal = (file: File) => {
|
|
192
|
+
const imageUrl = getImagePreview(file);
|
|
193
|
+
modal.open('image-modal', { closable: true, imageUrl }, ImageModal);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const formatFileSize = (bytes: number) => {
|
|
197
|
+
if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
198
|
+
if (bytes >= 1024) return `${(bytes / 1024).toFixed(2)} KB`;
|
|
199
|
+
return `${bytes} B`;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const getImagePreview = (file: File) => {
|
|
203
|
+
return URL.createObjectURL(file);
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
watch(uploadedFiles, (newFiles) => {
|
|
207
|
+
emit('update:files', newFiles);
|
|
208
|
+
}, { deep: true });
|
|
209
|
+
</script>
|
|
210
|
+
|
|
211
|
+
<style lang="scss" scoped>
|
|
212
|
+
@import '../../styles/variables';
|
|
213
|
+
@import '../../styles/root';
|
|
214
|
+
|
|
215
|
+
.base-file-upload {
|
|
216
|
+
display: flex;
|
|
217
|
+
flex-direction: column;
|
|
218
|
+
gap: var(--spacing-l);
|
|
219
|
+
|
|
220
|
+
&__wrapper {
|
|
221
|
+
display: flex;
|
|
222
|
+
flex-direction: column;
|
|
223
|
+
align-items: center;
|
|
224
|
+
justify-content: center;
|
|
225
|
+
gap: var(--spacing-xs);
|
|
226
|
+
border-radius: var(--corner-radius-m);
|
|
227
|
+
border: 1px solid var(--primary-black-300);
|
|
228
|
+
background: var(--bg-light);
|
|
229
|
+
padding: 32px 120px;
|
|
230
|
+
transition: all var(--transition);
|
|
231
|
+
|
|
232
|
+
p {
|
|
233
|
+
margin: 0;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
@include hover {
|
|
237
|
+
cursor: pointer;
|
|
238
|
+
background: var(--primary-black-200);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
&__title {
|
|
243
|
+
color: var(--primary-text-primary);
|
|
244
|
+
font: var(--typography-text-m-medium);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
&__description {
|
|
248
|
+
color: var(--primary-text-tertiary);
|
|
249
|
+
font: var(--typography-text-s-regular);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
&__input {
|
|
253
|
+
display: none;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
&__media-row {
|
|
257
|
+
display: flex;
|
|
258
|
+
gap: 1rem;
|
|
259
|
+
flex-wrap: wrap;
|
|
260
|
+
margin-bottom: 1rem;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
&__media-item {
|
|
264
|
+
position: relative;
|
|
265
|
+
display: inline-block;
|
|
266
|
+
width: 104px;
|
|
267
|
+
height: 104px;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
&__media-preview {
|
|
271
|
+
width: 100%;
|
|
272
|
+
height: 100%;
|
|
273
|
+
object-fit: cover;
|
|
274
|
+
border-radius: var(--corner-radius-xs);
|
|
275
|
+
border: 1px solid var(--primary-black-300);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
&__remove,
|
|
279
|
+
&__zoom {
|
|
280
|
+
position: absolute;
|
|
281
|
+
bottom: 10px;
|
|
282
|
+
cursor: pointer;
|
|
283
|
+
background: var(--bg-light);
|
|
284
|
+
border-radius: var(--corner-radius-2xs);
|
|
285
|
+
padding: var(--spacing-xs);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
&__remove {
|
|
289
|
+
right: 5px;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
&__zoom {
|
|
293
|
+
left: 5px;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
&__zoom-icon {
|
|
297
|
+
width: 20px;
|
|
298
|
+
height: 20px;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
&__file-list {
|
|
302
|
+
display: flex;
|
|
303
|
+
flex-direction: column;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
&__file-item {
|
|
307
|
+
display: flex;
|
|
308
|
+
justify-content: space-between;
|
|
309
|
+
align-items: center;
|
|
310
|
+
padding: 8px 0;
|
|
311
|
+
border-bottom: 1px solid var(--primary-black-200);
|
|
312
|
+
|
|
313
|
+
@include hover {
|
|
314
|
+
.base-file-upload__file-item-wrapper {
|
|
315
|
+
color: var(--primary-blue);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.base-file-upload__file-item-button {
|
|
319
|
+
background: var(--primary-blue-100);
|
|
320
|
+
}
|
|
321
|
+
.base-file-upload__file-item-button-trash {
|
|
322
|
+
background: var(--error-red-light-05);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
@include pressed {
|
|
327
|
+
.base-file-upload__file-item-wrapper {
|
|
328
|
+
color: var(--primary-blue-deep);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.base-file-upload__file-item-button {
|
|
332
|
+
background: var(--primary-blue-200);
|
|
333
|
+
}
|
|
334
|
+
.base-file-upload__file-item-button-trash {
|
|
335
|
+
background: var(--error-red-light-04);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
&__file-item-wrapper {
|
|
341
|
+
display: flex;
|
|
342
|
+
align-items: center;
|
|
343
|
+
gap: 8px;
|
|
344
|
+
color: var(--primary-text-primary);
|
|
345
|
+
font: var(--typography-text-m-regular);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
&__file-item-button {
|
|
349
|
+
display: flex;
|
|
350
|
+
align-items: center;
|
|
351
|
+
justify-content: center;
|
|
352
|
+
background: transparent;
|
|
353
|
+
border-radius: var(--corner-radius-2xs);
|
|
354
|
+
padding: var(--spacing-xs);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
&__error {
|
|
358
|
+
color: var(--primary-red-500);
|
|
359
|
+
margin-top: 0.5rem;
|
|
360
|
+
font-size: var(--typography-text-s-regular);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
&__media-placeholder {
|
|
364
|
+
display: flex;
|
|
365
|
+
flex-direction: column;
|
|
366
|
+
align-items: center;
|
|
367
|
+
justify-content: center;
|
|
368
|
+
gap: var(--spacing-s);
|
|
369
|
+
border: 1px dashed var(--primary-black-300);
|
|
370
|
+
border-radius: var(--corner-radius-xs);
|
|
371
|
+
cursor: pointer;
|
|
372
|
+
background: var(--bg-light);
|
|
373
|
+
transition: all var(--transition);
|
|
374
|
+
|
|
375
|
+
&:hover {
|
|
376
|
+
background: var(--primary-black-200);
|
|
377
|
+
border-color: var(--primary-blue-500);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
&__placeholder-text {
|
|
382
|
+
color: var(--primary-text-tertiary);
|
|
383
|
+
font: var(--typography-text-s-regular);
|
|
384
|
+
margin: 0;
|
|
385
|
+
text-align: center;
|
|
386
|
+
|
|
387
|
+
span {
|
|
388
|
+
color: var(--primary-blue);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="image-modal">
|
|
3
|
+
<img :src="modalProps.imageUrl" alt="Enlarged Image" class="image-modal__image" />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
defineProps<{
|
|
9
|
+
modalProps: { closable?: boolean; imageUrl?: string };
|
|
10
|
+
}>();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<style lang="scss" scoped>
|
|
14
|
+
@import '../../styles/variables';
|
|
15
|
+
@import '../../styles/root';
|
|
16
|
+
|
|
17
|
+
.image-modal {
|
|
18
|
+
&__image {
|
|
19
|
+
max-width: 90vw;
|
|
20
|
+
max-height: 80vh;
|
|
21
|
+
object-fit: contain;
|
|
22
|
+
border-radius: var(--corner-radius-m);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { inject } from 'vue';
|
|
2
|
+
import type { ICoreModalProps, ModalComponent } from '../types/modal';
|
|
3
|
+
interface ModalApi {
|
|
4
|
+
open(id: string, props?: ICoreModalProps, component?: ModalComponent): void;
|
|
5
|
+
close(id: string): void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function useModal() {
|
|
9
|
+
const modal = inject<ModalApi>('$modal');
|
|
10
|
+
if (!modal) {
|
|
11
|
+
throw new Error('Modal plugin is not installed');
|
|
12
|
+
}
|
|
13
|
+
return modal;
|
|
14
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createPinia } from "pinia";
|
|
2
|
-
import Modal from "./components/Modal/Modal.vue";
|
|
3
2
|
import DataTable from "./components/DataTable/DataTable.vue";
|
|
4
3
|
import Tooltip from "./components/Tooltip/Tooltip.vue";
|
|
5
4
|
import Spinner from "./components/Spinner/Spinner.vue";
|
|
6
|
-
import ModalPlugin
|
|
5
|
+
import ModalPlugin from "./plugins/modalPlugin";
|
|
6
|
+
import { useModal } from "./composables/useModal";
|
|
7
7
|
import ToasterPlugin, { useToast } from "./plugins/toasterPlugin";
|
|
8
8
|
import "./sprite"; // Импортируем иконки для генерации спрайта
|
|
9
9
|
import "./styles/root.scss";
|
|
@@ -28,12 +28,22 @@ import BaseSiteInput from "./components/BaseSiteInput/BaseSiteInput.vue";
|
|
|
28
28
|
import BaseInputPhone from "./components/BaseInputPhone/BaseInputPhone.vue";
|
|
29
29
|
import BaseInputCurrency from "./components/BaseInputCurrency/BaseInputCurrency.vue";
|
|
30
30
|
import BaseSegmentedButtons from "./components/BaseSegmentedButtons/BaseSegmentedButtons.vue";
|
|
31
|
+
import BaseChips from "./components/BaseChips/BaseChips.vue";
|
|
32
|
+
import BaseSwiper from "./components/BaseSwiper/BaseSwiper.vue";
|
|
33
|
+
import BaseModal from "./components/BaseModal/BaseModal.vue";
|
|
34
|
+
import BaseUpload from "./components/BaseUpload/BaseUpload.vue";
|
|
35
|
+
import BaseBadge from "./components/BaseBadge/BaseBadge.vue";
|
|
36
|
+
import BaseTag from "./components/BaseTag/BaseTag.vue";
|
|
37
|
+
import BaseBadgeGroup from "./components/BaseBadge/BaseBadgeGroup.vue";
|
|
31
38
|
|
|
32
|
-
const components = {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
const components = {
|
|
40
|
+
BaseModal,
|
|
41
|
+
BaseTag,
|
|
42
|
+
BaseBadge,
|
|
43
|
+
BaseBadgeGroup,
|
|
44
|
+
DataTable,
|
|
45
|
+
Tooltip,
|
|
46
|
+
Spinner,
|
|
37
47
|
BaseIcon,
|
|
38
48
|
BaseBreadCrumbs,
|
|
39
49
|
BaseButton,
|
|
@@ -54,18 +64,21 @@ const components = {
|
|
|
54
64
|
BaseInputPhone,
|
|
55
65
|
BaseInputCurrency,
|
|
56
66
|
BasePagination,
|
|
57
|
-
BaseSegmentedButtons
|
|
67
|
+
BaseSegmentedButtons,
|
|
68
|
+
BaseChips,
|
|
69
|
+
BaseSwiper,
|
|
70
|
+
BaseUpload
|
|
58
71
|
};
|
|
59
72
|
|
|
60
73
|
// Функция для загрузки sprite.svg
|
|
61
74
|
const loadSprite = () => {
|
|
62
75
|
const possiblePaths = [
|
|
63
76
|
"/sprite.svg",
|
|
64
|
-
"./sprite.svg",
|
|
77
|
+
"./sprite.svg",
|
|
65
78
|
"sprite.svg",
|
|
66
|
-
"/dist/sprite.svg"
|
|
79
|
+
"/dist/sprite.svg",
|
|
67
80
|
];
|
|
68
|
-
|
|
81
|
+
|
|
69
82
|
const tryLoadSprite = async (paths: string[]) => {
|
|
70
83
|
for (const path of paths) {
|
|
71
84
|
try {
|
|
@@ -85,7 +98,7 @@ const loadSprite = () => {
|
|
|
85
98
|
}
|
|
86
99
|
console.error("Не удалось загрузить SVG-спрайт ни с одного из путей");
|
|
87
100
|
};
|
|
88
|
-
|
|
101
|
+
|
|
89
102
|
tryLoadSprite(possiblePaths);
|
|
90
103
|
};
|
|
91
104
|
|
|
@@ -107,12 +120,15 @@ export default {
|
|
|
107
120
|
},
|
|
108
121
|
};
|
|
109
122
|
|
|
110
|
-
export {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
123
|
+
export {
|
|
124
|
+
BaseModal,
|
|
125
|
+
BaseBadgeGroup,
|
|
126
|
+
BaseBadge,
|
|
127
|
+
DataTable,
|
|
128
|
+
BaseTag,
|
|
129
|
+
Tooltip,
|
|
130
|
+
Spinner,
|
|
131
|
+
useModal,
|
|
116
132
|
useToast,
|
|
117
133
|
BaseIcon,
|
|
118
134
|
BaseBreadCrumbs,
|
|
@@ -134,5 +150,8 @@ export {
|
|
|
134
150
|
BaseInputPhone,
|
|
135
151
|
BaseInputCurrency,
|
|
136
152
|
BasePagination,
|
|
137
|
-
BaseSegmentedButtons
|
|
153
|
+
BaseSegmentedButtons,
|
|
154
|
+
BaseChips,
|
|
155
|
+
BaseSwiper,
|
|
156
|
+
BaseUpload
|
|
138
157
|
};
|