plugin-ui-for-kzt 0.0.23 → 0.0.25
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/assets/0e28e37419c99ac65b12.png +0 -0
- package/dist/assets/264165b2b0e8a6840eb0.png +0 -0
- package/dist/components/{DataTable/DataTable.vue.d.ts → BaseDefaultPages/BaseDefaultPages.vue.d.ts} +8 -6
- package/dist/components/BaseInput/BaseInput.vue.d.ts +1 -1
- package/dist/components/{Tooltip/Tooltip.vue.d.ts → BasePageLoader/BasePageLoader.vue.d.ts} +24 -11
- package/dist/components/BaseTable/BaseTable.vue.d.ts +44 -0
- package/dist/components/BaseToast/BaseToast.vue.d.ts +69 -0
- package/dist/composables/useToast.d.ts +2 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.js +1 -1
- package/dist/plugins/toastPlugin.d.ts +4 -0
- package/dist/sprite.svg +1 -1
- package/dist/store/toast.d.ts +8 -0
- package/example/App.vue +196 -29
- package/package.json +1 -1
- package/src/assets/404.png +0 -0
- package/src/assets/icons/arrow-down-stick.svg +4 -0
- package/src/assets/icons/edit-table.svg +5 -0
- package/src/assets/icons/ellipsis.svg +5 -0
- package/src/assets/icons/loading-page-default.svg +4 -0
- package/src/assets/icons/loading-page-error.svg +6 -0
- package/src/assets/icons/loading-page-success.svg +5 -0
- package/src/assets/icons/loading-page-warning.svg +6 -0
- package/src/assets/icons/more-dots.svg +5 -0
- package/src/assets/icons/time-table.svg +7 -0
- package/src/assets/icons/toast-error.svg +3 -0
- package/src/assets/icons/toast-info.svg +3 -0
- package/src/assets/icons/toast-success.svg +3 -0
- package/src/assets/icons/toast-warning.svg +3 -0
- package/src/assets/icons/trash-table.svg +7 -0
- package/src/assets/tech-work.png +0 -0
- package/src/components/BaseChips/BaseChips.vue +3 -1
- package/src/components/BaseDefaultPages/BaseDefaultPages.vue +140 -0
- package/src/components/BaseDefaultPages/README.md +128 -0
- package/src/components/BaseOpenedListItem/BaseOpenedListItem.vue +3 -3
- package/src/components/BasePageLoader/BasePageLoader.vue +211 -0
- package/src/components/BasePageLoader/README.md +80 -0
- package/src/components/BaseSelect/BaseSelect.vue +7 -3
- package/src/components/BaseTable/BaseTable.vue +411 -0
- package/src/components/BaseTable/README.md +294 -0
- package/src/components/BaseToast/BaseToast.vue +200 -0
- package/src/components/BaseToast/README.md +103 -0
- package/src/components/BaseTooltip/BaseTooltip.vue +1 -0
- package/src/components/BaseUpload/BaseUpload.vue +1 -1
- package/src/composables/useToast.ts +10 -0
- package/src/index.ts +17 -13
- package/src/plugins/toastPlugin.ts +100 -0
- package/src/store/toast.ts +59 -0
- package/src/styles/root.scss +2 -0
- package/src/styles/toast.scss +36 -0
- package/src/types/default-pages.d.ts +6 -0
- package/src/types/loading-page.d.ts +12 -0
- package/src/types/pagination.d.ts +1 -0
- package/src/types/table.d.ts +33 -0
- package/src/types/toast.d.ts +25 -0
- package/webpack.config.js +12 -0
- package/dist/components/Spinner/Spinner.vue.d.ts +0 -20
- package/dist/components/Toaster/Toaster.vue.d.ts +0 -80
- package/dist/components/Toaster/timer.d.ts +0 -12
- package/dist/plugins/toasterPlugin.d.ts +0 -26
- package/src/components/DataTable/DataTable.vue +0 -169
- package/src/components/DataTable/README.md +0 -57
- package/src/components/Spinner/README.md +0 -35
- package/src/components/Spinner/Spinner.vue +0 -60
- package/src/components/Toaster/README.md +0 -70
- package/src/components/Toaster/Toaster.vue +0 -235
- package/src/components/Toaster/timer.ts +0 -45
- package/src/components/Tooltip/README.md +0 -37
- package/src/components/Tooltip/Tooltip.vue +0 -96
- package/src/components/icons/CloseIcon.vue +0 -5
- package/src/components/icons/ErrorIcon.vue +0 -7
- package/src/components/icons/InfoIcon.vue +0 -7
- package/src/components/icons/SuccessIcon.vue +0 -6
- package/src/components/icons/WarningIcon.vue +0 -7
- package/src/plugins/toasterPlugin.ts +0 -179
package/src/index.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { createPinia } from "pinia";
|
|
2
|
-
import DataTable from "./components/DataTable/DataTable.vue";
|
|
3
|
-
import Tooltip from "./components/Tooltip/Tooltip.vue";
|
|
4
|
-
import Spinner from "./components/Spinner/Spinner.vue";
|
|
5
2
|
import ModalPlugin from "./plugins/modalPlugin";
|
|
6
3
|
import { useModal } from "./composables/useModal";
|
|
7
|
-
import
|
|
4
|
+
import { useToast } from "./composables/useToast";
|
|
5
|
+
import ToastPlugin from "./plugins/toastPlugin";
|
|
8
6
|
import "./sprite"; // Импортируем иконки для генерации спрайта
|
|
9
7
|
import "./styles/root.scss";
|
|
10
8
|
import BaseIcon from "./components/BaseIcon/BaseIcon.vue";
|
|
@@ -36,16 +34,17 @@ import BaseBadge from "./components/BaseBadge/BaseBadge.vue";
|
|
|
36
34
|
import BaseTag from "./components/BaseTag/BaseTag.vue";
|
|
37
35
|
import BaseBadgeGroup from "./components/BaseBadge/BaseBadgeGroup.vue";
|
|
38
36
|
import BaseField from "./components/BaseField/BaseField.vue";
|
|
37
|
+
import BaseToast from "./components/BaseToast/BaseToast.vue";
|
|
38
|
+
import BasePageLoader from "./components/BasePageLoader/BasePageLoader.vue";
|
|
39
39
|
import BaseTabs from "./components/BaseTabs/BaseTabs.vue";
|
|
40
|
+
import BaseTable from "./components/BaseTable/BaseTable.vue";
|
|
41
|
+
import BaseDefaultPages from "./components/BaseDefaultPages/BaseDefaultPages.vue";
|
|
40
42
|
|
|
41
43
|
const components = {
|
|
42
44
|
BaseModal,
|
|
43
45
|
BaseTag,
|
|
44
46
|
BaseBadge,
|
|
45
47
|
BaseBadgeGroup,
|
|
46
|
-
DataTable,
|
|
47
|
-
Tooltip,
|
|
48
|
-
Spinner,
|
|
49
48
|
BaseIcon,
|
|
50
49
|
BaseBreadCrumbs,
|
|
51
50
|
BaseButton,
|
|
@@ -71,7 +70,11 @@ const components = {
|
|
|
71
70
|
BaseSwiper,
|
|
72
71
|
BaseUpload,
|
|
73
72
|
BaseField,
|
|
74
|
-
|
|
73
|
+
BaseToast,
|
|
74
|
+
BasePageLoader,
|
|
75
|
+
BaseTabs,
|
|
76
|
+
BaseTable,
|
|
77
|
+
BaseDefaultPages
|
|
75
78
|
};
|
|
76
79
|
|
|
77
80
|
// Функция для загрузки sprite.svg
|
|
@@ -120,7 +123,7 @@ export default {
|
|
|
120
123
|
loadSprite();
|
|
121
124
|
|
|
122
125
|
app.use(ModalPlugin);
|
|
123
|
-
app.use(
|
|
126
|
+
app.use(ToastPlugin);
|
|
124
127
|
},
|
|
125
128
|
};
|
|
126
129
|
|
|
@@ -128,10 +131,7 @@ export {
|
|
|
128
131
|
BaseModal,
|
|
129
132
|
BaseBadgeGroup,
|
|
130
133
|
BaseBadge,
|
|
131
|
-
DataTable,
|
|
132
134
|
BaseTag,
|
|
133
|
-
Tooltip,
|
|
134
|
-
Spinner,
|
|
135
135
|
useModal,
|
|
136
136
|
useToast,
|
|
137
137
|
BaseIcon,
|
|
@@ -159,5 +159,9 @@ export {
|
|
|
159
159
|
BaseSwiper,
|
|
160
160
|
BaseUpload,
|
|
161
161
|
BaseField,
|
|
162
|
-
|
|
162
|
+
BaseToast,
|
|
163
|
+
BasePageLoader,
|
|
164
|
+
BaseTabs,
|
|
165
|
+
BaseTable,
|
|
166
|
+
BaseDefaultPages
|
|
163
167
|
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createApp, h, provide, defineComponent } from 'vue';
|
|
2
|
+
import { useToastStore } from '../store/toast';
|
|
3
|
+
import BaseToast from '../components/BaseToast/BaseToast.vue';
|
|
4
|
+
import { watch, ref } from 'vue';
|
|
5
|
+
import type { IBaseToastProps } from '../types/toast';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
install(app: any) {
|
|
9
|
+
console.log('Installing ToastPlugin...');
|
|
10
|
+
const toastStore = useToastStore();
|
|
11
|
+
|
|
12
|
+
let toastContainer = document.querySelector('.toast-container');
|
|
13
|
+
if (!toastContainer) {
|
|
14
|
+
toastContainer = document.createElement('div');
|
|
15
|
+
toastContainer.classList.add('toast-container');
|
|
16
|
+
document.body.appendChild(toastContainer);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const $toast = {
|
|
20
|
+
show(id: string, props: IBaseToastProps) {
|
|
21
|
+
toastStore.addToast(id, props);
|
|
22
|
+
},
|
|
23
|
+
hide(id: string) {
|
|
24
|
+
toastStore.removeToast(id);
|
|
25
|
+
},
|
|
26
|
+
clear() {
|
|
27
|
+
toastStore.clearToasts();
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
app.config.globalProperties.$toast = $toast;
|
|
32
|
+
app.provide('$toast', $toast);
|
|
33
|
+
|
|
34
|
+
const ToastContainerComponent = defineComponent({
|
|
35
|
+
setup() {
|
|
36
|
+
provide('$toast', $toast);
|
|
37
|
+
const toasts = ref(toastStore.toasts);
|
|
38
|
+
|
|
39
|
+
watch(
|
|
40
|
+
() => toastStore.toasts,
|
|
41
|
+
(newToasts) => {
|
|
42
|
+
toasts.value = newToasts;
|
|
43
|
+
},
|
|
44
|
+
{ deep: true }
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return () =>
|
|
48
|
+
h(
|
|
49
|
+
'div',
|
|
50
|
+
{ class: 'toast-container-inner', 'data-has-toasts': toasts.value.some(t => t.isOpen) },
|
|
51
|
+
h(
|
|
52
|
+
'transition-group',
|
|
53
|
+
{ name: 'toast', tag: 'div' },
|
|
54
|
+
toasts.value.map(toast =>
|
|
55
|
+
h(
|
|
56
|
+
BaseToast,
|
|
57
|
+
{
|
|
58
|
+
key: toast.id,
|
|
59
|
+
...toast.props,
|
|
60
|
+
isOpen: toast.isOpen,
|
|
61
|
+
onClose: () => toastStore.removeToast(toast.id),
|
|
62
|
+
onPrimaryAction: () => toastStore.removeToast(toast.id),
|
|
63
|
+
onSecondaryAction: () => toastStore.removeToast(toast.id),
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
);
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
let toastApp = (toastContainer as any).__vue_app__;
|
|
73
|
+
if (!toastApp) {
|
|
74
|
+
toastApp = createApp(ToastContainerComponent);
|
|
75
|
+
toastApp.mount(toastContainer);
|
|
76
|
+
(toastContainer as any).__vue_app__ = toastApp;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
window.addEventListener('popstate', () => {
|
|
80
|
+
toastStore.clearToasts();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const cleanup = () => {
|
|
84
|
+
toastApp.unmount();
|
|
85
|
+
window.removeEventListener('popstate', () => toastStore.clearToasts());
|
|
86
|
+
if (document.body.contains(toastContainer)) {
|
|
87
|
+
document.body.removeChild(toastContainer);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
if (app.unmount) {
|
|
92
|
+
const originalUnmount = app.unmount;
|
|
93
|
+
app.unmount = function () {
|
|
94
|
+
cleanup();
|
|
95
|
+
originalUnmount.call(app);
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
app._container?.addEventListener('beforeunload', cleanup);
|
|
99
|
+
},
|
|
100
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { defineStore } from 'pinia';
|
|
2
|
+
import type { IBaseToastProps, IToast } from '../types/toast';
|
|
3
|
+
|
|
4
|
+
export const useToastStore = defineStore('toast', {
|
|
5
|
+
state: () => ({
|
|
6
|
+
toasts: [] as IToast[],
|
|
7
|
+
}),
|
|
8
|
+
actions: {
|
|
9
|
+
addToast(id: string, props: IBaseToastProps) {
|
|
10
|
+
const messageLength = (props.title + (props.description || '')).length;
|
|
11
|
+
const duration = props.duration ?? (messageLength > 80 ? 10000 : 5000);
|
|
12
|
+
|
|
13
|
+
const existingToastIndex = this.toasts.findIndex(t => t.id === id);
|
|
14
|
+
if (existingToastIndex !== -1) {
|
|
15
|
+
const existingToast = this.toasts[existingToastIndex];
|
|
16
|
+
if (existingToast.timeoutId) {
|
|
17
|
+
clearTimeout(existingToast.timeoutId);
|
|
18
|
+
}
|
|
19
|
+
this.toasts.splice(existingToastIndex, 1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const maxToasts = window.innerWidth <= 768 ? 3 : 4;
|
|
23
|
+
if (this.toasts.length >= maxToasts) {
|
|
24
|
+
const oldestToast = this.toasts.shift();
|
|
25
|
+
if (oldestToast?.timeoutId) {
|
|
26
|
+
clearTimeout(oldestToast.timeoutId);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const toast: IToast = { id, props, isOpen: true };
|
|
31
|
+
this.toasts.push(toast);
|
|
32
|
+
|
|
33
|
+
toast.timeoutId = window.setTimeout(() => {
|
|
34
|
+
this.removeToast(id);
|
|
35
|
+
}, duration);
|
|
36
|
+
},
|
|
37
|
+
removeToast(id: string) {
|
|
38
|
+
const index = this.toasts.findIndex(t => t.id === id);
|
|
39
|
+
if (index !== -1) {
|
|
40
|
+
this.toasts[index].isOpen = false;
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
const toast = this.toasts[index];
|
|
43
|
+
if (toast?.timeoutId) {
|
|
44
|
+
clearTimeout(toast.timeoutId);
|
|
45
|
+
}
|
|
46
|
+
this.toasts.splice(index, 1);
|
|
47
|
+
}, 300);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
clearToasts() {
|
|
51
|
+
this.toasts.forEach(toast => {
|
|
52
|
+
if (toast.timeoutId) {
|
|
53
|
+
clearTimeout(toast.timeoutId);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
this.toasts = [];
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
});
|
package/src/styles/root.scss
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
.toast-container {
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 20px;
|
|
4
|
+
right: 20px;
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
gap: 8px;
|
|
8
|
+
z-index: 10000; // Высокий z-index для отображения поверх контента
|
|
9
|
+
max-width: 620px;
|
|
10
|
+
|
|
11
|
+
@media (max-width: 768px) {
|
|
12
|
+
right: 8px;
|
|
13
|
+
left: 8px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.toast-container-inner {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
gap: 8px;
|
|
20
|
+
|
|
21
|
+
&[data-has-toasts='true'] {
|
|
22
|
+
display: flex;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.toast-enter-active,
|
|
28
|
+
.toast-leave-active {
|
|
29
|
+
transition: all 0.3s ease;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.toast-enter-from,
|
|
33
|
+
.toast-leave-to {
|
|
34
|
+
transform: translateY(100%);
|
|
35
|
+
opacity: 0;
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ICoreSize } from './utils';
|
|
2
|
+
|
|
3
|
+
type TIconType = 'success' | 'error' | 'warning';
|
|
4
|
+
|
|
5
|
+
export interface IPageLoaderProps {
|
|
6
|
+
loading: boolean;
|
|
7
|
+
iconType?: TIconType;
|
|
8
|
+
message?: string;
|
|
9
|
+
modal?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type TPageLoaderProps = IPageLoaderProps & ICoreSize;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Component } from 'vue'
|
|
2
|
+
import type { TPaginationProps } from './pagination'
|
|
3
|
+
|
|
4
|
+
export type Row = Record<string, unknown>
|
|
5
|
+
|
|
6
|
+
export interface Column {
|
|
7
|
+
key: string
|
|
8
|
+
label?: string
|
|
9
|
+
sortable?: boolean
|
|
10
|
+
icons?: Component[]
|
|
11
|
+
dropdownVisible?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface Action {
|
|
15
|
+
key: string
|
|
16
|
+
icon: string | Component
|
|
17
|
+
label?: string
|
|
18
|
+
handler: (row: Row) => void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface BaseTableProps {
|
|
22
|
+
columns: Column[]
|
|
23
|
+
data: Row[]
|
|
24
|
+
rowKey?: keyof Row | ((row: Row) => unknown)
|
|
25
|
+
showRowSelection?: boolean
|
|
26
|
+
checkboxTitle?: string
|
|
27
|
+
showActions?: boolean
|
|
28
|
+
actions?: Action[]
|
|
29
|
+
pagination?: TPaginationProps
|
|
30
|
+
subTable?: {
|
|
31
|
+
slotName: string
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface IBaseToastProps {
|
|
2
|
+
title: string;
|
|
3
|
+
type?: 'info' | 'success' | 'warning' | 'error';
|
|
4
|
+
withBackground?: boolean;
|
|
5
|
+
description?: string;
|
|
6
|
+
showIcon?: boolean;
|
|
7
|
+
closable?: boolean;
|
|
8
|
+
primaryActionText?: string;
|
|
9
|
+
secondaryActionText?: string;
|
|
10
|
+
isOpen?: boolean;
|
|
11
|
+
duration?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface IToast {
|
|
15
|
+
id: string;
|
|
16
|
+
props: IBaseToastProps;
|
|
17
|
+
isOpen: boolean;
|
|
18
|
+
timeoutId?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface IToastApi {
|
|
22
|
+
show(id: string, props: IBaseToastProps): void;
|
|
23
|
+
hide(id: string): void;
|
|
24
|
+
clear(): void;
|
|
25
|
+
}
|
package/webpack.config.js
CHANGED
|
@@ -86,6 +86,18 @@ module.exports = (env, argv) => {
|
|
|
86
86
|
},
|
|
87
87
|
],
|
|
88
88
|
},
|
|
89
|
+
{
|
|
90
|
+
test: /\.(png|jpe?g|gif|webp)$/i,
|
|
91
|
+
type: "asset",
|
|
92
|
+
parser: {
|
|
93
|
+
dataUrlCondition: {
|
|
94
|
+
maxSize: 8 * 1024,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
generator: {
|
|
98
|
+
filename: "assets/[hash][ext][query]",
|
|
99
|
+
},
|
|
100
|
+
},
|
|
89
101
|
],
|
|
90
102
|
},
|
|
91
103
|
plugins: [new VueLoaderPlugin(), new SpriteLoaderPlugin()],
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
2
|
-
show: {
|
|
3
|
-
type: BooleanConstructor;
|
|
4
|
-
};
|
|
5
|
-
size: {};
|
|
6
|
-
color: {};
|
|
7
|
-
thickness: {};
|
|
8
|
-
}>, (_ctx: any, _cache: any) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
9
|
-
[key: string]: any;
|
|
10
|
-
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
11
|
-
show: {
|
|
12
|
-
type: BooleanConstructor;
|
|
13
|
-
};
|
|
14
|
-
size: {};
|
|
15
|
-
color: {};
|
|
16
|
-
thickness: {};
|
|
17
|
-
}>> & Readonly<{}>, {
|
|
18
|
-
show: boolean;
|
|
19
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
20
|
-
export default _default;
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
2
|
-
message: {
|
|
3
|
-
default: string;
|
|
4
|
-
};
|
|
5
|
-
type: {
|
|
6
|
-
default: string;
|
|
7
|
-
};
|
|
8
|
-
position: {
|
|
9
|
-
default: string;
|
|
10
|
-
};
|
|
11
|
-
dismissible: {
|
|
12
|
-
type: BooleanConstructor;
|
|
13
|
-
default: boolean;
|
|
14
|
-
};
|
|
15
|
-
onDismiss: {
|
|
16
|
-
type: FunctionConstructor;
|
|
17
|
-
default: () => void;
|
|
18
|
-
};
|
|
19
|
-
onClick: {
|
|
20
|
-
type: FunctionConstructor;
|
|
21
|
-
default: () => void;
|
|
22
|
-
};
|
|
23
|
-
pauseOnHover: {
|
|
24
|
-
type: BooleanConstructor;
|
|
25
|
-
default: boolean;
|
|
26
|
-
};
|
|
27
|
-
duration: {
|
|
28
|
-
default: number;
|
|
29
|
-
};
|
|
30
|
-
onHeightUpdate: {
|
|
31
|
-
type: FunctionConstructor;
|
|
32
|
-
default: () => void;
|
|
33
|
-
};
|
|
34
|
-
}>, (_ctx: any, _cache: any) => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
35
|
-
[key: string]: any;
|
|
36
|
-
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
37
|
-
message: {
|
|
38
|
-
default: string;
|
|
39
|
-
};
|
|
40
|
-
type: {
|
|
41
|
-
default: string;
|
|
42
|
-
};
|
|
43
|
-
position: {
|
|
44
|
-
default: string;
|
|
45
|
-
};
|
|
46
|
-
dismissible: {
|
|
47
|
-
type: BooleanConstructor;
|
|
48
|
-
default: boolean;
|
|
49
|
-
};
|
|
50
|
-
onDismiss: {
|
|
51
|
-
type: FunctionConstructor;
|
|
52
|
-
default: () => void;
|
|
53
|
-
};
|
|
54
|
-
onClick: {
|
|
55
|
-
type: FunctionConstructor;
|
|
56
|
-
default: () => void;
|
|
57
|
-
};
|
|
58
|
-
pauseOnHover: {
|
|
59
|
-
type: BooleanConstructor;
|
|
60
|
-
default: boolean;
|
|
61
|
-
};
|
|
62
|
-
duration: {
|
|
63
|
-
default: number;
|
|
64
|
-
};
|
|
65
|
-
onHeightUpdate: {
|
|
66
|
-
type: FunctionConstructor;
|
|
67
|
-
default: () => void;
|
|
68
|
-
};
|
|
69
|
-
}>> & Readonly<{}>, {
|
|
70
|
-
onClick: Function;
|
|
71
|
-
type: string;
|
|
72
|
-
message: string;
|
|
73
|
-
position: string;
|
|
74
|
-
duration: number;
|
|
75
|
-
dismissible: boolean;
|
|
76
|
-
pauseOnHover: boolean;
|
|
77
|
-
onDismiss: Function;
|
|
78
|
-
onHeightUpdate: Function;
|
|
79
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
80
|
-
export default _default;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
declare class Timer {
|
|
2
|
-
private timerId;
|
|
3
|
-
private start;
|
|
4
|
-
private remaining;
|
|
5
|
-
private callback;
|
|
6
|
-
constructor(callback: () => void, delay: number);
|
|
7
|
-
pause(): void;
|
|
8
|
-
resume(): void;
|
|
9
|
-
clear(): void;
|
|
10
|
-
reset(delay: number): void;
|
|
11
|
-
}
|
|
12
|
-
export default Timer;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
interface ToastOptions {
|
|
2
|
-
position?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
3
|
-
duration?: number;
|
|
4
|
-
dismissible?: boolean;
|
|
5
|
-
pauseOnHover?: boolean;
|
|
6
|
-
}
|
|
7
|
-
declare const _default: {
|
|
8
|
-
install(app: any): void;
|
|
9
|
-
};
|
|
10
|
-
export default _default;
|
|
11
|
-
export declare function useToast(): {
|
|
12
|
-
success: (message: string, options?: ToastOptions) => void;
|
|
13
|
-
error: (message: string, options?: ToastOptions) => void;
|
|
14
|
-
info: (message: string, options?: ToastOptions) => void;
|
|
15
|
-
warning: (message: string, options?: ToastOptions) => void;
|
|
16
|
-
} | undefined;
|
|
17
|
-
declare module "@vue/runtime-core" {
|
|
18
|
-
interface ComponentCustomProperties {
|
|
19
|
-
$toast: {
|
|
20
|
-
success: (message: string, options?: ToastOptions) => void;
|
|
21
|
-
error: (message: string, options?: ToastOptions) => void;
|
|
22
|
-
info: (message: string, options?: ToastOptions) => void;
|
|
23
|
-
warning: (message: string, options?: ToastOptions) => void;
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="table-container">
|
|
3
|
-
<div class="search-container">
|
|
4
|
-
<input
|
|
5
|
-
type="text"
|
|
6
|
-
placeholder="Поиск..."
|
|
7
|
-
:value="searchQuery"
|
|
8
|
-
@input="handleSearchInput"
|
|
9
|
-
/>
|
|
10
|
-
<p v-if="!searchExists">Ничего не найдено</p>
|
|
11
|
-
</div>
|
|
12
|
-
|
|
13
|
-
<table v-if="searchExists">
|
|
14
|
-
<thead>
|
|
15
|
-
<tr>
|
|
16
|
-
<th v-for="column in props.columns" :key="column.key">
|
|
17
|
-
{{ column.label }}
|
|
18
|
-
</th>
|
|
19
|
-
</tr>
|
|
20
|
-
</thead>
|
|
21
|
-
<tbody>
|
|
22
|
-
<tr v-for="(row, rowIndex) in paginatedRows" :key="rowIndex">
|
|
23
|
-
<td v-for="column in props.columns" :key="column.key">
|
|
24
|
-
{{ row[column.key] }}
|
|
25
|
-
</td>
|
|
26
|
-
</tr>
|
|
27
|
-
</tbody>
|
|
28
|
-
</table>
|
|
29
|
-
|
|
30
|
-
<div v-if="searchExists" class="pagination">
|
|
31
|
-
<button @click="goToPreviousPage" :disabled="currentPage === 1">
|
|
32
|
-
Предыдущая
|
|
33
|
-
</button>
|
|
34
|
-
<span>Страница {{ currentPage }} из {{ totalPages }}</span>
|
|
35
|
-
<button @click="goToNextPage" :disabled="currentPage === totalPages">
|
|
36
|
-
Следующая
|
|
37
|
-
</button>
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
</template>
|
|
41
|
-
|
|
42
|
-
<script setup lang="ts">
|
|
43
|
-
import {ref, computed} from 'vue';
|
|
44
|
-
|
|
45
|
-
interface TableColumn {
|
|
46
|
-
key: string;
|
|
47
|
-
label: string;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
interface TableProps {
|
|
51
|
-
columns: TableColumn[];
|
|
52
|
-
rows: Record<string, any>[];
|
|
53
|
-
pageSize?: number;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const props = defineProps<TableProps>();
|
|
57
|
-
|
|
58
|
-
// states
|
|
59
|
-
const searchQuery = ref<string>('');
|
|
60
|
-
const currentPage = ref<number>(1);
|
|
61
|
-
const rowsPerPage = ref<number>(props.pageSize ?? 5);
|
|
62
|
-
|
|
63
|
-
// computed properties
|
|
64
|
-
const filteredRows = computed(() => {
|
|
65
|
-
if (!searchQuery.value) {
|
|
66
|
-
return props.rows;
|
|
67
|
-
}
|
|
68
|
-
const query = searchQuery.value.toLowerCase();
|
|
69
|
-
return props.rows.filter((row: string | any) =>
|
|
70
|
-
Object.values(row).some((val) =>
|
|
71
|
-
String(val).toLowerCase().includes(query)
|
|
72
|
-
)
|
|
73
|
-
);
|
|
74
|
-
});
|
|
75
|
-
const searchExists = computed(() => filteredRows.value.length > 0);
|
|
76
|
-
const totalPages = computed(() =>
|
|
77
|
-
Math.ceil(filteredRows.value.length / rowsPerPage.value)
|
|
78
|
-
);
|
|
79
|
-
const startIndex = computed(() => (currentPage.value - 1) * rowsPerPage.value);
|
|
80
|
-
const endIndex = computed(() => currentPage.value * rowsPerPage.value);
|
|
81
|
-
const paginatedRows = computed(() =>
|
|
82
|
-
filteredRows.value.slice(startIndex.value, endIndex.value)
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
// functions
|
|
86
|
-
const goToPreviousPage = (): void => {
|
|
87
|
-
if (currentPage.value > 1) {
|
|
88
|
-
currentPage.value--;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
const goToNextPage = (): void => {
|
|
92
|
-
if (currentPage.value < totalPages.value) {
|
|
93
|
-
currentPage.value++;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
const handleSearchInput = (event: Event): void => {
|
|
97
|
-
searchQuery.value = (event.target as HTMLInputElement).value;
|
|
98
|
-
currentPage.value = 1;
|
|
99
|
-
}
|
|
100
|
-
</script>
|
|
101
|
-
|
|
102
|
-
<style scoped lang="scss">
|
|
103
|
-
.table-container {
|
|
104
|
-
max-width: 100%;
|
|
105
|
-
overflow-x: auto;
|
|
106
|
-
padding: 1rem;
|
|
107
|
-
|
|
108
|
-
.search-container {
|
|
109
|
-
margin-bottom: 1rem;
|
|
110
|
-
|
|
111
|
-
input {
|
|
112
|
-
padding: 0.5rem;
|
|
113
|
-
border: 1px solid #ccc;
|
|
114
|
-
border-radius: 4px;
|
|
115
|
-
|
|
116
|
-
&:focus {
|
|
117
|
-
outline: none;
|
|
118
|
-
border-color: #90caf9;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
table {
|
|
124
|
-
width: 100%;
|
|
125
|
-
border-collapse: collapse;
|
|
126
|
-
margin-bottom: 1rem;
|
|
127
|
-
|
|
128
|
-
thead {
|
|
129
|
-
background-color: #e3f2fd;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
th, td {
|
|
133
|
-
padding: 0.75rem 1rem;
|
|
134
|
-
border: 1px solid #ccc;
|
|
135
|
-
text-align: left;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
.pagination {
|
|
140
|
-
display: flex;
|
|
141
|
-
align-items: center;
|
|
142
|
-
justify-content: flex-end;
|
|
143
|
-
|
|
144
|
-
button {
|
|
145
|
-
background-color: #90caf9;
|
|
146
|
-
color: #fff;
|
|
147
|
-
border: none;
|
|
148
|
-
padding: 0.5rem 1rem;
|
|
149
|
-
margin: 0 0.25rem;
|
|
150
|
-
border-radius: 4px;
|
|
151
|
-
cursor: pointer;
|
|
152
|
-
transition: background-color 0.2s ease;
|
|
153
|
-
|
|
154
|
-
&:hover:not(:disabled) {
|
|
155
|
-
background-color: #64b5f6;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
&:disabled {
|
|
159
|
-
background-color: #ccc;
|
|
160
|
-
cursor: not-allowed;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
span {
|
|
165
|
-
margin: 0 0.5rem;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
</style>
|