plugin-ui-for-kzt 0.0.2

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 (38) hide show
  1. package/README.md +83 -0
  2. package/dist/index.js +31 -0
  3. package/dist/types/components/Toaster/timer.d.ts +12 -0
  4. package/dist/types/index.d.ts +11 -0
  5. package/dist/types/plugins/modalPlugin.d.ts +16 -0
  6. package/dist/types/plugins/toasterPlugin.d.ts +26 -0
  7. package/dist/types/store/modal.d.ts +11 -0
  8. package/dist/types/types/index.d.ts +4 -0
  9. package/package.json +46 -0
  10. package/public/close-icon.svg +3 -0
  11. package/public/error-icon.svg +5 -0
  12. package/public/success-icon.svg +4 -0
  13. package/shims-vue.d.ts +5 -0
  14. package/src/components/AboutPage/AboutPage.vue +1 -0
  15. package/src/components/DataTable/DataTable.vue +169 -0
  16. package/src/components/DataTable/README.md +57 -0
  17. package/src/components/Modal/Modal.vue +149 -0
  18. package/src/components/Modal/README.md +47 -0
  19. package/src/components/Spinner/README.md +35 -0
  20. package/src/components/Spinner/Spinner.vue +59 -0
  21. package/src/components/Toaster/README.md +69 -0
  22. package/src/components/Toaster/Toaster.vue +235 -0
  23. package/src/components/Toaster/timer.ts +45 -0
  24. package/src/components/Tooltip/README.md +37 -0
  25. package/src/components/Tooltip/Tooltip.vue +96 -0
  26. package/src/components/icons/CloseIcon.vue +5 -0
  27. package/src/components/icons/ErrorIcon.vue +7 -0
  28. package/src/components/icons/InfoIcon.vue +7 -0
  29. package/src/components/icons/SuccessIcon.vue +6 -0
  30. package/src/components/icons/WarningIcon.vue +7 -0
  31. package/src/index.ts +27 -0
  32. package/src/plugins/modalPlugin.ts +81 -0
  33. package/src/plugins/toasterPlugin.ts +179 -0
  34. package/src/store/modal.ts +22 -0
  35. package/src/styles/index.scss +3 -0
  36. package/src/types/index.ts +4 -0
  37. package/tsconfig.json +31 -0
  38. package/webpack.config.js +56 -0
