km-card-layout-component-miniprogram 0.1.6 → 0.1.8
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/example/pages/home/index.js +1 -351
- package/miniprogram_dist/components/card-layout/index.js +25 -188
- package/miniprogram_dist/components/card-layout/index.wxml +17 -9
- package/miniprogram_dist/components/card-layout/index.wxss +11 -8
- package/miniprogram_dist/vendor/km-card-layout-core/bindings.js +74 -0
- package/miniprogram_dist/vendor/km-card-layout-core/data.js +38 -0
- package/miniprogram_dist/vendor/km-card-layout-core/helpers.js +72 -0
- package/miniprogram_dist/vendor/km-card-layout-core/index.js +15 -366
- package/miniprogram_dist/vendor/km-card-layout-core/interface/index.js +1 -0
- package/miniprogram_dist/vendor/km-card-layout-core/layout.js +117 -0
- package/miniprogram_dist/vendor/km-card-layout-core/ops/changeBackground.js +135 -0
- package/miniprogram_dist/vendor/km-card-layout-core/render/builder.js +210 -0
- package/miniprogram_dist/vendor/km-card-layout-core/utils.js +25 -0
- package/package.json +1 -1
- package/script/sync-core.js +10 -2
- package/src/components/card-layout/index.ts +30 -278
- package/src/components/card-layout/index.wxml +17 -9
- package/src/components/card-layout/index.wxss +11 -8
- package/src/vendor/km-card-layout-core/bindings.ts +84 -0
- package/src/vendor/km-card-layout-core/data.ts +38 -0
- package/src/vendor/km-card-layout-core/helpers.ts +76 -0
- package/src/vendor/km-card-layout-core/index.ts +21 -458
- package/src/vendor/km-card-layout-core/interface/data/payload.ts +20 -2
- package/src/vendor/km-card-layout-core/interface/index.ts +1 -0
- package/src/vendor/km-card-layout-core/interface/render.ts +1 -0
- package/src/vendor/km-card-layout-core/layout.ts +129 -0
- package/src/vendor/km-card-layout-core/ops/changeBackground.ts +169 -0
- package/src/vendor/km-card-layout-core/render/builder.ts +288 -0
- package/src/vendor/km-card-layout-core/types.d.ts +97 -8
- package/src/vendor/km-card-layout-core/utils.ts +9 -0
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
CardElement,
|
|
3
2
|
CardLayoutInput,
|
|
4
3
|
CardLayoutSchema,
|
|
5
|
-
|
|
6
|
-
ImageElement,
|
|
7
|
-
LayoutPanelElement,
|
|
8
|
-
TextElement,
|
|
4
|
+
RenderNode,
|
|
9
5
|
} from '../../vendor/km-card-layout-core/index';
|
|
10
6
|
import {
|
|
11
|
-
|
|
7
|
+
buildRenderResult,
|
|
12
8
|
normalizeLayout,
|
|
13
|
-
resolveBindingValue,
|
|
14
|
-
styleObjectToString,
|
|
15
9
|
} from '../../vendor/km-card-layout-core/index';
|
|
16
10
|
import { ICON_CODE_MAP } from './icon-map';
|
|
17
11
|
|
|
@@ -19,34 +13,12 @@ type LayoutData = {
|
|
|
19
13
|
[key: string]: any;
|
|
20
14
|
};
|
|
21
15
|
|
|
22
|
-
interface RenderIcon {
|
|
23
|
-
name?: string;
|
|
24
|
-
text?: string;
|
|
25
|
-
size?: string;
|
|
26
|
-
color?: string;
|
|
27
|
-
gap?: string;
|
|
28
|
-
align?: 'left' | 'right';
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
interface RenderElement {
|
|
32
|
-
id: string;
|
|
33
|
-
type: CardElement['type'];
|
|
34
|
-
wrapperStyle: string;
|
|
35
|
-
contentStyle: string;
|
|
36
|
-
name?: string;
|
|
37
|
-
text?: string;
|
|
38
|
-
src?: string;
|
|
39
|
-
mode?: string;
|
|
40
|
-
icon?: RenderIcon;
|
|
41
|
-
children?: RenderElement[];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
16
|
interface RenderCard {
|
|
45
17
|
id: string;
|
|
46
18
|
cardStyle: string;
|
|
47
19
|
backgroundImage?: string;
|
|
48
20
|
backgroundStyle: string;
|
|
49
|
-
nodes:
|
|
21
|
+
nodes: RenderNode[];
|
|
50
22
|
}
|
|
51
23
|
|
|
52
24
|
const ensureArray = (input: CardLayoutInput | any): CardLayoutInput => {
|
|
@@ -59,106 +31,6 @@ const pickCardId = (layout: any, idx: number) => {
|
|
|
59
31
|
return `card-${idx}`;
|
|
60
32
|
};
|
|
61
33
|
|
|
62
|
-
const withUnit = (value: any, unit: 'px' | 'rpx') => addUnit(value, unit);
|
|
63
|
-
|
|
64
|
-
const buildCardStyle = (layout: CardLayoutSchema, unit: 'px' | 'rpx') =>
|
|
65
|
-
styleObjectToString(
|
|
66
|
-
{
|
|
67
|
-
width: withUnit(layout.width, unit),
|
|
68
|
-
height: withUnit(layout.height, unit),
|
|
69
|
-
color: layout.fontColor,
|
|
70
|
-
borderRadius:
|
|
71
|
-
layout.borderRadius !== undefined
|
|
72
|
-
? withUnit(layout.borderRadius, unit)
|
|
73
|
-
: undefined,
|
|
74
|
-
padding:
|
|
75
|
-
layout.padding !== undefined ? withUnit(layout.padding, unit) : undefined,
|
|
76
|
-
position: 'relative',
|
|
77
|
-
overflow: 'hidden',
|
|
78
|
-
boxSizing: 'border-box',
|
|
79
|
-
backgroundColor: 'transparent',
|
|
80
|
-
},
|
|
81
|
-
unit,
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
const buildBackgroundStyle = (layout: CardLayoutSchema, unit: 'px' | 'rpx') =>
|
|
85
|
-
styleObjectToString(
|
|
86
|
-
{
|
|
87
|
-
zIndex: layout.backgroundZIndex,
|
|
88
|
-
borderRadius:
|
|
89
|
-
layout.borderRadius !== undefined
|
|
90
|
-
? withUnit(layout.borderRadius, unit)
|
|
91
|
-
: undefined,
|
|
92
|
-
width: '100%',
|
|
93
|
-
height: '100%',
|
|
94
|
-
position: 'absolute',
|
|
95
|
-
left: 0,
|
|
96
|
-
top: 0,
|
|
97
|
-
},
|
|
98
|
-
unit,
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
const buildWrapperStyle = (el: CardElement, unit: 'px' | 'rpx') => {
|
|
102
|
-
if (!el.layout || el.layout.mode !== 'absolute') return '';
|
|
103
|
-
return styleObjectToString(
|
|
104
|
-
{
|
|
105
|
-
position: 'absolute',
|
|
106
|
-
left: withUnit(el.layout.x, unit),
|
|
107
|
-
top: withUnit(el.layout.y, unit),
|
|
108
|
-
width: withUnit(el.layout.width, unit),
|
|
109
|
-
height: withUnit(el.layout.height, unit),
|
|
110
|
-
zIndex: el.layout.zIndex,
|
|
111
|
-
boxSizing: 'border-box',
|
|
112
|
-
display: 'flex',
|
|
113
|
-
alignItems: 'center',
|
|
114
|
-
},
|
|
115
|
-
unit,
|
|
116
|
-
);
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const buildPanelContentStyle = (
|
|
120
|
-
el: LayoutPanelElement,
|
|
121
|
-
unit: 'px' | 'rpx',
|
|
122
|
-
) =>
|
|
123
|
-
styleObjectToString(
|
|
124
|
-
{
|
|
125
|
-
position: 'relative',
|
|
126
|
-
width: '100%',
|
|
127
|
-
height: '100%',
|
|
128
|
-
display: 'block',
|
|
129
|
-
boxSizing: 'border-box',
|
|
130
|
-
...(el.style || {}),
|
|
131
|
-
},
|
|
132
|
-
unit,
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
const buildTextContentStyle = (el: TextElement, unit: 'px' | 'rpx') => {
|
|
136
|
-
const textAlign =
|
|
137
|
-
(el.style?.textAlign as string | undefined) || el.align || undefined;
|
|
138
|
-
const style: Record<string, any> = {
|
|
139
|
-
...el.style,
|
|
140
|
-
whiteSpace: 'pre-wrap',
|
|
141
|
-
wordBreak: 'break-word',
|
|
142
|
-
lineHeight:
|
|
143
|
-
el.style?.lineHeight !== undefined && el.style?.lineHeight !== null
|
|
144
|
-
? el.style.lineHeight
|
|
145
|
-
: '1.2',
|
|
146
|
-
display: 'inline-flex',
|
|
147
|
-
alignItems: 'center',
|
|
148
|
-
};
|
|
149
|
-
if (textAlign) style.textAlign = textAlign;
|
|
150
|
-
return styleObjectToString(style, unit);
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const buildBaseContentStyle = (el: CardElement, unit: 'px' | 'rpx') =>
|
|
154
|
-
styleObjectToString(
|
|
155
|
-
{
|
|
156
|
-
...(el.style || {}),
|
|
157
|
-
boxSizing: 'border-box',
|
|
158
|
-
},
|
|
159
|
-
unit,
|
|
160
|
-
);
|
|
161
|
-
|
|
162
34
|
const mapIconGlyph = (name?: string, fallback?: string) => {
|
|
163
35
|
if (!name) return fallback;
|
|
164
36
|
const glyph = ICON_CODE_MAP[name];
|
|
@@ -166,153 +38,38 @@ const mapIconGlyph = (name?: string, fallback?: string) => {
|
|
|
166
38
|
return fallback || name;
|
|
167
39
|
};
|
|
168
40
|
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
if (style === 'dot') name = 'round';
|
|
180
|
-
else if (style === 'line') name = baseName ? `${baseName}-line` : undefined;
|
|
181
|
-
else name = baseName || undefined;
|
|
182
|
-
if (!name) return undefined;
|
|
183
|
-
|
|
184
|
-
const size =
|
|
185
|
-
icon.size !== undefined && icon.size !== null
|
|
186
|
-
? icon.size
|
|
187
|
-
: (el.style?.fontSize as number | string | undefined);
|
|
188
|
-
const gap = icon.gap !== undefined && icon.gap !== null ? icon.gap : 4;
|
|
189
|
-
const color =
|
|
190
|
-
icon.color ?? (el.style?.color as string | undefined) ?? undefined;
|
|
41
|
+
const mapRenderNode = (node: RenderNode): RenderNode => {
|
|
42
|
+
const icon = node.icon
|
|
43
|
+
? {
|
|
44
|
+
...node.icon,
|
|
45
|
+
text: mapIconGlyph(node.icon.name, node.icon.text),
|
|
46
|
+
}
|
|
47
|
+
: undefined;
|
|
48
|
+
const children = node.children?.map(mapRenderNode);
|
|
49
|
+
const mappedText =
|
|
50
|
+
node.type === 'icon' ? mapIconGlyph(node.name, node.text) : node.text;
|
|
191
51
|
|
|
192
|
-
const text = mapIconGlyph(name, name);
|
|
193
52
|
return {
|
|
194
|
-
|
|
195
|
-
text,
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
color,
|
|
199
|
-
align: icon.align || 'left',
|
|
53
|
+
...node,
|
|
54
|
+
text: mappedText,
|
|
55
|
+
icon,
|
|
56
|
+
children,
|
|
200
57
|
};
|
|
201
58
|
};
|
|
202
59
|
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
id: el.id,
|
|
215
|
-
type: el.type,
|
|
216
|
-
wrapperStyle,
|
|
217
|
-
contentStyle: buildPanelContentStyle(panel, unit),
|
|
218
|
-
children: buildRenderNodes(panel.children || [], data, unit),
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (el.type === 'text') {
|
|
223
|
-
const textValue =
|
|
224
|
-
resolveBindingValue(el.binding, data) ?? el.defaultValue ?? '';
|
|
225
|
-
return {
|
|
226
|
-
id: el.id,
|
|
227
|
-
type: el.type,
|
|
228
|
-
wrapperStyle,
|
|
229
|
-
contentStyle: buildTextContentStyle(el as TextElement, unit),
|
|
230
|
-
text: `${textValue}`,
|
|
231
|
-
icon: buildTextIcon(el as TextElement, unit),
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (el.type === 'image') {
|
|
236
|
-
const style: Record<string, any> = { ...(el.style || {}) };
|
|
237
|
-
const borderWidth = Number(style.borderWidth);
|
|
238
|
-
if (Number.isFinite(borderWidth) && borderWidth > 0) {
|
|
239
|
-
if (!style.borderStyle) style.borderStyle = 'solid';
|
|
240
|
-
if (!style.borderColor) style.borderColor = '#000000';
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const src =
|
|
244
|
-
resolveBindingValue(el.binding, data) ??
|
|
245
|
-
(el as ImageElement).defaultUrl ??
|
|
246
|
-
el.defaultValue ??
|
|
247
|
-
'';
|
|
248
|
-
const mode =
|
|
249
|
-
(el as ImageElement).fit === 'contain' ? 'aspectFit' : 'aspectFill';
|
|
250
|
-
return {
|
|
251
|
-
id: el.id,
|
|
252
|
-
type: el.type,
|
|
253
|
-
wrapperStyle,
|
|
254
|
-
contentStyle: styleObjectToString(style, unit),
|
|
255
|
-
src,
|
|
256
|
-
mode,
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (el.type === 'icon') {
|
|
261
|
-
const resolved =
|
|
262
|
-
resolveBindingValue(el.binding, data) ??
|
|
263
|
-
(el as IconElement).name ??
|
|
264
|
-
el.defaultValue ??
|
|
265
|
-
'';
|
|
266
|
-
const text = mapIconGlyph(`${resolved}`, `${resolved}`);
|
|
267
|
-
return {
|
|
268
|
-
id: el.id,
|
|
269
|
-
type: el.type,
|
|
270
|
-
wrapperStyle,
|
|
271
|
-
contentStyle: buildBaseContentStyle(el, unit),
|
|
272
|
-
name: `${resolved}`,
|
|
273
|
-
text,
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (el.type === 'custom') {
|
|
278
|
-
return {
|
|
279
|
-
id: el.id,
|
|
280
|
-
type: el.type,
|
|
281
|
-
wrapperStyle,
|
|
282
|
-
contentStyle: buildBaseContentStyle(el, unit),
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
return null;
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
const buildRenderNodes = (
|
|
290
|
-
children: CardElement[],
|
|
291
|
-
data: LayoutData,
|
|
292
|
-
unit: 'px' | 'rpx',
|
|
293
|
-
) => {
|
|
294
|
-
if (!Array.isArray(children)) return [];
|
|
295
|
-
const nodes: RenderElement[] = [];
|
|
296
|
-
children.forEach(el => {
|
|
297
|
-
if (!el || el.visible === false) return;
|
|
298
|
-
const node = buildRenderNode(el, data, unit);
|
|
299
|
-
if (node) nodes.push(node);
|
|
300
|
-
});
|
|
301
|
-
return nodes;
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
const buildCards = (
|
|
305
|
-
layouts: CardLayoutInput,
|
|
306
|
-
data: LayoutData,
|
|
307
|
-
unit: 'px' | 'rpx',
|
|
308
|
-
) =>
|
|
309
|
-
layouts.map(layout => ({
|
|
310
|
-
id: layout.name || (layout as any).id || '',
|
|
311
|
-
cardStyle: buildCardStyle(layout, unit),
|
|
312
|
-
backgroundImage: layout.backgroundImage || '',
|
|
313
|
-
backgroundStyle: buildBackgroundStyle(layout, unit),
|
|
314
|
-
nodes: buildRenderNodes(layout.children || [], data, unit),
|
|
60
|
+
const mapRenderTree = (nodes: RenderNode[]) =>
|
|
61
|
+
Array.isArray(nodes) ? nodes.map(mapRenderNode) : [];
|
|
62
|
+
|
|
63
|
+
const buildCards = (layouts: CardLayoutSchema[], data: LayoutData) => {
|
|
64
|
+
const renders = buildRenderResult(layouts as CardLayoutInput, data, 'rpx');
|
|
65
|
+
return renders.map((render, idx) => ({
|
|
66
|
+
id: pickCardId(layouts[idx], idx),
|
|
67
|
+
cardStyle: render.cardStyle,
|
|
68
|
+
backgroundImage: render.backgroundImage || '',
|
|
69
|
+
backgroundStyle: render.backgroundStyle,
|
|
70
|
+
nodes: mapRenderTree(render.renderTree),
|
|
315
71
|
}));
|
|
72
|
+
};
|
|
316
73
|
|
|
317
74
|
Component({
|
|
318
75
|
options: {
|
|
@@ -358,12 +115,7 @@ Component({
|
|
|
358
115
|
}
|
|
359
116
|
|
|
360
117
|
const normalizedLayouts = normalizeLayout(layoutInput);
|
|
361
|
-
const cards = buildCards(normalizedLayouts, dataInput
|
|
362
|
-
(card, idx) => ({
|
|
363
|
-
...card,
|
|
364
|
-
id: pickCardId(layoutInput[idx], idx),
|
|
365
|
-
}),
|
|
366
|
-
);
|
|
118
|
+
const cards = buildCards(normalizedLayouts, dataInput);
|
|
367
119
|
|
|
368
120
|
this.setData({ cards });
|
|
369
121
|
},
|
|
@@ -62,15 +62,23 @@
|
|
|
62
62
|
<view class="km-node km-node--text" style="{{node.wrapperStyle}}">
|
|
63
63
|
<view class="km-node__text" style="{{node.contentStyle}}">
|
|
64
64
|
<block wx:if="{{node.icon && node.icon.name}}">
|
|
65
|
-
<view
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
65
|
+
<view class="km-node__text-content">
|
|
66
|
+
<block wx:if="{{node.icon.align === 'right'}}">
|
|
67
|
+
<text class="km-node__text-value">{{node.text || ''}}</text>
|
|
68
|
+
<view style="{{node.icon.wrapperStyle}}">
|
|
69
|
+
<text
|
|
70
|
+
class="km-node__text-icon icon"
|
|
71
|
+
style="font-size: {{node.icon.size || '16px'}}; color: {{node.icon.color || ''}}; margin-right: {{node.icon.gap || ''}};">{{node.icon.text || node.icon.name || ''}}</text>
|
|
72
|
+
</view>
|
|
73
|
+
</block>
|
|
74
|
+
<block wx:else>
|
|
75
|
+
<view style="{{node.icon.wrapperStyle}}">
|
|
76
|
+
<text
|
|
77
|
+
class="km-node__text-icon icon"
|
|
78
|
+
style="font-size: {{node.icon.size || '16px'}}; color: {{node.icon.color || ''}}; margin-right: {{node.icon.gap || ''}};">{{node.icon.text || node.icon.name || ''}}</text>
|
|
79
|
+
</view>
|
|
80
|
+
<text class="km-node__text-value">{{node.text || ''}}</text>
|
|
81
|
+
</block>
|
|
74
82
|
</view>
|
|
75
83
|
</block>
|
|
76
84
|
<block wx:else>
|
|
@@ -78,25 +78,28 @@
|
|
|
78
78
|
.km-node__text {
|
|
79
79
|
width: 100%;
|
|
80
80
|
height: 100%;
|
|
81
|
-
display:
|
|
82
|
-
|
|
81
|
+
display: block;
|
|
82
|
+
box-sizing: border-box;
|
|
83
|
+
text-align: inherit;
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
.km-node__text-content {
|
|
86
|
-
display: inline-
|
|
87
|
-
align
|
|
87
|
+
display: inline-block;
|
|
88
|
+
vertical-align: middle;
|
|
89
|
+
height: 100%;
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
.km-node__text-value {
|
|
91
93
|
display: inline-block;
|
|
92
94
|
white-space: pre-wrap;
|
|
93
95
|
word-break: break-word;
|
|
96
|
+
vertical-align: middle;
|
|
97
|
+
}
|
|
98
|
+
.km-node--text{
|
|
99
|
+
/* 溢出隐藏 */
|
|
94
100
|
}
|
|
95
|
-
|
|
96
101
|
.km-node--text text {
|
|
97
|
-
display:
|
|
98
|
-
white-space: pre-wrap;
|
|
99
|
-
word-break: break-word;
|
|
102
|
+
display: inline;
|
|
100
103
|
}
|
|
101
104
|
|
|
102
105
|
/* ICON */
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { CardElement, CardLayoutSchema } from './interface';
|
|
2
|
+
import type {
|
|
3
|
+
TemplateBackground,
|
|
4
|
+
TemplateItem,
|
|
5
|
+
} from './interface/data/payload';
|
|
6
|
+
|
|
7
|
+
export function stripLayoutBindings(
|
|
8
|
+
layouts: CardLayoutSchema[] = []
|
|
9
|
+
): CardLayoutSchema[] {
|
|
10
|
+
const targetLayouts = Array.isArray(layouts) ? layouts : [];
|
|
11
|
+
const stripElement = (el: CardElement): CardElement => {
|
|
12
|
+
const { binding: _b, defaultValue: _d, ...rest } = el as any;
|
|
13
|
+
if (el.type === 'layout-panel') {
|
|
14
|
+
return {
|
|
15
|
+
...rest,
|
|
16
|
+
children: (el.children || []).map(stripElement),
|
|
17
|
+
} as CardElement;
|
|
18
|
+
}
|
|
19
|
+
return rest as CardElement;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return targetLayouts.map(layout => ({
|
|
23
|
+
...layout,
|
|
24
|
+
children: (layout.children || []).map(stripElement),
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function applyItemCollectBindings(
|
|
29
|
+
layouts: CardLayoutSchema[] = [],
|
|
30
|
+
items: TemplateItem[] = []
|
|
31
|
+
): CardLayoutSchema[] {
|
|
32
|
+
const targetLayouts = Array.isArray(layouts) ? layouts : [];
|
|
33
|
+
const metaMap = new Map<string, TemplateItem>();
|
|
34
|
+
const metaList = Array.isArray(items) ? items : [];
|
|
35
|
+
metaList.forEach(item => {
|
|
36
|
+
if (item && item.id !== undefined && item.id !== null) {
|
|
37
|
+
metaMap.set(String(item.id), item);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const assignBinding = (el: CardElement): CardElement => {
|
|
42
|
+
const meta = metaMap.get(String(el.id));
|
|
43
|
+
const binding =
|
|
44
|
+
meta && meta.bind !== undefined && meta.bind !== null
|
|
45
|
+
? meta.bind
|
|
46
|
+
: el.binding;
|
|
47
|
+
const defaultValue =
|
|
48
|
+
meta && meta.default !== undefined ? meta.default : el.defaultValue;
|
|
49
|
+
const key = meta && meta.key !== undefined ? meta.key : el.key;
|
|
50
|
+
const base: any = { ...el };
|
|
51
|
+
if (binding !== undefined) base.binding = binding;
|
|
52
|
+
else delete base.binding;
|
|
53
|
+
if (defaultValue !== undefined) base.defaultValue = defaultValue;
|
|
54
|
+
else delete base.defaultValue;
|
|
55
|
+
if (key !== undefined) base.key = key;
|
|
56
|
+
else delete base.key;
|
|
57
|
+
|
|
58
|
+
if (el.type === 'layout-panel') {
|
|
59
|
+
return {
|
|
60
|
+
...base,
|
|
61
|
+
children: (el.children || []).map(assignBinding),
|
|
62
|
+
} as CardElement;
|
|
63
|
+
}
|
|
64
|
+
return base as CardElement;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
return targetLayouts.map(layout => ({
|
|
68
|
+
...layout,
|
|
69
|
+
children: (layout.children || []).map(assignBinding),
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function getTemplateItems(ids: string, items: TemplateItem[]) {
|
|
74
|
+
const idArray = ids.split(',').map(id => id.trim());
|
|
75
|
+
return items.filter(item => idArray.includes(String(item.id)));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function getTemplateBackgrounds(
|
|
79
|
+
ids: string,
|
|
80
|
+
items: TemplateBackground[]
|
|
81
|
+
) {
|
|
82
|
+
const idArray = ids.split(',').map(id => id.trim());
|
|
83
|
+
return items.filter(item => idArray.includes(String(item.id)));
|
|
84
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { isObject } from './helpers';
|
|
2
|
+
|
|
3
|
+
const pathToSegments = (path: string): string[] =>
|
|
4
|
+
`${path || ''}`
|
|
5
|
+
.replace(/\[(\d+)\]/g, '.$1')
|
|
6
|
+
.split('.')
|
|
7
|
+
.map(p => p.trim())
|
|
8
|
+
.filter(Boolean);
|
|
9
|
+
|
|
10
|
+
const readByPath = (data: any, path: string): any => {
|
|
11
|
+
if (path === undefined || path === null || path === '') return data;
|
|
12
|
+
const segments = pathToSegments(path);
|
|
13
|
+
let cursor: any = data;
|
|
14
|
+
for (let i = 0; i < segments.length; i += 1) {
|
|
15
|
+
if (!isObject(cursor) && !Array.isArray(cursor)) return undefined;
|
|
16
|
+
const key = segments[i];
|
|
17
|
+
if (Array.isArray(cursor)) {
|
|
18
|
+
const idx = Number(key);
|
|
19
|
+
cursor = Number.isNaN(idx) ? undefined : cursor[idx];
|
|
20
|
+
} else {
|
|
21
|
+
cursor = (cursor as Record<string, any>)[key];
|
|
22
|
+
}
|
|
23
|
+
if (cursor === undefined || cursor === null) {
|
|
24
|
+
return cursor;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return cursor;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const resolveBindingValue = (
|
|
31
|
+
binding: string | undefined,
|
|
32
|
+
rootData: Record<string, any>,
|
|
33
|
+
context?: Record<string, any>
|
|
34
|
+
): any => {
|
|
35
|
+
if (!binding) return undefined;
|
|
36
|
+
const value = readByPath(rootData, binding);
|
|
37
|
+
return value === undefined ? undefined : value;
|
|
38
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const DIMENSION_PROPS = new Set([
|
|
2
|
+
'width',
|
|
3
|
+
'height',
|
|
4
|
+
'top',
|
|
5
|
+
'right',
|
|
6
|
+
'bottom',
|
|
7
|
+
'left',
|
|
8
|
+
'padding',
|
|
9
|
+
'paddingTop',
|
|
10
|
+
'paddingBottom',
|
|
11
|
+
'paddingLeft',
|
|
12
|
+
'paddingRight',
|
|
13
|
+
'margin',
|
|
14
|
+
'marginTop',
|
|
15
|
+
'marginBottom',
|
|
16
|
+
'marginLeft',
|
|
17
|
+
'marginRight',
|
|
18
|
+
'fontSize',
|
|
19
|
+
'lineHeight',
|
|
20
|
+
'borderRadius',
|
|
21
|
+
'borderWidth',
|
|
22
|
+
'letterSpacing',
|
|
23
|
+
'gap',
|
|
24
|
+
'rowGap',
|
|
25
|
+
'columnGap',
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
export const toNumber = (value: unknown): number | undefined => {
|
|
29
|
+
const num = Number(value);
|
|
30
|
+
return Number.isFinite(num) ? num : undefined;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const toKebab = (key: string): string =>
|
|
34
|
+
key.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
|
35
|
+
|
|
36
|
+
export const addUnit = (
|
|
37
|
+
value: string | number | undefined | null,
|
|
38
|
+
unit: 'px' | 'rpx'
|
|
39
|
+
): string | undefined => {
|
|
40
|
+
if (value === undefined || value === null || value === '') return undefined;
|
|
41
|
+
if (typeof value === 'number') {
|
|
42
|
+
const ratio = unit === 'rpx' ? 2 : 1;
|
|
43
|
+
return `${value * ratio}${unit}`;
|
|
44
|
+
}
|
|
45
|
+
if (typeof value === 'string') {
|
|
46
|
+
const parsed = Number(value);
|
|
47
|
+
if (Number.isFinite(parsed)) {
|
|
48
|
+
const ratio = unit === 'rpx' ? 2 : 1;
|
|
49
|
+
return `${parsed * ratio}${unit}`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return `${value}`;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const styleObjectToString = (
|
|
56
|
+
style?: Record<string, any>,
|
|
57
|
+
unit: 'px' | 'rpx' = 'px'
|
|
58
|
+
): string => {
|
|
59
|
+
if (!style) return '';
|
|
60
|
+
const pairs: string[] = [];
|
|
61
|
+
Object.keys(style).forEach(key => {
|
|
62
|
+
const value = style[key];
|
|
63
|
+
if (value === undefined || value === null || value === '') return;
|
|
64
|
+
const useUnit = DIMENSION_PROPS.has(key)
|
|
65
|
+
? addUnit(value as any, unit)
|
|
66
|
+
: value;
|
|
67
|
+
if (useUnit === undefined || useUnit === null || useUnit === '') return;
|
|
68
|
+
pairs.push(`${toKebab(key)}:${useUnit}`);
|
|
69
|
+
});
|
|
70
|
+
return pairs.join(';');
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const isObject = (
|
|
74
|
+
val: unknown
|
|
75
|
+
): val is Record<string, any> | any[] =>
|
|
76
|
+
Boolean(val) && typeof val === 'object';
|