snail.vue 1.0.11 → 1.0.13
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/snail.vue.d.ts +38 -13
- package/dist/snail.vue.js +256 -247
- package/dist/snail.vue.umd.js +283 -0
- package/package.json +9 -9
package/dist/snail.vue.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { IScope } from 'snail.core';
|
|
1
2
|
import * as vue from 'vue';
|
|
2
3
|
import { App, Component } from 'vue';
|
|
3
|
-
import { IScope } from 'snail.core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Vue App助手类,做一些app实例的辅助性工作
|
|
@@ -41,6 +41,21 @@ type ComponentOptions = {
|
|
|
41
41
|
*/
|
|
42
42
|
url?: string;
|
|
43
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
*/
|
|
47
|
+
type ComponentMountOptions = ComponentOptions & {
|
|
48
|
+
/**
|
|
49
|
+
* 挂载到哪个dom元素下
|
|
50
|
+
*/
|
|
51
|
+
target: Element;
|
|
52
|
+
/**
|
|
53
|
+
* 传递给组件的属性值,执行v-bind绑定到要显示的组件
|
|
54
|
+
* - key为属性名称,遵循vue解析规则
|
|
55
|
+
* - 若为事件监听,则使用onXXX
|
|
56
|
+
*/
|
|
57
|
+
props?: Record<string, any>;
|
|
58
|
+
};
|
|
44
59
|
|
|
45
60
|
/**
|
|
46
61
|
* 模态弹窗显示的组件配置选项
|
|
@@ -52,16 +67,6 @@ type DialogOptions = ComponentOptions & {
|
|
|
52
67
|
* - 若为事件监听,则使用onXXX
|
|
53
68
|
*/
|
|
54
69
|
props?: Record<string, any>;
|
|
55
|
-
/**
|
|
56
|
-
* 按下esc健时是否关闭弹窗
|
|
57
|
-
* - 默认值:false
|
|
58
|
-
*/
|
|
59
|
-
closeOnEscape?: boolean;
|
|
60
|
-
/**
|
|
61
|
-
* 点击遮罩层时是否关闭弹窗
|
|
62
|
-
* - 默认值:false
|
|
63
|
-
*/
|
|
64
|
-
closeOnMask?: boolean;
|
|
65
70
|
/**
|
|
66
71
|
* 自定义class
|
|
67
72
|
* - 绑定模块弹窗显示的组件根元素上
|
|
@@ -72,6 +77,16 @@ type DialogOptions = ComponentOptions & {
|
|
|
72
77
|
* - 绑定模块弹窗显示的组件根元素上
|
|
73
78
|
*/
|
|
74
79
|
style?: string | string[];
|
|
80
|
+
/**
|
|
81
|
+
* 按下esc健时是否关闭弹窗
|
|
82
|
+
* - 默认值:false
|
|
83
|
+
*/
|
|
84
|
+
closeOnEscape?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* 点击遮罩层时是否关闭弹窗
|
|
87
|
+
* - 默认值:false
|
|
88
|
+
*/
|
|
89
|
+
closeOnMask?: boolean;
|
|
75
90
|
/**
|
|
76
91
|
* 弹窗的z-index值
|
|
77
92
|
* - 无特殊情况,建议不粗韩,内部会自动生成,确保弹窗正确性
|
|
@@ -187,5 +202,15 @@ type __VLS_WithSlots<T, S> = T & {
|
|
|
187
202
|
};
|
|
188
203
|
};
|
|
189
204
|
|
|
190
|
-
|
|
191
|
-
|
|
205
|
+
/**
|
|
206
|
+
* 挂载vue组件
|
|
207
|
+
* - 全新创建一个Vue实例挂载的传入组件
|
|
208
|
+
* - 用于在非vue环境下渲染vue组件内容
|
|
209
|
+
* @param options 挂载配置选项
|
|
210
|
+
* @param onDestroyed 监听【调用方】的销毁时机,用于自动销毁挂载的实力
|
|
211
|
+
* @returns
|
|
212
|
+
*/
|
|
213
|
+
declare function mount(options: ComponentMountOptions, onDestroyed?: (fn: () => void) => void): IScope;
|
|
214
|
+
|
|
215
|
+
export { _default$1 as SnailDynamic, _default as SnailLoading, mount, onAppCreated, openDialog, triggerAppCreated };
|
|
216
|
+
export type { ComponentMountOptions, ComponentOptions, Dialog, DialogHandle, DialogOpenResult, DialogOptions, LoadingOptions };
|
package/dist/snail.vue.js
CHANGED
|
@@ -1,268 +1,277 @@
|
|
|
1
1
|
//@ sourceURL=/snail.vue.js
|
|
2
|
-
|
|
2
|
+
import { mustFunction, isStringNotEmpty, isObject, script, delay, getMessage, style, hook, mustObject, defer, newId, isFunction } from 'snail.core';
|
|
3
|
+
import { defineComponent, createBlock, openBlock, Transition, withCtx, createElementBlock, createCommentVNode, normalizeClass, renderSlot, normalizeProps, guardReactiveProps, ref, shallowRef, watch, onErrorCaptured, onActivated, onDeactivated, Fragment, resolveDynamicComponent, mergeProps, createSlots, renderList, createTextVNode, createElementVNode, toDisplayString, TransitionGroup, withModifiers, normalizeStyle, createVNode, createApp } from 'vue';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
};
|
|
5
|
+
const appCreatedFns = [];
|
|
6
|
+
function onAppCreated(fn) {
|
|
7
|
+
mustFunction(fn, "fn");
|
|
8
|
+
appCreatedFns.push(fn);
|
|
9
|
+
return {
|
|
10
|
+
destroy: () => {
|
|
11
|
+
const index = appCreatedFns.indexOf(fn);
|
|
12
|
+
index >= 0 && appCreatedFns.splice(index, 1);
|
|
14
13
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function triggerAppCreated(app) {
|
|
17
|
+
appCreatedFns.forEach(fn => fn(app));
|
|
18
|
+
return app;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
var _sfc_main$2 = defineComponent({
|
|
22
|
+
...{
|
|
23
|
+
name: "SnailLoading",
|
|
24
|
+
inheritAttrs: false
|
|
25
|
+
},
|
|
26
|
+
__name: "loading",
|
|
27
|
+
props: {
|
|
28
|
+
show: {
|
|
29
|
+
type: Boolean,
|
|
30
|
+
default: false
|
|
31
|
+
},
|
|
32
|
+
disabledMask: {
|
|
33
|
+
type: Boolean,
|
|
34
|
+
default: false
|
|
35
|
+
},
|
|
36
|
+
rootClass: {
|
|
37
|
+
default: () => []
|
|
38
|
+
},
|
|
39
|
+
transition: {
|
|
40
|
+
default: "snail-loading"
|
|
18
41
|
}
|
|
42
|
+
},
|
|
43
|
+
setup(__props) {
|
|
44
|
+
return (_ctx, _cache) => {
|
|
45
|
+
return openBlock(), createBlock(Transition, {
|
|
46
|
+
name: _ctx.transition
|
|
47
|
+
}, {
|
|
48
|
+
default: withCtx(() => [_ctx.show ? (openBlock(), createElementBlock("div", {
|
|
49
|
+
key: 0,
|
|
50
|
+
class: normalizeClass(["snail-loading", {
|
|
51
|
+
"show-mask": _ctx.disabledMask != true
|
|
52
|
+
}, _ctx.rootClass])
|
|
53
|
+
}, [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(_ctx.$attrs)))], 2)) : createCommentVNode("", true)]),
|
|
54
|
+
_: 3
|
|
55
|
+
}, 8, ["name"]);
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
});
|
|
19
59
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
},
|
|
42
|
-
setup(__props) {
|
|
43
|
-
return (_ctx, _cache) => {
|
|
44
|
-
return vue.openBlock(), vue.createBlock(vue.Transition, {
|
|
45
|
-
name: _ctx.transition
|
|
46
|
-
}, {
|
|
47
|
-
default: vue.withCtx(() => [_ctx.show ? (vue.openBlock(), vue.createElementBlock("div", {
|
|
48
|
-
key: 0,
|
|
49
|
-
class: vue.normalizeClass(["snail-loading", {
|
|
50
|
-
"show-mask": _ctx.disabledMask != true
|
|
51
|
-
}, _ctx.rootClass])
|
|
52
|
-
}, [vue.renderSlot(_ctx.$slots, "default", vue.normalizeProps(vue.guardReactiveProps(_ctx.$attrs)))], 2)) : vue.createCommentVNode("", true)]),
|
|
53
|
-
_: 3
|
|
54
|
-
}, 8, ["name"]);
|
|
55
|
-
};
|
|
60
|
+
var _sfc_main$1 = defineComponent({
|
|
61
|
+
...{
|
|
62
|
+
name: "SnailDynamic",
|
|
63
|
+
inheritAttrs: false
|
|
64
|
+
},
|
|
65
|
+
__name: "dynamic",
|
|
66
|
+
props: {
|
|
67
|
+
name: {},
|
|
68
|
+
component: {},
|
|
69
|
+
url: {}
|
|
70
|
+
},
|
|
71
|
+
setup(__props) {
|
|
72
|
+
const componentRef = ref(null);
|
|
73
|
+
const dynamicComponent = shallowRef(void 0);
|
|
74
|
+
const dynamicError = shallowRef(void 0);
|
|
75
|
+
async function buildDynamicComponent() {
|
|
76
|
+
dynamicComponent.value = void 0;
|
|
77
|
+
dynamicError.value = void 0;
|
|
78
|
+
if (isStringNotEmpty(__props.name) == true) {
|
|
79
|
+
dynamicComponent.value = __props.name;
|
|
80
|
+
return;
|
|
56
81
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
url: {}
|
|
69
|
-
},
|
|
70
|
-
setup(__props) {
|
|
71
|
-
const componentRef = vue.ref(null);
|
|
72
|
-
const dynamicComponent = vue.shallowRef(void 0);
|
|
73
|
-
const dynamicError = vue.shallowRef(void 0);
|
|
74
|
-
async function buildDynamicComponent() {
|
|
82
|
+
if (isObject(__props.component) == true) {
|
|
83
|
+
dynamicComponent.value = __props.component;
|
|
84
|
+
return;
|
|
85
|
+
} else if (isStringNotEmpty(__props.url) == true) {
|
|
86
|
+
console.log("load dynamic component:", __props.url);
|
|
87
|
+
const task = script.load(__props.url);
|
|
88
|
+
await delay(200);
|
|
89
|
+
try {
|
|
90
|
+
const comp = await task;
|
|
91
|
+
isObject(comp) || isStringNotEmpty(comp) ? dynamicComponent.value = comp : dynamicError.value = `load component failed:return nulll or undefined. url:${__props.url}.`;
|
|
92
|
+
} catch (ex) {
|
|
75
93
|
dynamicComponent.value = void 0;
|
|
76
|
-
dynamicError.value =
|
|
77
|
-
if (snail_core.isStringNotEmpty(__props.name) == true) {
|
|
78
|
-
dynamicComponent.value = __props.name;
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
if (snail_core.isObject(__props.component) == true) {
|
|
82
|
-
dynamicComponent.value = __props.component;
|
|
83
|
-
return;
|
|
84
|
-
} else if (snail_core.isStringNotEmpty(__props.url) == true) {
|
|
85
|
-
console.log("load dynamic component:", __props.url);
|
|
86
|
-
const task = snail_core.script.load(__props.url);
|
|
87
|
-
await snail_core.delay(200);
|
|
88
|
-
try {
|
|
89
|
-
const comp = await task;
|
|
90
|
-
snail_core.isObject(comp) || snail_core.isStringNotEmpty(comp) ? dynamicComponent.value = comp : dynamicError.value = `load component failed:return nulll or undefined. url:${__props.url}.`;
|
|
91
|
-
} catch (ex) {
|
|
92
|
-
dynamicComponent.value = void 0;
|
|
93
|
-
dynamicError.value = snail_core.getMessage(ex);
|
|
94
|
-
}
|
|
95
|
-
} else {
|
|
96
|
-
dynamicError.value = "load error: name component、url are all empty.";
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
{
|
|
100
|
-
vue.watch(() => __props.name, buildDynamicComponent);
|
|
101
|
-
vue.watch(() => __props.component, buildDynamicComponent);
|
|
102
|
-
vue.watch(() => __props.url, buildDynamicComponent);
|
|
103
|
-
buildDynamicComponent();
|
|
94
|
+
dynamicError.value = getMessage(ex);
|
|
104
95
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}, [vue.renderList(_ctx.$slots, (_, name) => {
|
|
120
|
-
return {
|
|
121
|
-
name,
|
|
122
|
-
fn: vue.withCtx(slotData => [vue.renderSlot(_ctx.$slots, name, vue.normalizeProps(vue.guardReactiveProps(slotData)))])
|
|
123
|
-
};
|
|
124
|
-
})]), 1040)), dynamicError.value != void 0 ? (vue.openBlock(), vue.createElementBlock("div", vue.mergeProps({
|
|
125
|
-
key: 0,
|
|
126
|
-
class: "snail-dynamic-error"
|
|
127
|
-
}, _ctx.$attrs), [_cache[0] || (_cache[0] = vue.createTextVNode(" load component error:")), vue.createElementVNode("span", null, vue.toDisplayString(dynamicError.value), 1)], 16)) : dynamicComponent.value == void 0 ? (vue.openBlock(), vue.createBlock(_sfc_main$2, {
|
|
128
|
-
key: 1,
|
|
129
|
-
show: true,
|
|
130
|
-
"disabled-mask": true
|
|
131
|
-
})) : vue.createCommentVNode("", true)], 64);
|
|
132
|
-
};
|
|
96
|
+
} else {
|
|
97
|
+
dynamicError.value = "load error: name component、url are all empty.";
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
{
|
|
101
|
+
watch(() => __props.name, buildDynamicComponent);
|
|
102
|
+
watch(() => __props.component, buildDynamicComponent);
|
|
103
|
+
watch(() => __props.url, buildDynamicComponent);
|
|
104
|
+
buildDynamicComponent();
|
|
105
|
+
}
|
|
106
|
+
onErrorCaptured((error, vm, info) => {
|
|
107
|
+
if (componentRef.value == null || vm == componentRef.value) {
|
|
108
|
+
console.error("动态加载组件报错,已拦截错误:", error.message, error);
|
|
109
|
+
return false;
|
|
133
110
|
}
|
|
134
111
|
});
|
|
112
|
+
onActivated(() => console.log("onActivated"));
|
|
113
|
+
onDeactivated(() => console.log("onDeactivated"));
|
|
114
|
+
return (_ctx, _cache) => {
|
|
115
|
+
return openBlock(), createElementBlock(Fragment, null, [(openBlock(), createBlock(resolveDynamicComponent(dynamicComponent.value), mergeProps(_ctx.$attrs, {
|
|
116
|
+
ref_key: "componentRef",
|
|
117
|
+
ref: componentRef
|
|
118
|
+
}), createSlots({
|
|
119
|
+
_: 2
|
|
120
|
+
}, [renderList(_ctx.$slots, (_, name) => {
|
|
121
|
+
return {
|
|
122
|
+
name,
|
|
123
|
+
fn: withCtx(slotData => [renderSlot(_ctx.$slots, name, normalizeProps(guardReactiveProps(slotData)))])
|
|
124
|
+
};
|
|
125
|
+
})]), 1040)), dynamicError.value != void 0 ? (openBlock(), createElementBlock("div", mergeProps({
|
|
126
|
+
key: 0,
|
|
127
|
+
class: "snail-dynamic-error"
|
|
128
|
+
}, _ctx.$attrs), [_cache[0] || (_cache[0] = createTextVNode(" load component error:")), createElementVNode("span", null, toDisplayString(dynamicError.value), 1)], 16)) : dynamicComponent.value == void 0 ? (openBlock(), createBlock(_sfc_main$2, {
|
|
129
|
+
key: 1,
|
|
130
|
+
show: true,
|
|
131
|
+
"disabled-mask": true
|
|
132
|
+
})) : createCommentVNode("", true)], 64);
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
});
|
|
135
136
|
|
|
136
|
-
|
|
137
|
+
var addLink = href => setTimeout(style.register, 0, href);
|
|
137
138
|
|
|
138
|
-
|
|
139
|
+
addLink("/css/snail.vue.vue.css");
|
|
139
140
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
return (_ctx, _cache) => {
|
|
165
|
-
return vue.openBlock(), vue.createBlock(vue.TransitionGroup, {
|
|
166
|
-
name: "snail-dialog"
|
|
167
|
-
}, {
|
|
168
|
-
default: vue.withCtx(() => [(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.descriptors, (dialog, $index) => {
|
|
169
|
-
return vue.openBlock(), vue.createElementBlock("div", {
|
|
170
|
-
key: dialog.id,
|
|
171
|
-
class: vue.normalizeClass(["snail-dialog", dialog.options.rootClass, {
|
|
172
|
-
"unactive": __props.descriptors.length - 1 !== $index
|
|
173
|
-
}]),
|
|
174
|
-
style: vue.normalizeStyle("z-index:" + dialog.options.zIndex),
|
|
175
|
-
onClick: vue.withModifiers($event => onMaskClick(dialog), ["self"])
|
|
176
|
-
}, [vue.createVNode(_sfc_main$1, vue.mergeProps({
|
|
177
|
-
class: ["dialog-body", dialog.options.class],
|
|
178
|
-
name: dialog.options.name,
|
|
179
|
-
component: dialog.options.component,
|
|
180
|
-
url: dialog.options.url,
|
|
181
|
-
style: dialog.options.style
|
|
182
|
-
}, {
|
|
183
|
-
ref_for: true
|
|
184
|
-
}, dialog.options.props, {
|
|
185
|
-
ref_for: true
|
|
186
|
-
}, dialog.handle), null, 16, ["name", "component", "url", "class", "style"])], 14, _hoisted_1);
|
|
187
|
-
}), 128))]),
|
|
188
|
-
_: 1
|
|
189
|
-
});
|
|
190
|
-
};
|
|
141
|
+
const _hoisted_1 = ["onClick"];
|
|
142
|
+
var _sfc_main = defineComponent({
|
|
143
|
+
...{
|
|
144
|
+
name: "SnailDialogWrapper",
|
|
145
|
+
inheritAttrs: true
|
|
146
|
+
},
|
|
147
|
+
__name: "dialog-wrapper",
|
|
148
|
+
props: {
|
|
149
|
+
descriptors: {
|
|
150
|
+
type: Array,
|
|
151
|
+
required: true
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
setup(__props) {
|
|
155
|
+
function onMaskClick(dialog) {
|
|
156
|
+
const last = __props.descriptors[__props.descriptors.length - 1];
|
|
157
|
+
last === dialog && dialog.options.closeOnMask && dialog.handle.closeDialog(dialog);
|
|
158
|
+
}
|
|
159
|
+
addEventListener("keyup", event => {
|
|
160
|
+
if (event.key === "Escape" && __props.descriptors.length > 0) {
|
|
161
|
+
const dialog = __props.descriptors[__props.descriptors.length - 1];
|
|
162
|
+
dialog.options.closeOnEscape && dialog.handle.closeDialog(dialog);
|
|
191
163
|
}
|
|
192
164
|
});
|
|
165
|
+
return (_ctx, _cache) => {
|
|
166
|
+
return openBlock(), createBlock(TransitionGroup, {
|
|
167
|
+
name: "snail-dialog"
|
|
168
|
+
}, {
|
|
169
|
+
default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.descriptors, (dialog, $index) => {
|
|
170
|
+
return openBlock(), createElementBlock("div", {
|
|
171
|
+
key: dialog.id,
|
|
172
|
+
class: normalizeClass(["snail-dialog", dialog.options.rootClass, {
|
|
173
|
+
"unactive": __props.descriptors.length - 1 !== $index
|
|
174
|
+
}]),
|
|
175
|
+
style: normalizeStyle("z-index:" + dialog.options.zIndex),
|
|
176
|
+
onClick: withModifiers($event => onMaskClick(dialog), ["self"])
|
|
177
|
+
}, [createVNode(_sfc_main$1, mergeProps({
|
|
178
|
+
class: ["dialog-body", dialog.options.class],
|
|
179
|
+
name: dialog.options.name,
|
|
180
|
+
component: dialog.options.component,
|
|
181
|
+
url: dialog.options.url,
|
|
182
|
+
style: dialog.options.style
|
|
183
|
+
}, {
|
|
184
|
+
ref_for: true
|
|
185
|
+
}, dialog.options.props, {
|
|
186
|
+
ref_for: true
|
|
187
|
+
}, dialog.handle), null, 16, ["name", "component", "url", "class", "style"])], 14, _hoisted_1);
|
|
188
|
+
}), 128))]),
|
|
189
|
+
_: 1
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
});
|
|
193
194
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
213
|
-
destroyDialog(dialog);
|
|
214
|
-
deferred.resolve(data);
|
|
215
|
-
},
|
|
216
|
-
onDialogClose(fn) {
|
|
217
|
-
const hookCode = createDialogHookCode(dialog);
|
|
218
|
-
dialogHook.register(hookCode, fn);
|
|
219
|
-
}
|
|
220
|
-
})
|
|
221
|
-
};
|
|
222
|
-
initVueApp();
|
|
223
|
-
descriptors.value.push(dialog);
|
|
224
|
-
snail_core.isFunction(onDestroyed) && onDestroyed(() => destroyDialog(dialog));
|
|
225
|
-
const dr = deferred.promise;
|
|
226
|
-
dr.destroy = () => {
|
|
227
|
-
console.warn("force close dialog after openDialog caller called close function.");
|
|
228
|
-
destroyDialog(dialog);
|
|
229
|
-
deferred.resolve(void 0);
|
|
230
|
-
};
|
|
231
|
-
return dr;
|
|
232
|
-
}
|
|
233
|
-
const descriptors = vue.ref([]);
|
|
234
|
-
const dialogHook = snail_core.hook.newScope();
|
|
235
|
-
const createDialogHookCode = dialog => `onCloseDialog:${dialog.id}`;
|
|
236
|
-
function destroyDialog(dialog) {
|
|
237
|
-
const index = descriptors.value.indexOf(dialog);
|
|
238
|
-
if (index != -1) {
|
|
239
|
-
for (var tmpIndex = index; tmpIndex < descriptors.value.length; tmpIndex++) {
|
|
240
|
-
const hookCode = createDialogHookCode(descriptors.value[tmpIndex]);
|
|
241
|
-
dialogHook.remove(hookCode);
|
|
195
|
+
function openDialog(options, onDestroyed) {
|
|
196
|
+
mustObject(options, "options");
|
|
197
|
+
options.zIndex = options.zIndex || 2e3;
|
|
198
|
+
const deferred = defer();
|
|
199
|
+
const dialog = {
|
|
200
|
+
id: newId(),
|
|
201
|
+
options,
|
|
202
|
+
handle: Object.freeze({
|
|
203
|
+
inDialog: true,
|
|
204
|
+
async closeDialog(data) {
|
|
205
|
+
const hookCode = createDialogHookCode(dialog);
|
|
206
|
+
const rt = await dialogHook.runHookAsync(hookCode, {
|
|
207
|
+
mode: "one",
|
|
208
|
+
order: "desc"
|
|
209
|
+
});
|
|
210
|
+
if (rt.success != true) {
|
|
211
|
+
console.warn("run onDialogClose failed", rt.reason, rt.ex);
|
|
212
|
+
return;
|
|
242
213
|
}
|
|
243
|
-
|
|
214
|
+
destroyDialog(dialog);
|
|
215
|
+
deferred.resolve(data);
|
|
216
|
+
},
|
|
217
|
+
onDialogClose(fn) {
|
|
218
|
+
const hookCode = createDialogHookCode(dialog);
|
|
219
|
+
dialogHook.register(hookCode, fn);
|
|
244
220
|
}
|
|
221
|
+
})
|
|
222
|
+
};
|
|
223
|
+
initVueApp();
|
|
224
|
+
descriptors.value.push(dialog);
|
|
225
|
+
isFunction(onDestroyed) && onDestroyed(() => destroyDialog(dialog));
|
|
226
|
+
const dr = deferred.promise;
|
|
227
|
+
dr.destroy = () => {
|
|
228
|
+
console.warn("force close dialog after openDialog caller called close function.");
|
|
229
|
+
destroyDialog(dialog);
|
|
230
|
+
deferred.resolve(void 0);
|
|
231
|
+
};
|
|
232
|
+
return dr;
|
|
233
|
+
}
|
|
234
|
+
const descriptors = ref([]);
|
|
235
|
+
const dialogHook = hook.newScope();
|
|
236
|
+
const createDialogHookCode = dialog => `onCloseDialog:${dialog.id}`;
|
|
237
|
+
function destroyDialog(dialog) {
|
|
238
|
+
const index = descriptors.value.indexOf(dialog);
|
|
239
|
+
if (index != -1) {
|
|
240
|
+
for (var tmpIndex = index; tmpIndex < descriptors.value.length; tmpIndex++) {
|
|
241
|
+
const hookCode = createDialogHookCode(descriptors.value[tmpIndex]);
|
|
242
|
+
dialogHook.remove(hookCode);
|
|
245
243
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
};
|
|
260
|
-
|
|
244
|
+
descriptors.value.splice(index);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
const initVueApp = (() => {
|
|
248
|
+
var dialogApp = void 0;
|
|
249
|
+
return function () {
|
|
250
|
+
if (dialogApp == void 0) {
|
|
251
|
+
const container = document.createElement("div");
|
|
252
|
+
container.style = "height:0 !important; width:0 !important;";
|
|
253
|
+
container.classList.add("snail-dialog-container");
|
|
254
|
+
document.body.appendChild(container);
|
|
255
|
+
dialogApp = createApp(_sfc_main, {
|
|
256
|
+
descriptors: descriptors.value
|
|
257
|
+
});
|
|
258
|
+
triggerAppCreated(dialogApp).mount(container);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
})();
|
|
261
262
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
263
|
+
function mount(options, onDestroyed) {
|
|
264
|
+
mustObject(options, "options");
|
|
265
|
+
mustObject(options.target, "options.target");
|
|
266
|
+
const app = createApp(_sfc_main$1, options.props);
|
|
267
|
+
app.mount(options.target);
|
|
268
|
+
function destroy() {
|
|
269
|
+
app.unmount();
|
|
270
|
+
}
|
|
271
|
+
isFunction(onDestroyed) && onDestroyed(destroy);
|
|
272
|
+
return {
|
|
273
|
+
destroy
|
|
274
|
+
};
|
|
275
|
+
}
|
|
267
276
|
|
|
268
|
-
}
|
|
277
|
+
export { _sfc_main$1 as SnailDynamic, _sfc_main$2 as SnailLoading, mount, onAppCreated, openDialog, triggerAppCreated };
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
//@ sourceURL=/snail.vue.js
|
|
2
|
+
(function (global, factory) {
|
|
3
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('snail.core'), require('vue')) :
|
|
4
|
+
typeof define === 'function' && define.amd ? define(['exports', 'snail.core', 'vue'], factory) :
|
|
5
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.SnailVue = global.SnailVue || {}, global.Snail, global.Vue));
|
|
6
|
+
})(this, (function (exports, snail_core, vue) { 'use strict';
|
|
7
|
+
|
|
8
|
+
const appCreatedFns = [];
|
|
9
|
+
function onAppCreated(fn) {
|
|
10
|
+
snail_core.mustFunction(fn, "fn");
|
|
11
|
+
appCreatedFns.push(fn);
|
|
12
|
+
return {
|
|
13
|
+
destroy: () => {
|
|
14
|
+
const index = appCreatedFns.indexOf(fn);
|
|
15
|
+
index >= 0 && appCreatedFns.splice(index, 1);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function triggerAppCreated(app) {
|
|
20
|
+
appCreatedFns.forEach(fn => fn(app));
|
|
21
|
+
return app;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var _sfc_main$2 = vue.defineComponent({
|
|
25
|
+
...{
|
|
26
|
+
name: "SnailLoading",
|
|
27
|
+
inheritAttrs: false
|
|
28
|
+
},
|
|
29
|
+
__name: "loading",
|
|
30
|
+
props: {
|
|
31
|
+
show: {
|
|
32
|
+
type: Boolean,
|
|
33
|
+
default: false
|
|
34
|
+
},
|
|
35
|
+
disabledMask: {
|
|
36
|
+
type: Boolean,
|
|
37
|
+
default: false
|
|
38
|
+
},
|
|
39
|
+
rootClass: {
|
|
40
|
+
default: () => []
|
|
41
|
+
},
|
|
42
|
+
transition: {
|
|
43
|
+
default: "snail-loading"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
setup(__props) {
|
|
47
|
+
return (_ctx, _cache) => {
|
|
48
|
+
return vue.openBlock(), vue.createBlock(vue.Transition, {
|
|
49
|
+
name: _ctx.transition
|
|
50
|
+
}, {
|
|
51
|
+
default: vue.withCtx(() => [_ctx.show ? (vue.openBlock(), vue.createElementBlock("div", {
|
|
52
|
+
key: 0,
|
|
53
|
+
class: vue.normalizeClass(["snail-loading", {
|
|
54
|
+
"show-mask": _ctx.disabledMask != true
|
|
55
|
+
}, _ctx.rootClass])
|
|
56
|
+
}, [vue.renderSlot(_ctx.$slots, "default", vue.normalizeProps(vue.guardReactiveProps(_ctx.$attrs)))], 2)) : vue.createCommentVNode("", true)]),
|
|
57
|
+
_: 3
|
|
58
|
+
}, 8, ["name"]);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
var _sfc_main$1 = vue.defineComponent({
|
|
64
|
+
...{
|
|
65
|
+
name: "SnailDynamic",
|
|
66
|
+
inheritAttrs: false
|
|
67
|
+
},
|
|
68
|
+
__name: "dynamic",
|
|
69
|
+
props: {
|
|
70
|
+
name: {},
|
|
71
|
+
component: {},
|
|
72
|
+
url: {}
|
|
73
|
+
},
|
|
74
|
+
setup(__props) {
|
|
75
|
+
const componentRef = vue.ref(null);
|
|
76
|
+
const dynamicComponent = vue.shallowRef(void 0);
|
|
77
|
+
const dynamicError = vue.shallowRef(void 0);
|
|
78
|
+
async function buildDynamicComponent() {
|
|
79
|
+
dynamicComponent.value = void 0;
|
|
80
|
+
dynamicError.value = void 0;
|
|
81
|
+
if (snail_core.isStringNotEmpty(__props.name) == true) {
|
|
82
|
+
dynamicComponent.value = __props.name;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (snail_core.isObject(__props.component) == true) {
|
|
86
|
+
dynamicComponent.value = __props.component;
|
|
87
|
+
return;
|
|
88
|
+
} else if (snail_core.isStringNotEmpty(__props.url) == true) {
|
|
89
|
+
console.log("load dynamic component:", __props.url);
|
|
90
|
+
const task = snail_core.script.load(__props.url);
|
|
91
|
+
await snail_core.delay(200);
|
|
92
|
+
try {
|
|
93
|
+
const comp = await task;
|
|
94
|
+
snail_core.isObject(comp) || snail_core.isStringNotEmpty(comp) ? dynamicComponent.value = comp : dynamicError.value = `load component failed:return nulll or undefined. url:${__props.url}.`;
|
|
95
|
+
} catch (ex) {
|
|
96
|
+
dynamicComponent.value = void 0;
|
|
97
|
+
dynamicError.value = snail_core.getMessage(ex);
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
dynamicError.value = "load error: name component、url are all empty.";
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
{
|
|
104
|
+
vue.watch(() => __props.name, buildDynamicComponent);
|
|
105
|
+
vue.watch(() => __props.component, buildDynamicComponent);
|
|
106
|
+
vue.watch(() => __props.url, buildDynamicComponent);
|
|
107
|
+
buildDynamicComponent();
|
|
108
|
+
}
|
|
109
|
+
vue.onErrorCaptured((error, vm, info) => {
|
|
110
|
+
if (componentRef.value == null || vm == componentRef.value) {
|
|
111
|
+
console.error("动态加载组件报错,已拦截错误:", error.message, error);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
vue.onActivated(() => console.log("onActivated"));
|
|
116
|
+
vue.onDeactivated(() => console.log("onDeactivated"));
|
|
117
|
+
return (_ctx, _cache) => {
|
|
118
|
+
return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [(vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(dynamicComponent.value), vue.mergeProps(_ctx.$attrs, {
|
|
119
|
+
ref_key: "componentRef",
|
|
120
|
+
ref: componentRef
|
|
121
|
+
}), vue.createSlots({
|
|
122
|
+
_: 2
|
|
123
|
+
}, [vue.renderList(_ctx.$slots, (_, name) => {
|
|
124
|
+
return {
|
|
125
|
+
name,
|
|
126
|
+
fn: vue.withCtx(slotData => [vue.renderSlot(_ctx.$slots, name, vue.normalizeProps(vue.guardReactiveProps(slotData)))])
|
|
127
|
+
};
|
|
128
|
+
})]), 1040)), dynamicError.value != void 0 ? (vue.openBlock(), vue.createElementBlock("div", vue.mergeProps({
|
|
129
|
+
key: 0,
|
|
130
|
+
class: "snail-dynamic-error"
|
|
131
|
+
}, _ctx.$attrs), [_cache[0] || (_cache[0] = vue.createTextVNode(" load component error:")), vue.createElementVNode("span", null, vue.toDisplayString(dynamicError.value), 1)], 16)) : dynamicComponent.value == void 0 ? (vue.openBlock(), vue.createBlock(_sfc_main$2, {
|
|
132
|
+
key: 1,
|
|
133
|
+
show: true,
|
|
134
|
+
"disabled-mask": true
|
|
135
|
+
})) : vue.createCommentVNode("", true)], 64);
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const _hoisted_1 = ["onClick"];
|
|
141
|
+
var _sfc_main = vue.defineComponent({
|
|
142
|
+
...{
|
|
143
|
+
name: "SnailDialogWrapper",
|
|
144
|
+
inheritAttrs: true
|
|
145
|
+
},
|
|
146
|
+
__name: "dialog-wrapper",
|
|
147
|
+
props: {
|
|
148
|
+
descriptors: {
|
|
149
|
+
type: Array,
|
|
150
|
+
required: true
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
setup(__props) {
|
|
154
|
+
function onMaskClick(dialog) {
|
|
155
|
+
const last = __props.descriptors[__props.descriptors.length - 1];
|
|
156
|
+
last === dialog && dialog.options.closeOnMask && dialog.handle.closeDialog(dialog);
|
|
157
|
+
}
|
|
158
|
+
addEventListener("keyup", event => {
|
|
159
|
+
if (event.key === "Escape" && __props.descriptors.length > 0) {
|
|
160
|
+
const dialog = __props.descriptors[__props.descriptors.length - 1];
|
|
161
|
+
dialog.options.closeOnEscape && dialog.handle.closeDialog(dialog);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
return (_ctx, _cache) => {
|
|
165
|
+
return vue.openBlock(), vue.createBlock(vue.TransitionGroup, {
|
|
166
|
+
name: "snail-dialog"
|
|
167
|
+
}, {
|
|
168
|
+
default: vue.withCtx(() => [(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.descriptors, (dialog, $index) => {
|
|
169
|
+
return vue.openBlock(), vue.createElementBlock("div", {
|
|
170
|
+
key: dialog.id,
|
|
171
|
+
class: vue.normalizeClass(["snail-dialog", dialog.options.rootClass, {
|
|
172
|
+
"unactive": __props.descriptors.length - 1 !== $index
|
|
173
|
+
}]),
|
|
174
|
+
style: vue.normalizeStyle("z-index:" + dialog.options.zIndex),
|
|
175
|
+
onClick: vue.withModifiers($event => onMaskClick(dialog), ["self"])
|
|
176
|
+
}, [vue.createVNode(_sfc_main$1, vue.mergeProps({
|
|
177
|
+
class: ["dialog-body", dialog.options.class],
|
|
178
|
+
name: dialog.options.name,
|
|
179
|
+
component: dialog.options.component,
|
|
180
|
+
url: dialog.options.url,
|
|
181
|
+
style: dialog.options.style
|
|
182
|
+
}, {
|
|
183
|
+
ref_for: true
|
|
184
|
+
}, dialog.options.props, {
|
|
185
|
+
ref_for: true
|
|
186
|
+
}, dialog.handle), null, 16, ["name", "component", "url", "class", "style"])], 14, _hoisted_1);
|
|
187
|
+
}), 128))]),
|
|
188
|
+
_: 1
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
function openDialog(options, onDestroyed) {
|
|
195
|
+
snail_core.mustObject(options, "options");
|
|
196
|
+
options.zIndex = options.zIndex || 2e3;
|
|
197
|
+
const deferred = snail_core.defer();
|
|
198
|
+
const dialog = {
|
|
199
|
+
id: snail_core.newId(),
|
|
200
|
+
options,
|
|
201
|
+
handle: Object.freeze({
|
|
202
|
+
inDialog: true,
|
|
203
|
+
async closeDialog(data) {
|
|
204
|
+
const hookCode = createDialogHookCode(dialog);
|
|
205
|
+
const rt = await dialogHook.runHookAsync(hookCode, {
|
|
206
|
+
mode: "one",
|
|
207
|
+
order: "desc"
|
|
208
|
+
});
|
|
209
|
+
if (rt.success != true) {
|
|
210
|
+
console.warn("run onDialogClose failed", rt.reason, rt.ex);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
destroyDialog(dialog);
|
|
214
|
+
deferred.resolve(data);
|
|
215
|
+
},
|
|
216
|
+
onDialogClose(fn) {
|
|
217
|
+
const hookCode = createDialogHookCode(dialog);
|
|
218
|
+
dialogHook.register(hookCode, fn);
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
};
|
|
222
|
+
initVueApp();
|
|
223
|
+
descriptors.value.push(dialog);
|
|
224
|
+
snail_core.isFunction(onDestroyed) && onDestroyed(() => destroyDialog(dialog));
|
|
225
|
+
const dr = deferred.promise;
|
|
226
|
+
dr.destroy = () => {
|
|
227
|
+
console.warn("force close dialog after openDialog caller called close function.");
|
|
228
|
+
destroyDialog(dialog);
|
|
229
|
+
deferred.resolve(void 0);
|
|
230
|
+
};
|
|
231
|
+
return dr;
|
|
232
|
+
}
|
|
233
|
+
const descriptors = vue.ref([]);
|
|
234
|
+
const dialogHook = snail_core.hook.newScope();
|
|
235
|
+
const createDialogHookCode = dialog => `onCloseDialog:${dialog.id}`;
|
|
236
|
+
function destroyDialog(dialog) {
|
|
237
|
+
const index = descriptors.value.indexOf(dialog);
|
|
238
|
+
if (index != -1) {
|
|
239
|
+
for (var tmpIndex = index; tmpIndex < descriptors.value.length; tmpIndex++) {
|
|
240
|
+
const hookCode = createDialogHookCode(descriptors.value[tmpIndex]);
|
|
241
|
+
dialogHook.remove(hookCode);
|
|
242
|
+
}
|
|
243
|
+
descriptors.value.splice(index);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const initVueApp = (() => {
|
|
247
|
+
var dialogApp = void 0;
|
|
248
|
+
return function () {
|
|
249
|
+
if (dialogApp == void 0) {
|
|
250
|
+
const container = document.createElement("div");
|
|
251
|
+
container.style = "height:0 !important; width:0 !important;";
|
|
252
|
+
container.classList.add("snail-dialog-container");
|
|
253
|
+
document.body.appendChild(container);
|
|
254
|
+
dialogApp = vue.createApp(_sfc_main, {
|
|
255
|
+
descriptors: descriptors.value
|
|
256
|
+
});
|
|
257
|
+
triggerAppCreated(dialogApp).mount(container);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
})();
|
|
261
|
+
|
|
262
|
+
function mount(options, onDestroyed) {
|
|
263
|
+
snail_core.mustObject(options, "options");
|
|
264
|
+
snail_core.mustObject(options.target, "options.target");
|
|
265
|
+
const app = vue.createApp(_sfc_main$1, options.props);
|
|
266
|
+
app.mount(options.target);
|
|
267
|
+
function destroy() {
|
|
268
|
+
app.unmount();
|
|
269
|
+
}
|
|
270
|
+
snail_core.isFunction(onDestroyed) && onDestroyed(destroy);
|
|
271
|
+
return {
|
|
272
|
+
destroy
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
exports.SnailDynamic = _sfc_main$1;
|
|
277
|
+
exports.SnailLoading = _sfc_main$2;
|
|
278
|
+
exports.mount = mount;
|
|
279
|
+
exports.onAppCreated = onAppCreated;
|
|
280
|
+
exports.openDialog = openDialog;
|
|
281
|
+
exports.triggerAppCreated = triggerAppCreated;
|
|
282
|
+
|
|
283
|
+
}));
|
package/package.json
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
"description": "依赖【snail】,基于vue封装常用UI组件",
|
|
4
4
|
"author": "snail_dev@163.com",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.13",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"main": "dist/
|
|
9
|
-
"module": "dist/
|
|
10
|
-
"types": "dist/
|
|
8
|
+
"main": "dist/snail.vue.js",
|
|
9
|
+
"module": "dist/snail.vue.js",
|
|
10
|
+
"types": "dist/snail.vue.d.ts",
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "rollup -c ./rollup.config.js",
|
|
13
13
|
"types": "vue-tsc -p ./tsconfig.dts.json --declarationDir ./dist/_types",
|
|
@@ -15,17 +15,17 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"vue": "^3.5.14",
|
|
18
|
-
"snail.core": ">=1.2.
|
|
18
|
+
"snail.core": ">=1.2.10"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"vue-tsc": "^2.2.10",
|
|
22
|
-
"snail.rollup": ">=1.2.
|
|
22
|
+
"snail.rollup": ">=1.2.7",
|
|
23
23
|
"snail.rollup-asset": ">=1.2.1",
|
|
24
|
-
"snail.rollup-html": ">=1.2.
|
|
24
|
+
"snail.rollup-html": ">=1.2.2",
|
|
25
25
|
"snail.rollup-url": ">=1.2.1",
|
|
26
26
|
"snail.rollup-inject": ">=1.2.1",
|
|
27
|
-
"snail.rollup-script": ">=1.2.
|
|
28
|
-
"snail.rollup-style": ">=1.2.
|
|
27
|
+
"snail.rollup-script": ">=1.2.2",
|
|
28
|
+
"snail.rollup-style": ">=1.2.2",
|
|
29
29
|
"snail.rollup-vue": ">=1.2.3"
|
|
30
30
|
}
|
|
31
31
|
}
|