plugin-ui-for-kzt 0.0.22 → 0.0.23
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 +1 -1
- package/dist/components/BaseButton/BaseButton.vue.d.ts +3 -3
- package/dist/components/BaseCheckbox/BaseCheckbox.vue.d.ts +4 -4
- package/dist/components/BaseDropdown/BaseDropdown.vue.d.ts +3 -3
- package/dist/components/BaseField/BaseField.vue.d.ts +2 -2
- package/dist/components/BaseInput/BaseInput.vue.d.ts +6 -6
- package/dist/components/BaseInputCalendar/BaseInputCalendar.vue.d.ts +5 -5
- package/dist/components/BaseInputCurrency/BaseInputCurrency.vue.d.ts +6 -6
- package/dist/components/BaseInputEmail/BaseInputEmail.vue.d.ts +5 -5
- package/dist/components/BaseInputPhone/BaseInputPhone.vue.d.ts +5 -5
- 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/BaseTabs/BaseTabs.vue.d.ts +25 -0
- package/dist/components/BaseTag/BaseTag.vue.d.ts +1 -1
- 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 +11 -0
- package/dist/components/BaseUpload/CropModal.vue.d.ts +9 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/index.js.LICENSE.txt +15 -0
- package/example/App.vue +37 -31
- package/example/TestImage.vue +6 -0
- package/package.json +2 -1
- package/src/components/BaseCheckbox/BaseCheckbox.vue +76 -46
- package/src/components/BaseRadio/BaseRadio.vue +266 -233
- package/src/components/BaseTabs/BaseTabs.vue +193 -0
- package/src/components/BaseUpload/BaseUpload.vue +35 -1
- package/src/components/BaseUpload/CropModal.vue +210 -0
- package/src/index.ts +5 -2
- package/src/types/tab.d.ts +17 -0
- package/src/types/uploadedFile.d.ts +7 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="base-tabs" :class="classList">
|
|
3
|
+
<div class="base-tabs__header">
|
|
4
|
+
<base-button
|
|
5
|
+
v-for="tab in tabs"
|
|
6
|
+
:key="tab.id"
|
|
7
|
+
size="custom"
|
|
8
|
+
color="custom"
|
|
9
|
+
class="base-tabs__tab"
|
|
10
|
+
:class="{ 'base-tabs__tab--active': activeTab === tab.id }"
|
|
11
|
+
@click="selectTab(tab.id)"
|
|
12
|
+
:disabled="tab.disabled"
|
|
13
|
+
>
|
|
14
|
+
<div v-if="tab.icon" class="base-tab__icon">
|
|
15
|
+
<component :is="tab.icon" />
|
|
16
|
+
</div>
|
|
17
|
+
<span>{{ tab.title }}</span>
|
|
18
|
+
</base-button>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="base-tabs__content">
|
|
21
|
+
<slot />
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
import { ref, computed, watch } from 'vue';
|
|
28
|
+
import type { TTabProps } from '../../types/tab.d';
|
|
29
|
+
import BaseButton from '../BaseButton/BaseButton.vue';
|
|
30
|
+
|
|
31
|
+
const props = withDefaults(defineProps<TTabProps>(), {
|
|
32
|
+
size: 'medium',
|
|
33
|
+
modelValue: 0,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const emit = defineEmits(['update:modelValue']);
|
|
37
|
+
|
|
38
|
+
const activeTab = ref(props.modelValue);
|
|
39
|
+
|
|
40
|
+
watch(() => props.modelValue, (newValue) => {
|
|
41
|
+
activeTab.value = newValue;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const selectTab = (id: number) => {
|
|
45
|
+
if (!props.tabs[id]?.disabled) {
|
|
46
|
+
activeTab.value = id;
|
|
47
|
+
emit('update:modelValue', id);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const classList = computed(() => [`base-tabs--${props.size}`]);
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<style lang="scss" scoped>
|
|
55
|
+
@import '../../styles/variables';
|
|
56
|
+
@import '../../styles/root';
|
|
57
|
+
|
|
58
|
+
.base-tabs {
|
|
59
|
+
width: 100%;
|
|
60
|
+
|
|
61
|
+
&__header {
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: stretch;
|
|
64
|
+
position: relative;
|
|
65
|
+
z-index: 1;
|
|
66
|
+
|
|
67
|
+
&::before {
|
|
68
|
+
content: '';
|
|
69
|
+
width: 100%;
|
|
70
|
+
border-bottom: 1px solid var(--primary-black-200);
|
|
71
|
+
position: absolute;
|
|
72
|
+
bottom: 0;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
&__tab {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
padding: var(--spacing-m) var(--spacing-l);
|
|
80
|
+
background: none;
|
|
81
|
+
border: none;
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
color: var(--primary-black-700);
|
|
84
|
+
transition: color 0.2s ease, border-color 0.2s ease;
|
|
85
|
+
white-space: nowrap;
|
|
86
|
+
position: relative;
|
|
87
|
+
|
|
88
|
+
@include hover {
|
|
89
|
+
& {
|
|
90
|
+
color: var(--primary-black);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@include pressed {
|
|
95
|
+
color: var(--primary-black);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@include is-disabled-state {
|
|
99
|
+
color: var(--primary-black-400);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&--active {
|
|
103
|
+
color: var(--primary-blue);
|
|
104
|
+
border-bottom: 2px solid var(--primary-blue);
|
|
105
|
+
z-index: 2;
|
|
106
|
+
|
|
107
|
+
@include hover {
|
|
108
|
+
& {
|
|
109
|
+
color: var(--primary-blue-700);
|
|
110
|
+
border-color: transparent;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@include pressed {
|
|
115
|
+
color: var(--primary-blue-deep);
|
|
116
|
+
border-color: transparent;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.base-tab__icon {
|
|
121
|
+
display: flex;
|
|
122
|
+
align-items: center;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Размеры
|
|
127
|
+
&--extra-small {
|
|
128
|
+
.base-tabs__header {
|
|
129
|
+
gap: var(--spacing-l);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.base-tabs__tab {
|
|
133
|
+
height: 38px;
|
|
134
|
+
padding: var(--spacing-s) var(--spacing-m);
|
|
135
|
+
font: var(--typography-text-s-medium);
|
|
136
|
+
gap: var(--spacing-s);
|
|
137
|
+
|
|
138
|
+
&--active {
|
|
139
|
+
font: var(--typography-text-s-semibold);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.base-tab__icon {
|
|
143
|
+
width: 20px;
|
|
144
|
+
height: 20px;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
&--small {
|
|
150
|
+
.base-tabs__header {
|
|
151
|
+
gap: var(--spacing-xl);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.base-tabs__tab {
|
|
155
|
+
height: 48px;
|
|
156
|
+
padding: var(--spacing-m) var(--spacing-l);
|
|
157
|
+
font: var(--typography-text-m-medium);
|
|
158
|
+
gap: var(--spacing-m);
|
|
159
|
+
|
|
160
|
+
&--active {
|
|
161
|
+
font: var(--typography-text-m-semibold);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.base-tab__icon {
|
|
165
|
+
width: 24px;
|
|
166
|
+
height: 24px;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
&--medium {
|
|
172
|
+
.base-tabs__header {
|
|
173
|
+
gap: var(--spacing-xl);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.base-tabs__tab {
|
|
177
|
+
height: 56px;
|
|
178
|
+
padding: var(--spacing-l) var(--spacing-xl);
|
|
179
|
+
font: var(--typography-text-l-medium);
|
|
180
|
+
gap: var(--spacing-m);
|
|
181
|
+
|
|
182
|
+
&--active {
|
|
183
|
+
font: var(--typography-text-l-semibold);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.base-tab__icon {
|
|
187
|
+
width: 32px;
|
|
188
|
+
height: 32px;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
</style>
|
|
@@ -111,10 +111,12 @@ import BaseIcon from '../BaseIcon/BaseIcon.vue';
|
|
|
111
111
|
import { useModal } from '../../composables/useModal';
|
|
112
112
|
import type { UploadedFile, IpropsUpload } from '../../types/uploadedFile.d';
|
|
113
113
|
import ImageModal from './ImageModal.vue';
|
|
114
|
+
import CropModal from './CropModal.vue';
|
|
114
115
|
|
|
115
116
|
const props = withDefaults(defineProps<IpropsUpload>(), {
|
|
116
117
|
multiple: true,
|
|
117
118
|
maxFileSize: 25 * 1024 * 1024, // 25 MB в байтах
|
|
119
|
+
enableCrop: false,
|
|
118
120
|
});
|
|
119
121
|
|
|
120
122
|
const emit = defineEmits(['update:files']);
|
|
@@ -141,6 +143,11 @@ const triggerFileInput = () => {
|
|
|
141
143
|
fileInput.value?.click();
|
|
142
144
|
};
|
|
143
145
|
|
|
146
|
+
const isImageFile = (file: File) => {
|
|
147
|
+
const fileExtension = `.${file.name.split('.').pop()?.toLowerCase() || ''}`;
|
|
148
|
+
return mediaExtensions.includes(fileExtension);
|
|
149
|
+
};
|
|
150
|
+
|
|
144
151
|
const handleFileUpload = (event: Event) => {
|
|
145
152
|
const target = event.target as HTMLInputElement;
|
|
146
153
|
const files = target.files;
|
|
@@ -161,7 +168,11 @@ const handleFileUpload = (event: Event) => {
|
|
|
161
168
|
return;
|
|
162
169
|
}
|
|
163
170
|
|
|
164
|
-
|
|
171
|
+
if (props.enableCrop && isImageFile(file)) {
|
|
172
|
+
openCropModal(file);
|
|
173
|
+
} else {
|
|
174
|
+
uploadedFiles.value.push({ name: file.name, size: file.size, file });
|
|
175
|
+
}
|
|
165
176
|
});
|
|
166
177
|
|
|
167
178
|
isUploading.value = false;
|
|
@@ -169,6 +180,29 @@ const handleFileUpload = (event: Event) => {
|
|
|
169
180
|
}
|
|
170
181
|
};
|
|
171
182
|
|
|
183
|
+
const openCropModal = (file: File) => {
|
|
184
|
+
const imageUrl = URL.createObjectURL(file);
|
|
185
|
+
|
|
186
|
+
modal.open('crop-modal', {
|
|
187
|
+
closable: false,
|
|
188
|
+
imageUrl,
|
|
189
|
+
fileName: file.name,
|
|
190
|
+
cancelText: props.cropTexts?.cancel,
|
|
191
|
+
confirmText: props.cropTexts?.confirm,
|
|
192
|
+
onConfirm: (croppedFile: File) => {
|
|
193
|
+
uploadedFiles.value.push({
|
|
194
|
+
name: croppedFile.name,
|
|
195
|
+
size: croppedFile.size,
|
|
196
|
+
file: croppedFile
|
|
197
|
+
});
|
|
198
|
+
URL.revokeObjectURL(imageUrl);
|
|
199
|
+
},
|
|
200
|
+
onCancel: () => {
|
|
201
|
+
URL.revokeObjectURL(imageUrl);
|
|
202
|
+
}
|
|
203
|
+
}, CropModal);
|
|
204
|
+
};
|
|
205
|
+
|
|
172
206
|
const removeFile = (index: number, isMedia: boolean) => {
|
|
173
207
|
const files = isMedia ? mediaFiles.value : otherFiles.value;
|
|
174
208
|
const globalIndex = uploadedFiles.value.indexOf(files[index]);
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="crop-modal">
|
|
3
|
+
<div class="crop-modal__container">
|
|
4
|
+
<div class="crop-modal__body">
|
|
5
|
+
<div class="crop-modal__cropper-container">
|
|
6
|
+
<Cropper
|
|
7
|
+
ref="cropperRef"
|
|
8
|
+
class="crop-modal__cropper"
|
|
9
|
+
:src="modalProps.imageUrl"
|
|
10
|
+
:stencil-props="{
|
|
11
|
+
aspectRatio: NaN,
|
|
12
|
+
movable: true,
|
|
13
|
+
resizable: true,
|
|
14
|
+
}"
|
|
15
|
+
:resize-image="{
|
|
16
|
+
adjustStencil: false
|
|
17
|
+
}"
|
|
18
|
+
/>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<div class="crop-modal__footer">
|
|
23
|
+
<base-button
|
|
24
|
+
color="secondary"
|
|
25
|
+
size="small"
|
|
26
|
+
@click="handleCancel"
|
|
27
|
+
class="crop-modal__button"
|
|
28
|
+
>
|
|
29
|
+
{{ modalProps.cancelText || 'Отменить' }}
|
|
30
|
+
</base-button>
|
|
31
|
+
|
|
32
|
+
<base-button
|
|
33
|
+
color="primary"
|
|
34
|
+
size="small"
|
|
35
|
+
@click="handleConfirm"
|
|
36
|
+
class="crop-modal__button"
|
|
37
|
+
>
|
|
38
|
+
{{ modalProps.confirmText || 'Применить' }}
|
|
39
|
+
</base-button>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</template>
|
|
44
|
+
|
|
45
|
+
<script setup lang="ts">
|
|
46
|
+
import {ref} from 'vue';
|
|
47
|
+
import {Cropper} from 'vue-advanced-cropper';
|
|
48
|
+
import 'vue-advanced-cropper/dist/style.css';
|
|
49
|
+
import BaseButton from '../BaseButton/BaseButton.vue';
|
|
50
|
+
import {useModal} from '../../composables/useModal';
|
|
51
|
+
|
|
52
|
+
interface CropModalProps {
|
|
53
|
+
modalProps: {
|
|
54
|
+
imageUrl: string;
|
|
55
|
+
fileName: string;
|
|
56
|
+
onConfirm: (croppedFile: File) => void;
|
|
57
|
+
onCancel: () => void;
|
|
58
|
+
cancelText?: string;
|
|
59
|
+
confirmText?: string;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const props = defineProps<CropModalProps>();
|
|
64
|
+
const modal = useModal();
|
|
65
|
+
|
|
66
|
+
const cropperRef = ref();
|
|
67
|
+
|
|
68
|
+
const handleCancel = () => {
|
|
69
|
+
props.modalProps.onCancel();
|
|
70
|
+
modal.close('crop-modal');
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const handleConfirm = () => {
|
|
74
|
+
if (!cropperRef.value) return;
|
|
75
|
+
|
|
76
|
+
const {canvas} = cropperRef.value.getResult();
|
|
77
|
+
|
|
78
|
+
if (canvas) {
|
|
79
|
+
canvas.toBlob((blob: Blob | null) => {
|
|
80
|
+
if (blob) {
|
|
81
|
+
const croppedFile = new File([blob], props.modalProps.fileName, {
|
|
82
|
+
type: 'image/jpeg',
|
|
83
|
+
lastModified: Date.now(),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
props.modalProps.onConfirm(croppedFile);
|
|
87
|
+
modal.close('crop-modal');
|
|
88
|
+
}
|
|
89
|
+
}, 'image/jpeg', 0.9);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
</script>
|
|
93
|
+
|
|
94
|
+
<style lang="scss" scoped>
|
|
95
|
+
@import '../../styles/variables';
|
|
96
|
+
@import '../../styles/root';
|
|
97
|
+
|
|
98
|
+
.crop-modal {
|
|
99
|
+
display: flex;
|
|
100
|
+
align-items: center;
|
|
101
|
+
justify-content: center;
|
|
102
|
+
max-width: 588px;
|
|
103
|
+
max-height: 776px;
|
|
104
|
+
|
|
105
|
+
@media #{$mobile-max-576} {
|
|
106
|
+
max-width: 100%;
|
|
107
|
+
width: 100%;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
&__container {
|
|
111
|
+
width: 100%;
|
|
112
|
+
background: rgba(0, 0, 0, 0.3);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
&__body {
|
|
116
|
+
flex: 1;
|
|
117
|
+
overflow: hidden;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
&__cropper-container {
|
|
121
|
+
height: 500px;
|
|
122
|
+
width: 100%;
|
|
123
|
+
overflow: hidden;
|
|
124
|
+
display: flex;
|
|
125
|
+
align-items: center;
|
|
126
|
+
|
|
127
|
+
@media #{$mobile-max-375} {
|
|
128
|
+
overflow: unset;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
&__footer {
|
|
133
|
+
display: flex;
|
|
134
|
+
gap: var(--spacing-xl);
|
|
135
|
+
justify-content: space-between;
|
|
136
|
+
padding: var(--spacing-xl);
|
|
137
|
+
background-color: var(--primary-black-white);
|
|
138
|
+
|
|
139
|
+
@media #{$mobile-max-576} {
|
|
140
|
+
flex-direction: column;
|
|
141
|
+
justify-content: center;
|
|
142
|
+
gap: var(--spacing-l);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
&__button {
|
|
147
|
+
min-width: 258px;
|
|
148
|
+
|
|
149
|
+
@media #{$mobile-landscape} {
|
|
150
|
+
min-width: unset;
|
|
151
|
+
width: 100%;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
::v-deep(.vue-advanced-cropper__background) {
|
|
157
|
+
background: rgba(0, 0, 0, 0.3);
|
|
158
|
+
width: 100%;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
::v-deep(.vue-advanced-cropper__foreground) {
|
|
162
|
+
border-color: var(--primary-blue);
|
|
163
|
+
background: rgba(0, 0, 0, 0.3);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
::v-deep(.vue-simple-handler) {
|
|
167
|
+
background: var(--primary-blue);
|
|
168
|
+
border-color: white;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
::v-deep(.vue-simple-handler:hover) {
|
|
172
|
+
background: var(--primary-blue-deep);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
::v-deep(.vue-simple-line) {
|
|
176
|
+
border-color: var(--primary-blue);
|
|
177
|
+
}
|
|
178
|
+
</style>
|
|
179
|
+
|
|
180
|
+
<style lang="scss">
|
|
181
|
+
@import '../../styles/variables';
|
|
182
|
+
@import '../../styles/root';
|
|
183
|
+
|
|
184
|
+
.base-modal:has(.crop-modal) {
|
|
185
|
+
@media screen and (max-width: 375px) {
|
|
186
|
+
max-height: unset !important;
|
|
187
|
+
height: 100vh !important;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.base-modal__content:has(.crop-modal) {
|
|
192
|
+
width: 100% !important;
|
|
193
|
+
|
|
194
|
+
@media screen and (max-width: 375px) {
|
|
195
|
+
overflow-y: unset !important;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.base-modal__wrapper:has(.crop-modal) {
|
|
200
|
+
padding: 0 !important;
|
|
201
|
+
|
|
202
|
+
@media #{$mobile-max-767} {
|
|
203
|
+
padding: 0 !important;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@media screen and (max-width: 375px) {
|
|
207
|
+
justify-content: start !important;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
</style>
|
package/src/index.ts
CHANGED
|
@@ -36,6 +36,7 @@ import BaseBadge from "./components/BaseBadge/BaseBadge.vue";
|
|
|
36
36
|
import BaseTag from "./components/BaseTag/BaseTag.vue";
|
|
37
37
|
import BaseBadgeGroup from "./components/BaseBadge/BaseBadgeGroup.vue";
|
|
38
38
|
import BaseField from "./components/BaseField/BaseField.vue";
|
|
39
|
+
import BaseTabs from "./components/BaseTabs/BaseTabs.vue";
|
|
39
40
|
|
|
40
41
|
const components = {
|
|
41
42
|
BaseModal,
|
|
@@ -69,7 +70,8 @@ const components = {
|
|
|
69
70
|
BaseChips,
|
|
70
71
|
BaseSwiper,
|
|
71
72
|
BaseUpload,
|
|
72
|
-
BaseField
|
|
73
|
+
BaseField,
|
|
74
|
+
BaseTabs
|
|
73
75
|
};
|
|
74
76
|
|
|
75
77
|
// Функция для загрузки sprite.svg
|
|
@@ -156,5 +158,6 @@ export {
|
|
|
156
158
|
BaseChips,
|
|
157
159
|
BaseSwiper,
|
|
158
160
|
BaseUpload,
|
|
159
|
-
BaseField
|
|
161
|
+
BaseField,
|
|
162
|
+
BaseTabs
|
|
160
163
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ICoreSize } from './utils';
|
|
2
|
+
|
|
3
|
+
type IconComponent = Component | (new () => Component) | (() => Promise<{ default: Component }>);
|
|
4
|
+
|
|
5
|
+
interface ITab {
|
|
6
|
+
title: string;
|
|
7
|
+
id: number;
|
|
8
|
+
icon?: IconComponent;
|
|
9
|
+
disabled?: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface ITabs {
|
|
13
|
+
tabs: ITab[];
|
|
14
|
+
modelValue: number,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type TTabProps = ICoreSize & ITabs
|
|
@@ -4,10 +4,17 @@ export interface UploadedFile {
|
|
|
4
4
|
file: File;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
export interface CropTexts {
|
|
8
|
+
cancel?: string;
|
|
9
|
+
confirm?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
7
12
|
export interface IpropsUpload {
|
|
8
13
|
acceptedFormats: string[]; // Фильтр по типу файлов (например, "image/*" для изображений)
|
|
9
14
|
multiple?: boolean; // Разрешить множественный выбор файлов
|
|
10
15
|
maxFileSize?: number; // Максимальный размер файла в байтах
|
|
16
|
+
enableCrop?: boolean; // Включить функциональность кропа для изображений
|
|
17
|
+
cropTexts?: CropTexts; // Тексты для кнопок в модальном окне кропа
|
|
11
18
|
onUpload?: (files: UploadedFile[]) => void; // Callback при загрузке файлов
|
|
12
19
|
onError?: (error: string) => void; // Callback при ошибке загрузки
|
|
13
20
|
}
|