@oinone/kunlun-vue-widget 6.2.0
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/oinone-kunlun-vue-widget.esm.js +16 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/src/basic/AsyncVueWidget.d.ts +7 -0
- package/dist/types/src/basic/VueFragment.vue.d.ts +2 -0
- package/dist/types/src/basic/VueWidget.d.ts +331 -0
- package/dist/types/src/basic/Widget.d.ts +234 -0
- package/dist/types/src/basic/index.d.ts +3 -0
- package/dist/types/src/data/ActiveRecordsWidget.d.ts +246 -0
- package/dist/types/src/data/PathWidget.d.ts +34 -0
- package/dist/types/src/data/index.d.ts +2 -0
- package/dist/types/src/dsl/DslDefinitionWidget.d.ts +61 -0
- package/dist/types/src/dsl/DslNodeWidget.d.ts +42 -0
- package/dist/types/src/dsl/DslRenderWidget.d.ts +44 -0
- package/dist/types/src/dsl/index.d.ts +3 -0
- package/dist/types/src/feature/index.d.ts +1 -0
- package/dist/types/src/feature/invisible-supported.d.ts +11 -0
- package/dist/types/src/hooks/all-mounted.d.ts +20 -0
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/index.d.ts +9 -0
- package/dist/types/src/token/index.d.ts +2 -0
- package/dist/types/src/typing/WidgetTagContext.d.ts +39 -0
- package/dist/types/src/typing/WidgetTagProps.d.ts +23 -0
- package/dist/types/src/typing/index.d.ts +3 -0
- package/dist/types/src/typing/typing.d.ts +7 -0
- package/dist/types/src/util/dsl-render.d.ts +106 -0
- package/dist/types/src/util/index.d.ts +4 -0
- package/dist/types/src/util/install.d.ts +4 -0
- package/dist/types/src/util/render.d.ts +7 -0
- package/dist/types/src/util/widget-manager.d.ts +4 -0
- package/dist/types/src/view/index.d.ts +161 -0
- package/index.ts +1 -0
- package/package.json +34 -0
- package/rollup.config.js +21 -0
- package/src/basic/AsyncVueWidget.ts +31 -0
- package/src/basic/VueFragment.vue +11 -0
- package/src/basic/VueWidget.ts +997 -0
- package/src/basic/Widget.ts +675 -0
- package/src/basic/index.ts +3 -0
- package/src/data/ActiveRecordsWidget.ts +572 -0
- package/src/data/PathWidget.ts +82 -0
- package/src/data/index.ts +2 -0
- package/src/dsl/DslDefinitionWidget.ts +235 -0
- package/src/dsl/DslNodeWidget.ts +130 -0
- package/src/dsl/DslRenderWidget.ts +106 -0
- package/src/dsl/index.ts +3 -0
- package/src/feature/index.ts +1 -0
- package/src/feature/invisible-supported.ts +29 -0
- package/src/hooks/all-mounted.ts +179 -0
- package/src/hooks/index.ts +1 -0
- package/src/index.ts +9 -0
- package/src/shim-translate.d.ts +7 -0
- package/src/shim-vue.d.ts +6 -0
- package/src/token/index.ts +8 -0
- package/src/typing/WidgetTagContext.ts +53 -0
- package/src/typing/WidgetTagProps.ts +24 -0
- package/src/typing/index.ts +3 -0
- package/src/typing/typing.ts +7 -0
- package/src/util/dsl-render.ts +464 -0
- package/src/util/index.ts +4 -0
- package/src/util/install.ts +29 -0
- package/src/util/render.ts +21 -0
- package/src/util/widget-manager.ts +14 -0
- package/src/view/index.ts +416 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { InjectionKey } from 'vue';
|
|
2
|
+
import { InjectionToken } from '@oinone/kunlun-spi';
|
|
3
|
+
|
|
4
|
+
const __DEV__ = process.env.NODE_ENV === 'development';
|
|
5
|
+
|
|
6
|
+
export const genToken = <T>(name: string): InjectionKey<T> => {
|
|
7
|
+
return InjectionToken<T>(__DEV__ ? `[vue-kunlun]: ${name}` : name) as any as InjectionKey<T>;
|
|
8
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { DslDefinition } from '@oinone/kunlun-dsl';
|
|
2
|
+
import { Slots } from 'vue';
|
|
3
|
+
import { VueWidget } from '../basic';
|
|
4
|
+
import { DslDefinitionWidgetProps } from '../dsl';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 渲染组件
|
|
8
|
+
*/
|
|
9
|
+
export interface RenderWidget {
|
|
10
|
+
/**
|
|
11
|
+
* 当前组件唯一键
|
|
12
|
+
*/
|
|
13
|
+
handle: string;
|
|
14
|
+
/**
|
|
15
|
+
* 主要组件
|
|
16
|
+
*/
|
|
17
|
+
widget: VueWidget;
|
|
18
|
+
/**
|
|
19
|
+
* 混入组件
|
|
20
|
+
*/
|
|
21
|
+
widgets: VueWidget[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 组件标签上下文
|
|
26
|
+
*/
|
|
27
|
+
export interface WidgetTagContext extends Record<string, unknown> {
|
|
28
|
+
dslDefinition: DslDefinition;
|
|
29
|
+
|
|
30
|
+
slotName: string;
|
|
31
|
+
|
|
32
|
+
widgetHandle: string;
|
|
33
|
+
|
|
34
|
+
widget: VueWidget;
|
|
35
|
+
|
|
36
|
+
widgets: VueWidget[];
|
|
37
|
+
|
|
38
|
+
slotContext?: Record<string, unknown>;
|
|
39
|
+
|
|
40
|
+
getWidgetTag(): string;
|
|
41
|
+
|
|
42
|
+
getParentHandle(): string;
|
|
43
|
+
|
|
44
|
+
getDslDefinition(): DslDefinition | undefined;
|
|
45
|
+
|
|
46
|
+
getSlotName(): string;
|
|
47
|
+
|
|
48
|
+
getProps(): DslDefinitionWidgetProps;
|
|
49
|
+
|
|
50
|
+
getCurrentSlots(): Slots | undefined;
|
|
51
|
+
|
|
52
|
+
createWidget(slots?: Slots): RenderWidget | undefined;
|
|
53
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { DslDefinition } from '@oinone/kunlun-dsl';
|
|
2
|
+
import { PropType } from 'vue';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 组件标签属性
|
|
6
|
+
*/
|
|
7
|
+
export const WidgetTagProps = {
|
|
8
|
+
handle: {
|
|
9
|
+
type: String
|
|
10
|
+
},
|
|
11
|
+
dslDefinition: {
|
|
12
|
+
type: Object as PropType<DslDefinition>
|
|
13
|
+
},
|
|
14
|
+
slotName: {
|
|
15
|
+
type: String
|
|
16
|
+
},
|
|
17
|
+
inline: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: undefined
|
|
20
|
+
},
|
|
21
|
+
slotContext: {
|
|
22
|
+
type: Object
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_SLOT_NAME,
|
|
3
|
+
DslDefinition,
|
|
4
|
+
DslDefinitionHelper,
|
|
5
|
+
DslDefinitionType,
|
|
6
|
+
DslSlots,
|
|
7
|
+
DslSlotUtils,
|
|
8
|
+
ElementDslDefinition,
|
|
9
|
+
PackDslDefinition,
|
|
10
|
+
TemplateDslDefinition
|
|
11
|
+
} from '@oinone/kunlun-dsl';
|
|
12
|
+
import { StringHelper, uniqueKeyGenerator } from '@oinone/kunlun-shared';
|
|
13
|
+
import { PropRecordHelper } from '@oinone/kunlun-vue-ui-common';
|
|
14
|
+
import { intersection, isNil, isString } from 'lodash-es';
|
|
15
|
+
import { Component, createVNode, resolveDynamicComponent, Slots, VNode, withCtx } from 'vue';
|
|
16
|
+
|
|
17
|
+
export const DEFAULT_TAG_PREFIX = 'oinone';
|
|
18
|
+
|
|
19
|
+
export const SLOTS_KEY = '__slots';
|
|
20
|
+
|
|
21
|
+
export const RENDER_OPTIONS_KEY = '__render__options';
|
|
22
|
+
|
|
23
|
+
export const SLOT_CONTEXT_KEY = 'slotContext';
|
|
24
|
+
|
|
25
|
+
const htmlInternalTags: string[] = [
|
|
26
|
+
'div',
|
|
27
|
+
'a',
|
|
28
|
+
'span',
|
|
29
|
+
'table',
|
|
30
|
+
'form',
|
|
31
|
+
'detail',
|
|
32
|
+
'ul',
|
|
33
|
+
'li',
|
|
34
|
+
'h1',
|
|
35
|
+
'h2',
|
|
36
|
+
'h3',
|
|
37
|
+
'h4',
|
|
38
|
+
'h5',
|
|
39
|
+
'h6',
|
|
40
|
+
'p',
|
|
41
|
+
'thead',
|
|
42
|
+
'tbody',
|
|
43
|
+
'tr',
|
|
44
|
+
'th',
|
|
45
|
+
'td'
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 渲染可选项
|
|
50
|
+
*/
|
|
51
|
+
export interface DslRenderOptions {
|
|
52
|
+
/**
|
|
53
|
+
* 动态key
|
|
54
|
+
* 当key不存在时进行自动生成
|
|
55
|
+
*/
|
|
56
|
+
dynamicKey?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* 是否强制更新
|
|
59
|
+
* 永远使用新的key进行渲染
|
|
60
|
+
*/
|
|
61
|
+
focusUpdate?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* 是否递归渲染
|
|
64
|
+
* 递归渲染有性能损耗,但可以解决某些渲染问题,建议在明确递归层数的情况下局部使用该参数
|
|
65
|
+
*/
|
|
66
|
+
recursion?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* vue createVNode patchFlag
|
|
69
|
+
*/
|
|
70
|
+
patchFlag?: number;
|
|
71
|
+
/**
|
|
72
|
+
* vue createVNode dynamicProps
|
|
73
|
+
*/
|
|
74
|
+
dynamicProps?: string[] | null;
|
|
75
|
+
/**
|
|
76
|
+
* vue createVNode isBlockNode
|
|
77
|
+
*/
|
|
78
|
+
isBlockNode?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* 插槽上下文
|
|
81
|
+
*/
|
|
82
|
+
slotContext?: Record<string, unknown>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type DslChildren = string | VNode[] | Slots;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* dsl扩展属性
|
|
89
|
+
*/
|
|
90
|
+
export type DslRenderExtendProp = {
|
|
91
|
+
__slots?: DslChildren;
|
|
92
|
+
__render__options?: DslRenderOptions;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export type DslRenderDefinition = DslDefinition & DslRenderExtendProp;
|
|
96
|
+
|
|
97
|
+
export type DslPropType = {
|
|
98
|
+
dslDefinition: DslRenderDefinition;
|
|
99
|
+
slotName: string;
|
|
100
|
+
slotContext?: Record<string, unknown>;
|
|
101
|
+
|
|
102
|
+
[key: string]: any;
|
|
103
|
+
} & DslRenderExtendProp;
|
|
104
|
+
|
|
105
|
+
function dslExtendPropProcess<T>(props: DslPropType, key: string, value?: T): T | undefined {
|
|
106
|
+
let finalValue = props[key] as T | undefined;
|
|
107
|
+
delete props[key];
|
|
108
|
+
if (!finalValue && value) {
|
|
109
|
+
finalValue = value;
|
|
110
|
+
const { dslDefinition } = props;
|
|
111
|
+
if (dslDefinition) {
|
|
112
|
+
dslDefinition[key] = value;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return finalValue;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
type ResolveComponentType = Component | string;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* dsl渲染
|
|
122
|
+
*/
|
|
123
|
+
export class DslRender {
|
|
124
|
+
private static resolveComponentCache: Record<string, ResolveComponentType> = {};
|
|
125
|
+
|
|
126
|
+
private static resolveCommonComponentCache: Record<string, ResolveComponentType> = {};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 渲染指定dsl定义到对应插槽
|
|
130
|
+
* @param dsl 指定dsl
|
|
131
|
+
* @param slotName 插槽名称 默认为: default
|
|
132
|
+
* @param children 插槽
|
|
133
|
+
* @param options 渲染可选项
|
|
134
|
+
*/
|
|
135
|
+
public static render(
|
|
136
|
+
dsl: DslRenderDefinition,
|
|
137
|
+
slotName = DEFAULT_SLOT_NAME,
|
|
138
|
+
children?: DslChildren,
|
|
139
|
+
options?: DslRenderOptions
|
|
140
|
+
): VNode | undefined {
|
|
141
|
+
const component = DslRender.fetchComponent(dsl);
|
|
142
|
+
if (!component) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
return DslRender.createVNodeWithDslDefinition(component, dsl, slotName, children, options);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 渲染dsl插槽
|
|
150
|
+
* @param dslSlots dsl插槽
|
|
151
|
+
*/
|
|
152
|
+
public static renderSlots(dslSlots: DslSlots): Slots {
|
|
153
|
+
const slots = {};
|
|
154
|
+
for (const slotName in dslSlots) {
|
|
155
|
+
slots[slotName] = withCtx((context: Record<string, unknown>) => {
|
|
156
|
+
return DslRender.createVNodeChildren(dslSlots[slotName]?.widgets, slotName, context);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return slots;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* 通过指定dsl获取VNode插槽
|
|
164
|
+
* @param dsl 指定dsl
|
|
165
|
+
* @param supportedSlotNames
|
|
166
|
+
*/
|
|
167
|
+
public static fetchVNodeSlots(dsl: DslDefinition | undefined, supportedSlotNames?: string[]): Slots | undefined {
|
|
168
|
+
if (!dsl) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
const vSlots = dsl[SLOTS_KEY];
|
|
172
|
+
if (vSlots) {
|
|
173
|
+
return vSlots;
|
|
174
|
+
}
|
|
175
|
+
if (!supportedSlotNames) {
|
|
176
|
+
const finalSupportedSlotNames = [DEFAULT_SLOT_NAME];
|
|
177
|
+
dsl.widgets?.forEach((widget) => {
|
|
178
|
+
if (DslDefinitionHelper.isTemplate(widget)) {
|
|
179
|
+
let slotName = (widget as TemplateDslDefinition).slot;
|
|
180
|
+
if (!slotName) {
|
|
181
|
+
slotName = DEFAULT_SLOT_NAME;
|
|
182
|
+
}
|
|
183
|
+
finalSupportedSlotNames.push(slotName);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
supportedSlotNames = [...new Set(finalSupportedSlotNames)];
|
|
187
|
+
}
|
|
188
|
+
const dslSlots = DslSlotUtils.fetchSlotsBySlotNames(dsl, supportedSlotNames);
|
|
189
|
+
return DslRender.renderSlots(dslSlots);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* 根据dsl节点类型获取对应组件
|
|
194
|
+
*
|
|
195
|
+
* @remarks
|
|
196
|
+
* - {@link DslDefinitionType#VIEW} resolve rule: `{@link DEFAULT_TAG_PREFIX}-{@link DslDefinition#dslNodeType}` (Unsupported auto resolve methods)<br />
|
|
197
|
+
* - {@link DslDefinitionType#PACK} resolve rule: `{@link PackDslDefinition#widget}` (Supported auto resolve methods)<br>
|
|
198
|
+
* - {@link DslDefinitionType#ELEMENT} resolve rule: `{@link ElementDslDefinition#widget}` (Supported auto resolve methods)<br>
|
|
199
|
+
* - Others resolve rule: `{@link DslDefinition#dslNodeType}` (Unsupported auto resolve methods)
|
|
200
|
+
*
|
|
201
|
+
* @param dslDefinition dsl定义
|
|
202
|
+
* @return
|
|
203
|
+
* - 正确获取组件时返回: Component | string;
|
|
204
|
+
* - 未知类型、插槽或模板类型返回: null;
|
|
205
|
+
* - 无效的dslNodeType返回: undefined
|
|
206
|
+
*/
|
|
207
|
+
public static fetchComponent(dslDefinition: DslDefinition): ResolveComponentType | null | undefined {
|
|
208
|
+
let { dslNodeType } = dslDefinition || {};
|
|
209
|
+
if (!dslNodeType) {
|
|
210
|
+
dslNodeType = DslDefinitionType.ELEMENT;
|
|
211
|
+
}
|
|
212
|
+
let component: ResolveComponentType | null | undefined;
|
|
213
|
+
switch (dslNodeType as DslDefinitionType) {
|
|
214
|
+
case DslDefinitionType.VIEW:
|
|
215
|
+
component = resolveDynamicComponent(`${DEFAULT_TAG_PREFIX}-${dslDefinition.dslNodeType}`) as string;
|
|
216
|
+
break;
|
|
217
|
+
case DslDefinitionType.PACK: {
|
|
218
|
+
const packDslDefinition = dslDefinition as PackDslDefinition;
|
|
219
|
+
component = DslRender.resolveWidgetComponent(`${packDslDefinition.widget || 'group'}`);
|
|
220
|
+
if (typeof component === 'string') {
|
|
221
|
+
component = DslRender.resolveWidgetComponent(`${dslDefinition.dslNodeType}`);
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
case DslDefinitionType.ELEMENT: {
|
|
226
|
+
const elementDslDefinition = dslDefinition as ElementDslDefinition;
|
|
227
|
+
component = DslRender.resolveWidgetComponent(`${elementDslDefinition.widget}`);
|
|
228
|
+
if (typeof component === 'string') {
|
|
229
|
+
component = DslRender.resolveWidgetComponent(`${dslDefinition.dslNodeType}`);
|
|
230
|
+
}
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
case DslDefinitionType.ACTION:
|
|
234
|
+
case DslDefinitionType.FIELD: {
|
|
235
|
+
component = DslRender.resolveWidgetComponent(`${dslDefinition.dslNodeType}`);
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
case DslDefinitionType.UNKNOWN:
|
|
239
|
+
case DslDefinitionType.SLOT:
|
|
240
|
+
case DslDefinitionType.TEMPLATE:
|
|
241
|
+
component = null;
|
|
242
|
+
break;
|
|
243
|
+
default:
|
|
244
|
+
component = DslRender.resolveCommonWidgetComponent(dslNodeType);
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
return component;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private static createVNodeChildren(
|
|
251
|
+
widgets: DslDefinition[] | undefined,
|
|
252
|
+
slotName?: string,
|
|
253
|
+
context?: Record<string, unknown>,
|
|
254
|
+
offset?: number
|
|
255
|
+
): VNode[] {
|
|
256
|
+
const children: VNode[] = [];
|
|
257
|
+
if (!widgets) {
|
|
258
|
+
return children;
|
|
259
|
+
}
|
|
260
|
+
if (!slotName) {
|
|
261
|
+
slotName = DEFAULT_SLOT_NAME;
|
|
262
|
+
}
|
|
263
|
+
if (isNil(offset)) {
|
|
264
|
+
offset = 0;
|
|
265
|
+
}
|
|
266
|
+
const { length } = widgets;
|
|
267
|
+
for (let i = 0; i < length; i++) {
|
|
268
|
+
const dslDefinition = widgets[i];
|
|
269
|
+
const component = DslRender.fetchComponent(dslDefinition);
|
|
270
|
+
if (component) {
|
|
271
|
+
children.push(
|
|
272
|
+
DslRender.createVNodeWithDslDefinition(
|
|
273
|
+
component,
|
|
274
|
+
dslDefinition,
|
|
275
|
+
slotName,
|
|
276
|
+
isString(component) ? DslRender.fetchVNodeSlots(dslDefinition) : undefined,
|
|
277
|
+
context ? { slotContext: context } : undefined,
|
|
278
|
+
i + offset
|
|
279
|
+
)
|
|
280
|
+
);
|
|
281
|
+
} else if (component === null) {
|
|
282
|
+
const { dslNodeType } = dslDefinition;
|
|
283
|
+
switch (dslNodeType as DslDefinitionType) {
|
|
284
|
+
case DslDefinitionType.SLOT: {
|
|
285
|
+
const slotChildren = DslRender.createVNodeChildren(dslDefinition.widgets, slotName, context, i + offset);
|
|
286
|
+
offset += slotChildren.length;
|
|
287
|
+
slotChildren.forEach((child) => children.push(child));
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
case DslDefinitionType.UNKNOWN:
|
|
291
|
+
case DslDefinitionType.TEMPLATE:
|
|
292
|
+
// eslint-disable-next-line no-continue
|
|
293
|
+
continue;
|
|
294
|
+
default:
|
|
295
|
+
console.error('Invalid component.');
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return children;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
private static createVNodeWithDslDefinition(
|
|
304
|
+
component: ResolveComponentType,
|
|
305
|
+
dsl: DslDefinition,
|
|
306
|
+
slotName: string,
|
|
307
|
+
children?: DslChildren,
|
|
308
|
+
options?: DslRenderOptions,
|
|
309
|
+
index?: number
|
|
310
|
+
) {
|
|
311
|
+
if (!isNil(index) && dsl.__index !== index) {
|
|
312
|
+
dsl.__index = index;
|
|
313
|
+
}
|
|
314
|
+
const isHTMLTag = isString(component);
|
|
315
|
+
const props: DslPropType = isHTMLTag
|
|
316
|
+
? (PropRecordHelper.collectionBasicProps(dsl) as DslPropType)
|
|
317
|
+
: {
|
|
318
|
+
...dsl,
|
|
319
|
+
dslDefinition: { ...dsl },
|
|
320
|
+
slotName
|
|
321
|
+
};
|
|
322
|
+
let finalChildren: unknown;
|
|
323
|
+
if (isHTMLTag) {
|
|
324
|
+
finalChildren = dsl.__content || dslExtendPropProcess(props, SLOTS_KEY, children);
|
|
325
|
+
} else {
|
|
326
|
+
finalChildren = dslExtendPropProcess(props, SLOTS_KEY, children);
|
|
327
|
+
}
|
|
328
|
+
const finalOptions = dslExtendPropProcess<DslRenderOptions>(props, RENDER_OPTIONS_KEY, options);
|
|
329
|
+
const slotContext = finalOptions?.slotContext;
|
|
330
|
+
if (slotContext) {
|
|
331
|
+
const newSlotContext = options?.slotContext;
|
|
332
|
+
if (newSlotContext) {
|
|
333
|
+
finalOptions!.slotContext = newSlotContext;
|
|
334
|
+
}
|
|
335
|
+
props.slotContext = slotContext;
|
|
336
|
+
}
|
|
337
|
+
if (DslRenderHelper.predictIsUpdateKey(dsl, finalOptions)) {
|
|
338
|
+
const key = uniqueKeyGenerator();
|
|
339
|
+
dsl.key = key;
|
|
340
|
+
props.key = key;
|
|
341
|
+
}
|
|
342
|
+
if (DslRenderHelper.predictIsRecursion(finalOptions) && !finalChildren && dsl.widgets?.length) {
|
|
343
|
+
finalChildren = DslRender.fetchVNodeSlots(dsl);
|
|
344
|
+
}
|
|
345
|
+
let finalDynamicProps = finalOptions?.dynamicProps;
|
|
346
|
+
if (slotContext) {
|
|
347
|
+
finalDynamicProps = intersection(finalDynamicProps || [], [SLOT_CONTEXT_KEY]);
|
|
348
|
+
}
|
|
349
|
+
return createVNode(
|
|
350
|
+
component,
|
|
351
|
+
props,
|
|
352
|
+
finalChildren,
|
|
353
|
+
finalOptions?.patchFlag,
|
|
354
|
+
finalDynamicProps,
|
|
355
|
+
finalOptions?.isBlockNode
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
private static resolveMethods: ((ss: string) => string | undefined)[] = [
|
|
360
|
+
/**
|
|
361
|
+
* 首字母转换为小写
|
|
362
|
+
* @param ss 字符串
|
|
363
|
+
*/
|
|
364
|
+
(ss) => {
|
|
365
|
+
if (ss.indexOf('-') === -1) {
|
|
366
|
+
const firstCharCode = ss.charCodeAt(0);
|
|
367
|
+
if (firstCharCode >= StringHelper.UPPER_A_ASCLL && firstCharCode <= StringHelper.UPPER_Z_ASCLL) {
|
|
368
|
+
return `${ss[0].toLowerCase()}${ss.substring(1)}`;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return undefined;
|
|
372
|
+
},
|
|
373
|
+
/**
|
|
374
|
+
* 首字母转换为大写
|
|
375
|
+
* @param ss 字符串
|
|
376
|
+
*/
|
|
377
|
+
(ss) => {
|
|
378
|
+
if (ss.indexOf('-') === -1) {
|
|
379
|
+
const firstCharCode = ss.charCodeAt(0);
|
|
380
|
+
if (firstCharCode >= StringHelper.LOWER_A_ASCLL && firstCharCode <= StringHelper.LOWER_Z_ASCLL) {
|
|
381
|
+
return `${ss[0].toUpperCase()}${ss.substring(1)}`;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return undefined;
|
|
385
|
+
},
|
|
386
|
+
/**
|
|
387
|
+
* CamelCase转换为KebabCase
|
|
388
|
+
* @param ss 字符串
|
|
389
|
+
*/
|
|
390
|
+
(ss) => {
|
|
391
|
+
return StringHelper.camelCaseToKebabCase(ss);
|
|
392
|
+
}
|
|
393
|
+
];
|
|
394
|
+
|
|
395
|
+
private static resolveCommonWidgetComponent(widget: string): ResolveComponentType {
|
|
396
|
+
let component = DslRender.resolveCommonComponentCache[widget];
|
|
397
|
+
if (component) {
|
|
398
|
+
return component;
|
|
399
|
+
}
|
|
400
|
+
if (htmlInternalTags.includes(widget)) {
|
|
401
|
+
return widget;
|
|
402
|
+
}
|
|
403
|
+
component = resolveDynamicComponent(
|
|
404
|
+
`${DEFAULT_TAG_PREFIX}-${StringHelper.camelCaseToKebabCase(widget)}`
|
|
405
|
+
) as ResolveComponentType;
|
|
406
|
+
if (typeof component === 'string') {
|
|
407
|
+
component = resolveDynamicComponent(widget) as ResolveComponentType;
|
|
408
|
+
}
|
|
409
|
+
DslRender.resolveCommonComponentCache[widget] = component;
|
|
410
|
+
return component;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
private static resolveWidgetComponent(widget: string): ResolveComponentType {
|
|
414
|
+
let component = DslRender.resolveComponentCache[widget];
|
|
415
|
+
if (component) {
|
|
416
|
+
return component;
|
|
417
|
+
}
|
|
418
|
+
if (htmlInternalTags.includes(widget)) {
|
|
419
|
+
return widget;
|
|
420
|
+
}
|
|
421
|
+
component = resolveDynamicComponent(widget) as ResolveComponentType;
|
|
422
|
+
if (typeof component === 'string') {
|
|
423
|
+
for (const resolveMethod of DslRender.resolveMethods) {
|
|
424
|
+
const resolveWidget = resolveMethod(widget);
|
|
425
|
+
if (resolveWidget) {
|
|
426
|
+
const finalComponent = resolveDynamicComponent(resolveWidget) as ResolveComponentType;
|
|
427
|
+
if (typeof finalComponent !== 'string') {
|
|
428
|
+
component = finalComponent;
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
DslRender.resolveComponentCache[widget] = component;
|
|
435
|
+
return component;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* dsl渲染帮助类
|
|
441
|
+
*/
|
|
442
|
+
class DslRenderHelper {
|
|
443
|
+
/**
|
|
444
|
+
* 判定是否需要更新Key
|
|
445
|
+
* @param dsl 指定dsl
|
|
446
|
+
* @param options 渲染可选项
|
|
447
|
+
*/
|
|
448
|
+
public static predictIsUpdateKey(dsl: DslDefinition, options: DslRenderOptions | undefined): boolean {
|
|
449
|
+
const dynamicKey = options?.dynamicKey || false;
|
|
450
|
+
const focusUpdate = options?.focusUpdate || false;
|
|
451
|
+
if (dsl.key) {
|
|
452
|
+
if (focusUpdate) {
|
|
453
|
+
return true;
|
|
454
|
+
}
|
|
455
|
+
} else if (dynamicKey) {
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
public static predictIsRecursion(options: DslRenderOptions | undefined): boolean {
|
|
462
|
+
return options?.recursion || false;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { RuntimeContextManager } from '@oinone/kunlun-engine';
|
|
2
|
+
import { isDev } from '@oinone/kunlun-router';
|
|
3
|
+
import { App, Component, Directive, Plugin } from 'vue';
|
|
4
|
+
|
|
5
|
+
export function componentInstall(component: Component, name?: string | string[]): void {
|
|
6
|
+
if (!name) {
|
|
7
|
+
name = component.name;
|
|
8
|
+
}
|
|
9
|
+
const app = RuntimeContextManager.createOrReplace<App>().frameworkInstance;
|
|
10
|
+
if (name) {
|
|
11
|
+
if (typeof name === 'string') {
|
|
12
|
+
app.component(name, component);
|
|
13
|
+
} else {
|
|
14
|
+
name.forEach((s) => app.component(s, component));
|
|
15
|
+
}
|
|
16
|
+
} else if (isDev()) {
|
|
17
|
+
console.warn('component install error. reason: name is blank.', component);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function directiveInstall(directive: Directive, name: string) {
|
|
22
|
+
const app = RuntimeContextManager.createOrReplace<App>().frameworkInstance;
|
|
23
|
+
app.directive(name, directive);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function pluginInstall(plugin: Plugin, ...options: unknown[]) {
|
|
27
|
+
const app = RuntimeContextManager.createOrReplace<App>().frameworkInstance;
|
|
28
|
+
app.use(plugin, ...options);
|
|
29
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { StableSlotProp } from '@oinone/kunlun-vue-ui-common';
|
|
2
|
+
import { Slots, VNode } from 'vue';
|
|
3
|
+
import { VueWidget } from '../basic';
|
|
4
|
+
|
|
5
|
+
export function renderWidgets(widgets: VueWidget[], ctx: Record<string, unknown>, slots?: Slots) {
|
|
6
|
+
let vNodes: VNode | VNode[] | undefined;
|
|
7
|
+
const { length } = widgets;
|
|
8
|
+
for (let i = length - 1; i >= 0; i--) {
|
|
9
|
+
const widget = widgets[i];
|
|
10
|
+
if (vNodes) {
|
|
11
|
+
const finalVNodes = Array.isArray(vNodes) ? vNodes : [vNodes];
|
|
12
|
+
vNodes = widget.render(ctx, { default: () => finalVNodes, ...StableSlotProp });
|
|
13
|
+
} else {
|
|
14
|
+
vNodes = widget.render(ctx, {
|
|
15
|
+
...slots,
|
|
16
|
+
...StableSlotProp
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return vNodes;
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { CastHelper } from '@oinone/kunlun-shared';
|
|
2
|
+
import { VueWidget, Widget } from '../basic';
|
|
3
|
+
|
|
4
|
+
export function newVueWidget(): VueWidget {
|
|
5
|
+
return new VueWidget();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getWidget(handler: string): VueWidget | undefined {
|
|
9
|
+
return CastHelper.cast(Widget.select(handler));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getWidgetNotNull(handle: string): VueWidget {
|
|
13
|
+
return getWidget(handle) || newVueWidget();
|
|
14
|
+
}
|