@vuetkit/components 0.0.7 → 0.0.9
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/README.md +7 -3
- package/dist/index.d.ts +71 -2
- package/dist/index.js +228 -2
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
# Components
|
|
1
|
+
# Composable Components
|
|
2
2
|
|
|
3
3
|
## Description
|
|
4
4
|
|
|
5
|
-
Collection of business development
|
|
5
|
+
Collection of business development Composable Components for Vue3 + ElementPlus projects.
|
|
6
6
|
|
|
7
|
-
## All Components
|
|
7
|
+
## All Composable Components
|
|
8
8
|
|
|
9
9
|
### Feedback
|
|
10
10
|
|
|
11
11
|
- [useMessage](/components/src/feedback/useMessage/)
|
|
12
12
|
- [useAsyncConfirm](/components/src/feedback/useAsyncConfirm/)
|
|
13
|
+
|
|
14
|
+
### Form
|
|
15
|
+
|
|
16
|
+
- [useForm](/components/src/form/useForm/)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RequestService } from "@vuetkit/core";
|
|
2
|
+
import { ComponentSize, FormRules, MessageProps, MessageType } from "element-plus";
|
|
3
|
+
import { Component } from "vue";
|
|
2
4
|
|
|
5
|
+
//#region src/feedback/useAsyncConfirm/index.d.ts
|
|
6
|
+
interface AsyncConfirmOptions {
|
|
7
|
+
title?: string;
|
|
8
|
+
message?: string;
|
|
9
|
+
type?: MessageType;
|
|
10
|
+
confirmButtonText?: string;
|
|
11
|
+
cancelButtonText?: string;
|
|
12
|
+
successMessage?: string;
|
|
13
|
+
errorMessage?: string;
|
|
14
|
+
confirmSuccess?: () => void;
|
|
15
|
+
confirmError?: (error: unknown) => void;
|
|
16
|
+
}
|
|
17
|
+
declare function useAsyncConfirm(confirmService: RequestService, options: AsyncConfirmOptions): {
|
|
18
|
+
loading: import("vue").Ref<boolean, boolean>;
|
|
19
|
+
confirm: (params?: unknown) => void;
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
3
22
|
//#region src/feedback/useMessage/index.d.ts
|
|
4
23
|
declare function useMessage(options?: MessageProps): {
|
|
5
24
|
success: (message: string) => import("element-plus").MessageHandler;
|
|
@@ -9,4 +28,54 @@ declare function useMessage(options?: MessageProps): {
|
|
|
9
28
|
closeAll: () => void;
|
|
10
29
|
};
|
|
11
30
|
//#endregion
|
|
12
|
-
|
|
31
|
+
//#region src/form/useForm/index.d.ts
|
|
32
|
+
type CustomRender = (...args: unknown[]) => unknown;
|
|
33
|
+
type Recordable = Record<string, unknown>;
|
|
34
|
+
type DeepKeys<T> = T extends null | undefined ? never : T extends object ? { [K in keyof T]: K extends string ? T[K] extends null | undefined ? `${K}` : T[K] extends object ? `${K}` | `${K}.${DeepKeys<T[K]>}` : `${K}` : never }[keyof T] : never;
|
|
35
|
+
type DefaultComponentKey = 'input' | 'select' | 'date-picker' | 'time-picker' | 'checkbox' | 'radio' | 'upload' | 'input-number' | 'switch' | 'rate' | 'tree-select' | 'cascader' | 'color-picker' | 'input-otp' | 'mention' | 'select-v2' | 'slider' | 'time-select' | 'transfer';
|
|
36
|
+
type FormItemType = DefaultComponentKey | string | CustomRender;
|
|
37
|
+
interface FormSchema<T> {
|
|
38
|
+
label: string;
|
|
39
|
+
prop: DeepKeys<T>;
|
|
40
|
+
type: FormItemType;
|
|
41
|
+
span?: number;
|
|
42
|
+
componentProps?: Recordable;
|
|
43
|
+
}
|
|
44
|
+
type FormRuleFn<T> = (data: T) => FormRules<Recordable>;
|
|
45
|
+
interface FormOptions<T> {
|
|
46
|
+
'schemas': FormSchema<T>[];
|
|
47
|
+
'rules'?: FormRules<Recordable> | FormRuleFn<T>;
|
|
48
|
+
'defaultData'?: T;
|
|
49
|
+
'inline'?: boolean;
|
|
50
|
+
'colSpan'?: number;
|
|
51
|
+
'size'?: ComponentSize;
|
|
52
|
+
'rowGutter'?: number;
|
|
53
|
+
'labelWidth'?: string;
|
|
54
|
+
'labelPosition'?: 'left' | 'top' | 'right';
|
|
55
|
+
'labelSuffix'?: string;
|
|
56
|
+
'validate-on-rule-change'?: boolean;
|
|
57
|
+
'disabled'?: boolean;
|
|
58
|
+
'require-asterisk-position'?: 'left' | 'right';
|
|
59
|
+
'scrollTo-error'?: boolean;
|
|
60
|
+
'scroll-into-view-options'?: boolean | ScrollIntoViewOptions;
|
|
61
|
+
'status-icon'?: boolean;
|
|
62
|
+
'show-message'?: boolean;
|
|
63
|
+
'inline-message'?: boolean;
|
|
64
|
+
'enterCallback'?: () => void;
|
|
65
|
+
/**
|
|
66
|
+
* Custom component merged with default component. Only affects this useForm instance.
|
|
67
|
+
* eg: { 'c-input': CInput, 'c-select': CSelect }
|
|
68
|
+
* If the same key will retain the custom component.
|
|
69
|
+
*/
|
|
70
|
+
'customComponent'?: Record<string, Component>;
|
|
71
|
+
}
|
|
72
|
+
type FormReturnType<T extends object> = [Component, {
|
|
73
|
+
validate: (callback: (data: T) => void) => void;
|
|
74
|
+
reset: () => void;
|
|
75
|
+
getData: () => T;
|
|
76
|
+
setData: (newData: T) => void;
|
|
77
|
+
}];
|
|
78
|
+
declare function setDeepProperty(data: Recordable, propArr: string[], value: unknown): void;
|
|
79
|
+
declare function useForm<T extends object>(options: FormOptions<T>): FormReturnType<T>;
|
|
80
|
+
//#endregion
|
|
81
|
+
export { AsyncConfirmOptions, CustomRender, DefaultComponentKey, FormItemType, FormOptions, FormReturnType, FormRuleFn, FormSchema, Recordable, setDeepProperty, useAsyncConfirm, useForm, useMessage };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useRequest } from "@vuetkit/core";
|
|
2
|
+
import { ElCascader, ElCheckbox, ElCol, ElColorPicker, ElDatePicker, ElForm, ElFormItem, ElInput, ElInputNumber, ElInputOtp, ElMention, ElMessage, ElMessageBox, ElRadio, ElRate, ElRow, ElSelect, ElSelectV2, ElSlider, ElSwitch, ElTimePicker, ElTimeSelect, ElTransfer, ElTreeSelect, ElUpload } from "element-plus";
|
|
3
|
+
import { isFunc } from "@vuetkit/shared";
|
|
4
|
+
import { computed, defineComponent, h, nextTick, onMounted, ref, useTemplateRef } from "vue";
|
|
2
5
|
//#region src/feedback/useMessage/index.ts
|
|
3
6
|
const DEFAULT_DURATION = 3e3;
|
|
4
7
|
const DEFAULT_SHOW_CLOSE = true;
|
|
@@ -44,4 +47,227 @@ function useMessage(options = {}) {
|
|
|
44
47
|
};
|
|
45
48
|
}
|
|
46
49
|
//#endregion
|
|
47
|
-
|
|
50
|
+
//#region src/feedback/useAsyncConfirm/index.ts
|
|
51
|
+
function useAsyncConfirm(confirmService, options) {
|
|
52
|
+
const { title = "Confirm", message = "Sure Confirm?", type = "error", confirmButtonText = "Sure", cancelButtonText = "Cancel", confirmSuccess, confirmError, successMessage, errorMessage } = options || {};
|
|
53
|
+
const { loading, execute: executeConfirm, error } = useRequest(confirmService, { manual: true });
|
|
54
|
+
const { success, error: showError } = useMessage();
|
|
55
|
+
function confirm(params) {
|
|
56
|
+
ElMessageBox.confirm(message, title, {
|
|
57
|
+
confirmButtonText,
|
|
58
|
+
cancelButtonText,
|
|
59
|
+
type,
|
|
60
|
+
beforeClose: async (action, instance, done) => {
|
|
61
|
+
if (action === "confirm") {
|
|
62
|
+
instance.confirmButtonLoading = true;
|
|
63
|
+
await executeConfirm(params);
|
|
64
|
+
instance.confirmButtonLoading = false;
|
|
65
|
+
if (error.value) {
|
|
66
|
+
if (errorMessage) showError(errorMessage);
|
|
67
|
+
confirmError === null || confirmError === void 0 || confirmError(error.value);
|
|
68
|
+
} else {
|
|
69
|
+
if (successMessage) success(successMessage);
|
|
70
|
+
confirmSuccess === null || confirmSuccess === void 0 || confirmSuccess();
|
|
71
|
+
}
|
|
72
|
+
done();
|
|
73
|
+
} else done();
|
|
74
|
+
}
|
|
75
|
+
}).catch(() => {});
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
loading,
|
|
79
|
+
confirm
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/form/useForm/index.ts
|
|
84
|
+
const defaultComponent = {
|
|
85
|
+
"input": ElInput,
|
|
86
|
+
"select": ElSelect,
|
|
87
|
+
"date-picker": ElDatePicker,
|
|
88
|
+
"time-picker": ElTimePicker,
|
|
89
|
+
"checkbox": ElCheckbox,
|
|
90
|
+
"radio": ElRadio,
|
|
91
|
+
"upload": ElUpload,
|
|
92
|
+
"input-number": ElInputNumber,
|
|
93
|
+
"switch": ElSwitch,
|
|
94
|
+
"rate": ElRate,
|
|
95
|
+
"tree-select": ElTreeSelect,
|
|
96
|
+
"cascader": ElCascader,
|
|
97
|
+
"color-picker": ElColorPicker,
|
|
98
|
+
"input-otp": ElInputOtp,
|
|
99
|
+
"mention": ElMention,
|
|
100
|
+
"select-v2": ElSelectV2,
|
|
101
|
+
"slider": ElSlider,
|
|
102
|
+
"time-select": ElTimeSelect,
|
|
103
|
+
"transfer": ElTransfer
|
|
104
|
+
};
|
|
105
|
+
function setDeepProperty(data, propArr, value) {
|
|
106
|
+
let temp = data;
|
|
107
|
+
for (let i = 0; i < propArr.length - 1; i++) {
|
|
108
|
+
const key = propArr[i];
|
|
109
|
+
if (temp[key] === void 0) temp[key] = {};
|
|
110
|
+
temp = temp[key];
|
|
111
|
+
}
|
|
112
|
+
temp[propArr[propArr.length - 1]] = value;
|
|
113
|
+
}
|
|
114
|
+
function useForm(options) {
|
|
115
|
+
const { schemas = [], rules = {}, colSpan = 24, defaultData, disabled = false, inline = false, size, rowGutter = 20, labelWidth, labelSuffix = "", labelPosition = "left", "validate-on-rule-change": validateOnRuleChange = true, enterCallback, customComponent, "scrollTo-error": scrollToError = false, "scroll-into-view-options": scrollIntoViewOptions = true, "status-icon": statusIcon = false, "require-asterisk-position": requireAsteriskPosition = "left", "show-message": showMessage = true, "inline-message": inlineMessage = false } = options || {};
|
|
116
|
+
const components = {};
|
|
117
|
+
if (customComponent) Object.assign(components, defaultComponent, customComponent);
|
|
118
|
+
else Object.assign(components, defaultComponent);
|
|
119
|
+
const initFormData = schemas.reduce((prev, cur) => {
|
|
120
|
+
const prop = cur.prop;
|
|
121
|
+
const propArr = prop.split(".");
|
|
122
|
+
if ((propArr === null || propArr === void 0 ? void 0 : propArr.length) < 2) prev[prop] = void 0;
|
|
123
|
+
else setDeepProperty(prev, propArr, void 0);
|
|
124
|
+
return prev;
|
|
125
|
+
}, {});
|
|
126
|
+
const defaultFormData = defaultData || initFormData;
|
|
127
|
+
const copyInitFormData = JSON.parse(JSON.stringify(defaultFormData));
|
|
128
|
+
const formData = ref(defaultFormData);
|
|
129
|
+
const formInstanceRef = ref();
|
|
130
|
+
function getComponent(type) {
|
|
131
|
+
if (type && typeof type !== "string") return type;
|
|
132
|
+
return components[type];
|
|
133
|
+
}
|
|
134
|
+
const FormComp = defineComponent((props, { slots }) => {
|
|
135
|
+
const formRef = useTemplateRef("formRef");
|
|
136
|
+
/**
|
|
137
|
+
* get data value
|
|
138
|
+
* @data data object
|
|
139
|
+
* @prop bind prop
|
|
140
|
+
* eg:
|
|
141
|
+
* prop: 'user.name'
|
|
142
|
+
* data: {
|
|
143
|
+
* user: {
|
|
144
|
+
* usename: 'vuetkit',
|
|
145
|
+
* }
|
|
146
|
+
* }
|
|
147
|
+
*/
|
|
148
|
+
function getFormData(data, prop) {
|
|
149
|
+
var _prop;
|
|
150
|
+
const propArr = prop.split(".");
|
|
151
|
+
if ((propArr === null || propArr === void 0 ? void 0 : propArr.length) < 2) return (_prop = data[prop]) !== null && _prop !== void 0 ? _prop : void 0;
|
|
152
|
+
let value = data;
|
|
153
|
+
for (const propItem of propArr) {
|
|
154
|
+
if (value === void 0 || value === null) return;
|
|
155
|
+
if (typeof value !== "object") return;
|
|
156
|
+
value = value[propItem];
|
|
157
|
+
}
|
|
158
|
+
return value;
|
|
159
|
+
}
|
|
160
|
+
function setFormData(data, prop, value) {
|
|
161
|
+
const propArr = prop.split(".");
|
|
162
|
+
if ((propArr === null || propArr === void 0 ? void 0 : propArr.length) < 2) {
|
|
163
|
+
data[prop] = value;
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
setDeepProperty(data, propArr, value);
|
|
167
|
+
}
|
|
168
|
+
function handleEnter() {
|
|
169
|
+
enterCallback === null || enterCallback === void 0 || enterCallback();
|
|
170
|
+
}
|
|
171
|
+
const renderFormItem = (schema, slots) => {
|
|
172
|
+
if (isFunc(schema.type)) return h(schema.type, {});
|
|
173
|
+
return h(ElFormItem, {
|
|
174
|
+
label: schema.label,
|
|
175
|
+
prop: schema.prop,
|
|
176
|
+
size
|
|
177
|
+
}, () => {
|
|
178
|
+
if (slots[schema.prop]) {
|
|
179
|
+
var _slots$schema$prop;
|
|
180
|
+
return (_slots$schema$prop = slots[schema.prop]) === null || _slots$schema$prop === void 0 ? void 0 : _slots$schema$prop.call(slots);
|
|
181
|
+
}
|
|
182
|
+
const component = getComponent(schema.type);
|
|
183
|
+
if (!component) return null;
|
|
184
|
+
return h(component, {
|
|
185
|
+
"modelValue": getFormData(formData.value, schema.prop),
|
|
186
|
+
"onUpdate:modelValue": (val) => {
|
|
187
|
+
return setFormData(formData.value, schema.prop, val);
|
|
188
|
+
},
|
|
189
|
+
"onKeydown": (e) => {
|
|
190
|
+
if (e.key === "Enter" && !e.ctrlKey && !e.metaKey) {
|
|
191
|
+
e.preventDefault();
|
|
192
|
+
e.stopPropagation();
|
|
193
|
+
handleEnter();
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
...schema.componentProps || {}
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
};
|
|
200
|
+
const renderFormItems = (slots) => {
|
|
201
|
+
return schemas.map((schema) => {
|
|
202
|
+
if (inline) return renderFormItem(schema, slots);
|
|
203
|
+
return h(ElCol, {
|
|
204
|
+
span: schema.span ? schema.span : colSpan,
|
|
205
|
+
propItem: schema.prop
|
|
206
|
+
}, () => renderFormItem(schema, slots));
|
|
207
|
+
});
|
|
208
|
+
};
|
|
209
|
+
onMounted(async () => {
|
|
210
|
+
await nextTick();
|
|
211
|
+
formInstanceRef.value = formRef.value;
|
|
212
|
+
});
|
|
213
|
+
const formRules = computed(() => {
|
|
214
|
+
if (isFunc(rules)) {
|
|
215
|
+
var _ref;
|
|
216
|
+
return (_ref = rules === null || rules === void 0 ? void 0 : rules(formData.value)) !== null && _ref !== void 0 ? _ref : void 0;
|
|
217
|
+
}
|
|
218
|
+
return rules;
|
|
219
|
+
});
|
|
220
|
+
return () => {
|
|
221
|
+
return h(ElForm, {
|
|
222
|
+
model: formData.value,
|
|
223
|
+
rules: formRules.value,
|
|
224
|
+
size,
|
|
225
|
+
validateOnRuleChange,
|
|
226
|
+
labelWidth,
|
|
227
|
+
labelPosition,
|
|
228
|
+
labelSuffix,
|
|
229
|
+
ref: "formRef",
|
|
230
|
+
inline,
|
|
231
|
+
disabled,
|
|
232
|
+
scrollToError,
|
|
233
|
+
scrollIntoViewOptions,
|
|
234
|
+
statusIcon,
|
|
235
|
+
requireAsteriskPosition,
|
|
236
|
+
showMessage,
|
|
237
|
+
inlineMessage,
|
|
238
|
+
...props
|
|
239
|
+
}, () => {
|
|
240
|
+
const children = [];
|
|
241
|
+
if (inline) children.push(renderFormItems(slots));
|
|
242
|
+
else children.push(h(ElRow, { gutter: rowGutter }, () => renderFormItems(slots)));
|
|
243
|
+
if (slots === null || slots === void 0 ? void 0 : slots.footer) children.push(slots.footer());
|
|
244
|
+
return children;
|
|
245
|
+
});
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
async function validate(callback) {
|
|
249
|
+
var _formInstanceRef$valu;
|
|
250
|
+
return await ((_formInstanceRef$valu = formInstanceRef.value) === null || _formInstanceRef$valu === void 0 ? void 0 : _formInstanceRef$valu.validate((valid) => {
|
|
251
|
+
if (valid) callback === null || callback === void 0 || callback(formData.value);
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
function reset() {
|
|
255
|
+
var _formInstanceRef$valu2;
|
|
256
|
+
formData.value = copyInitFormData;
|
|
257
|
+
(_formInstanceRef$valu2 = formInstanceRef.value) === null || _formInstanceRef$valu2 === void 0 || _formInstanceRef$valu2.resetFields();
|
|
258
|
+
}
|
|
259
|
+
function getData() {
|
|
260
|
+
return formData.value;
|
|
261
|
+
}
|
|
262
|
+
function setData(newData) {
|
|
263
|
+
formData.value = newData;
|
|
264
|
+
}
|
|
265
|
+
return [FormComp, {
|
|
266
|
+
validate,
|
|
267
|
+
reset,
|
|
268
|
+
getData,
|
|
269
|
+
setData
|
|
270
|
+
}];
|
|
271
|
+
}
|
|
272
|
+
//#endregion
|
|
273
|
+
export { setDeepProperty, useAsyncConfirm, useForm, useMessage };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vuetkit/components",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.9",
|
|
5
5
|
"description": "Collection of business development components for Vue3 projects",
|
|
6
6
|
"author": "Kalu5",
|
|
7
7
|
"license": "MIT",
|
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
"element-plus": "^2.14.1",
|
|
21
21
|
"vue": "^3.5.35"
|
|
22
22
|
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@vuetkit/shared": "0.0.9"
|
|
25
|
+
},
|
|
23
26
|
"scripts": {
|
|
24
27
|
"build": "tsdown --config-loader tsx"
|
|
25
28
|
}
|