package/src/index.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { createPinia } from "pinia";
2
+ import Modal from "./components/Modal/Modal.vue";
3
+ import DataTable from "./components/DataTable/DataTable.vue";
4
+ import Tooltip from "./components/Tooltip/Tooltip.vue";
5
+ import Spinner from "./components/Spinner/Spinner.vue";
6
+ import ModalPlugin, { useModal } from "./plugins/modalPlugin";
7
+ import ToasterPlugin, { useToast } from "./plugins/toasterPlugin";
8
+
9
+ const components = { Modal, DataTable, Tooltip, Spinner };
10
+
11
+ export default {
12
+ install(app: any) {
13
+ if (!app._context.pinia) {
14
+ const pinia = createPinia();
15
+ app.use(pinia);
16
+ }
17
+
18
+ Object.entries(components).forEach(([name, component]) => {
19
+ app.component(name, component);
20
+ });
21
+
22
+ app.use(ModalPlugin);
23
+ app.use(ToasterPlugin);
24
+ },
25
+ };
26
+
27
+ export { Modal, DataTable, Tooltip, Spinner, useModal, useToast };
@@ -0,0 +1,81 @@
1
+ import { createApp, h, getCurrentInstance } from "vue";
2
+ import { useModalStore } from "../store/modal";
3
+ import Modal from "../components/Modal/Modal.vue";
4
+ import { watch } from "vue";
5
+ import { IModalState } from "types";
6
+
7
+ export default {
8
+ install(app: any) {
9
+ const modalStore = useModalStore();
10
+
11
+ // Добавление глобального метода $modal
12
+ app.config.globalProperties.$modal = {
13
+ open(name: string, options: IModalState) {
14
+ modalStore.openModal(name, options); // Открытие модалки через Pinia
15
+ console.log("Current modals:", modalStore.modals);
16
+ },
17
+ close(id: number) {
18
+ modalStore.closeModal(id); // Закрытие модалки через Pinia
19
+ },
20
+ };
21
+
22
+ // Найдем элемент с классом container
23
+ const modalContainer = document.createElement("div");
24
+ document.body.appendChild(modalContainer);
25
+
26
+ // Реактивное обновление модалок через watch
27
+ watch(
28
+ () => modalStore.modals,
29
+ (newModals) => {
30
+ // Очищаем контейнер
31
+ modalContainer.innerHTML = "";
32
+
33
+ // Добавляем модалки в DOM
34
+ newModals.forEach((modal) => {
35
+ modalContainer.dataset.modalId = String(modal.id);
36
+
37
+ modalContainer.addEventListener("click", (event) => {
38
+ console.log(`Closing modal with id: ${modal.id}`);
39
+ modalStore.closeModal(modal.id);
40
+ });
41
+ modalContainer.setAttribute("name", modal.name);
42
+ modalContainer.classList.add("modal");
43
+ modalContainer.addEventListener("click", () => {
44
+ console.log("this click on background");
45
+ modalStore.closeModal(modal.id);
46
+ });
47
+
48
+ const modalApp = createApp({
49
+ render() {
50
+ return h(Modal, {
51
+ options: modal.options,
52
+ name: modal.name,
53
+ onClose: () => {
54
+ modalContainer.classList.remove("modal");
55
+ modalStore.closeModal(modal.id);
56
+ },
57
+ });
58
+ },
59
+ });
60
+ modalApp.mount(modalContainer);
61
+ });
62
+ },
63
+ { deep: true }
64
+ );
65
+ },
66
+ };
67
+
68
+ export function useModal() {
69
+ const instance = getCurrentInstance();
70
+ return instance?.appContext.config.globalProperties.$modal;
71
+ }
72
+
73
+ // Расширение глобального интерфейса для TypeScript
74
+ declare module "@vue/runtime-core" {
75
+ interface ComponentCustomProperties {
76
+ $modal: {
77
+ open: (name: string, options?: Record<string, any>) => void;
78
+ close: (id: number) => void;
79
+ };
80
+ }
81
+ }
@@ -0,0 +1,179 @@
1
+ import { createApp, h, ref, getCurrentInstance } from "vue";
2
+ import Toaster from "../components/Toaster/Toaster.vue";
3
+
4
+ interface ToastOptions {
5
+ position?: "top-left" | "top-right" | "bottom-left" | "bottom-right";
6
+ duration?: number;
7
+ dismissible?: boolean;
8
+ pauseOnHover?: boolean;
9
+ }
10
+
11
+ interface Toast {
12
+ id: number;
13
+ type: "success" | "error" | "info" | "warning";
14
+ message: string;
15
+ position: "top-left" | "top-right" | "bottom-left" | "bottom-right";
16
+ duration: number;
17
+ dismissible: boolean;
18
+ pauseOnHover: boolean;
19
+ height?: number;
20
+ }
21
+
22
+ interface ToastPosition {
23
+ toasts: Toast[];
24
+ totalHeight: number;
25
+ }
26
+
27
+ export default {
28
+ install(app: any) {
29
+ app.config.globalProperties.$toast = {
30
+ success: (message: string, options: ToastOptions = {}) =>
31
+ addToast("success", message, options),
32
+ error: (message: string, options: ToastOptions = {}) =>
33
+ addToast("error", message, options),
34
+ info: (message: string, options: ToastOptions = {}) =>
35
+ addToast("info", message, options),
36
+ warning: (message: string, options: ToastOptions = {}) =>
37
+ addToast("warning", message, options),
38
+ };
39
+
40
+ const toasts = ref<Toast[]>([]);
41
+ const toastPositions = ref<Record<string, ToastPosition>>({
42
+ "top-right": { toasts: [], totalHeight: 0 },
43
+ "top-left": { toasts: [], totalHeight: 0 },
44
+ "bottom-right": { toasts: [], totalHeight: 0 },
45
+ "bottom-left": { toasts: [], totalHeight: 0 },
46
+ });
47
+
48
+ const calculatePosition = (toast: Toast, index: number): number => {
49
+ const position = toast.position;
50
+ const positionData = toastPositions.value[position];
51
+ const gap = 10;
52
+ let offset = 20;
53
+
54
+ for (let i = 0; i < index; i++) {
55
+ const prevToast = positionData.toasts[i];
56
+ offset += (prevToast.height || 0) + gap;
57
+ }
58
+
59
+ return offset;
60
+ };
61
+
62
+ const updateToastHeight = (id: number, height: number) => {
63
+ const toast = toasts.value.find((t) => t.id === id);
64
+ if (toast) {
65
+ toast.height = height;
66
+ const position = toast.position;
67
+ const positionData = toastPositions.value[position];
68
+ positionData.totalHeight = positionData.toasts.reduce(
69
+ (total, t) => total + (t.height || 0) + 10,
70
+ 20
71
+ );
72
+ }
73
+ };
74
+
75
+ const addToast = (
76
+ type: "success" | "error" | "info" | "warning",
77
+ message: string,
78
+ options: ToastOptions = {}
79
+ ) => {
80
+ const id = Date.now();
81
+ const position = options.position || "top-right";
82
+ const duration = options.duration || 5000;
83
+ const dismissible =
84
+ options.dismissible !== undefined ? options.dismissible : true;
85
+ const pauseOnHover =
86
+ options.pauseOnHover !== undefined ? options.pauseOnHover : true;
87
+
88
+ const toastData: Toast = {
89
+ id,
90
+ type,
91
+ message,
92
+ position,
93
+ duration,
94
+ dismissible,
95
+ pauseOnHover,
96
+ };
97
+
98
+ toasts.value = [...toasts.value, toastData];
99
+ toastPositions.value[position].toasts.push(toastData);
100
+ };
101
+
102
+ const removeToast = (id: number) => {
103
+ const toast = toasts.value.find((t) => t.id === id);
104
+ if (toast) {
105
+ const position = toast.position;
106
+ toastPositions.value[position].toasts = toastPositions.value[
107
+ position
108
+ ].toasts.filter((t) => t.id !== id);
109
+
110
+ toastPositions.value[position].totalHeight = toastPositions.value[
111
+ position
112
+ ].toasts.reduce((total, t) => total + (t.height || 0) + 10, 20);
113
+ }
114
+ toasts.value = toasts.value.filter((t) => t.id !== id);
115
+ };
116
+
117
+ const createContainer = (position: string) => {
118
+ const container = document.createElement("div");
119
+ container.classList.add("toast-container", `toast--${position}`);
120
+ document.body.appendChild(container);
121
+ return container;
122
+ };
123
+
124
+ const topRightContainer = createContainer("top-right");
125
+ const bottomRightContainer = createContainer("bottom-right");
126
+ const topLeftContainer = createContainer("top-left");
127
+ const bottomLeftContainer = createContainer("bottom-left");
128
+
129
+ const createAppInstance = (position: string, container: HTMLElement) => {
130
+ createApp({
131
+ setup() {
132
+ return { toasts, toastPositions };
133
+ },
134
+ render() {
135
+ const positionToasts = toastPositions.value[position].toasts;
136
+
137
+ return positionToasts.map((toast, index) => {
138
+ const offset = calculatePosition(toast, index);
139
+
140
+ return h(Toaster, {
141
+ key: toast.id,
142
+ ...toast,
143
+ style: {
144
+ position: "fixed",
145
+ [position.includes("top") ? "top" : "bottom"]: `${offset}px`,
146
+ [position.includes("right") ? "right" : "left"]: "20px",
147
+ transition: "all 0.3s ease",
148
+ },
149
+ onDismiss: () => removeToast(toast.id),
150
+ onHeightUpdate: (height: number) =>
151
+ updateToastHeight(toast.id, height),
152
+ });
153
+ });
154
+ },
155
+ }).mount(container);
156
+ };
157
+
158
+ createAppInstance("top-right", topRightContainer);
159
+ createAppInstance("bottom-right", bottomRightContainer);
160
+ createAppInstance("top-left", topLeftContainer);
161
+ createAppInstance("bottom-left", bottomLeftContainer);
162
+ },
163
+ };
164
+
165
+ export function useToast() {
166
+ const instance = getCurrentInstance();
167
+ return instance?.appContext.config.globalProperties.$toast;
168
+ }
169
+
170
+ declare module "@vue/runtime-core" {
171
+ interface ComponentCustomProperties {
172
+ $toast: {
173
+ success: (message: string, options?: ToastOptions) => void;
174
+ error: (message: string, options?: ToastOptions) => void;
175
+ info: (message: string, options?: ToastOptions) => void;
176
+ warning: (message: string, options?: ToastOptions) => void;
177
+ };
178
+ }
179
+ }
@@ -0,0 +1,22 @@
1
+ import { defineStore } from 'pinia';
2
+ import {IModalState} from "../types";
3
+
4
+ export const useModalStore = defineStore('modal', {
5
+ state: () => ({
6
+ modals: [] as Array<{ id: number; name: string; options: IModalState }>,
7
+ }),
8
+ actions: {
9
+ openModal(name: string, options: IModalState) {
10
+ this.modals.push({
11
+ id: Date.now(),
12
+ name,
13
+ options,
14
+ });
15
+ console.log('Modal added:', this.modals);
16
+ },
17
+ closeModal(id: number) {
18
+ console.log('Modal removed:', this.modals);
19
+ this.modals = this.modals.filter((modal) => modal.id !== id);
20
+ },
21
+ },
22
+ });
@@ -0,0 +1,3 @@
1
+ body {
2
+ font-family: Arial, sans-serif;
3
+ }
@@ -0,0 +1,4 @@
1
+ export interface IModalState{
2
+ title: string;
3
+ message: string;
4
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Node",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "jsx": "preserve",
10
+ "lib": [
11
+ "dom",
12
+ "esnext"
13
+ ],
14
+ "typeRoots": ["node_modules/@types"], // Pinia and Vue will be auto-detected
15
+ "baseUrl": "./src",
16
+ "paths": {
17
+ "@/*": ["src/*"],
18
+ }
19
+ },
20
+ "include": [
21
+
22
+ "src/**/*",
23
+ "src/**/*.ts",
24
+ "src/**/*.vue",
25
+ "shims-vue.d.ts"
26
+ ],
27
+ "exclude": [
28
+ "node_modules",
29
+ "dist"
30
+ ]
31
+ }
@@ -0,0 +1,56 @@
1
+ const path = require('path');
2
+ const {VueLoaderPlugin} = require('vue-loader');
3
+
4
+ module.exports = {
5
+ entry: './src/index.ts',
6
+ mode: "none",
7
+ output: {
8
+ path: __dirname + "/dist",
9
+ filename: "index.js",
10
+ libraryTarget: "umd", // Universal Module Definition
11
+ library: "ModalPluginNikitas",
12
+ globalObject: "this"
13
+ },
14
+ // output: {
15
+ // filename: 'index.js',
16
+ // path: path.resolve(__dirname, 'dist'),
17
+ // library: 'nikitaModal', //name for import to boot file
18
+ // libraryTarget: 'umd',
19
+ // umdNamedDefine: true,
20
+ // },
21
+ resolve: {
22
+ extensions: ['.js', '.ts', '.vue', '.json'],
23
+ alias: {
24
+ '@': path.resolve(__dirname, 'src'),
25
+ vue: 'vue/dist/vue.runtime.esm-bundler.js',
26
+ },
27
+ },
28
+
29
+ module: {
30
+ rules: [
31
+ {
32
+ test: /\.ts$/,
33
+ loader: 'ts-loader',
34
+ options: {
35
+ appendTsSuffixTo: [/\.vue$/],
36
+ },
37
+ },
38
+ {
39
+ test: /\.vue$/,
40
+ loader: 'vue-loader',
41
+ },
42
+ {
43
+ test: /\.scss$/,
44
+ use: ['vue-style-loader', 'css-loader', 'sass-loader'],
45
+ },
46
+ {
47
+ test: /\.svg$/,
48
+ use: ["file-loader"],
49
+ }
50
+ ],
51
+ },
52
+ plugins: [new VueLoaderPlugin()],
53
+ externals: {
54
+ vue: 'vue', // Vue will not be bundled; it’s an external dependency
55
+ },
56
+ };