km-card-layout-component-miniprogram 0.1.7 → 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/miniprogram_dist/components/card-layout/index.js +25 -193
- package/miniprogram_dist/components/card-layout/index.wxss +3 -1
- 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 -367
- 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 +23 -130
- package/package.json +1 -1
- package/script/sync-core.js +10 -2
- package/src/components/card-layout/index.ts +30 -287
- package/src/components/card-layout/index.wxss +3 -1
- 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 -460
- 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 -5
- package/src/vendor/km-card-layout-core/utils.ts +9 -141
|
@@ -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,35 +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
|
-
wrapperStyle: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
interface RenderElement {
|
|
33
|
-
id: string;
|
|
34
|
-
type: CardElement['type'];
|
|
35
|
-
wrapperStyle: string;
|
|
36
|
-
contentStyle: string;
|
|
37
|
-
name?: string;
|
|
38
|
-
text?: string;
|
|
39
|
-
src?: string;
|
|
40
|
-
mode?: string;
|
|
41
|
-
icon?: RenderIcon;
|
|
42
|
-
children?: RenderElement[];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
16
|
interface RenderCard {
|
|
46
17
|
id: string;
|
|
47
18
|
cardStyle: string;
|
|
48
19
|
backgroundImage?: string;
|
|
49
20
|
backgroundStyle: string;
|
|
50
|
-
nodes:
|
|
21
|
+
nodes: RenderNode[];
|
|
51
22
|
}
|
|
52
23
|
|
|
53
24
|
const ensureArray = (input: CardLayoutInput | any): CardLayoutInput => {
|
|
@@ -60,106 +31,6 @@ const pickCardId = (layout: any, idx: number) => {
|
|
|
60
31
|
return `card-${idx}`;
|
|
61
32
|
};
|
|
62
33
|
|
|
63
|
-
const withUnit = (value: any, unit: 'px' | 'rpx') => addUnit(value, unit);
|
|
64
|
-
|
|
65
|
-
const buildCardStyle = (layout: CardLayoutSchema, unit: 'px' | 'rpx') =>
|
|
66
|
-
styleObjectToString(
|
|
67
|
-
{
|
|
68
|
-
width: withUnit(layout.width, unit),
|
|
69
|
-
height: withUnit(layout.height, unit),
|
|
70
|
-
color: layout.fontColor,
|
|
71
|
-
borderRadius:
|
|
72
|
-
layout.borderRadius !== undefined
|
|
73
|
-
? withUnit(layout.borderRadius, unit)
|
|
74
|
-
: undefined,
|
|
75
|
-
padding:
|
|
76
|
-
layout.padding !== undefined ? withUnit(layout.padding, unit) : undefined,
|
|
77
|
-
position: 'relative',
|
|
78
|
-
overflow: 'hidden',
|
|
79
|
-
boxSizing: 'border-box',
|
|
80
|
-
backgroundColor: 'transparent',
|
|
81
|
-
},
|
|
82
|
-
unit,
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
const buildBackgroundStyle = (layout: CardLayoutSchema, unit: 'px' | 'rpx') =>
|
|
86
|
-
styleObjectToString(
|
|
87
|
-
{
|
|
88
|
-
zIndex: layout.backgroundZIndex,
|
|
89
|
-
borderRadius:
|
|
90
|
-
layout.borderRadius !== undefined
|
|
91
|
-
? withUnit(layout.borderRadius, unit)
|
|
92
|
-
: undefined,
|
|
93
|
-
width: '100%',
|
|
94
|
-
height: '100%',
|
|
95
|
-
position: 'absolute',
|
|
96
|
-
left: 0,
|
|
97
|
-
top: 0,
|
|
98
|
-
},
|
|
99
|
-
unit,
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
const buildWrapperStyle = (el: CardElement, unit: 'px' | 'rpx') => {
|
|
103
|
-
if (!el.layout || el.layout.mode !== 'absolute') return '';
|
|
104
|
-
return styleObjectToString(
|
|
105
|
-
{
|
|
106
|
-
position: 'absolute',
|
|
107
|
-
left: withUnit(el.layout.x, unit),
|
|
108
|
-
top: withUnit(el.layout.y, unit),
|
|
109
|
-
width: withUnit(el.layout.width, unit),
|
|
110
|
-
height: withUnit(el.layout.height, unit),
|
|
111
|
-
zIndex: el.layout.zIndex,
|
|
112
|
-
boxSizing: 'border-box',
|
|
113
|
-
display: 'flex',
|
|
114
|
-
alignItems: 'center',
|
|
115
|
-
},
|
|
116
|
-
unit,
|
|
117
|
-
);
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const buildPanelContentStyle = (
|
|
121
|
-
el: LayoutPanelElement,
|
|
122
|
-
unit: 'px' | 'rpx',
|
|
123
|
-
) =>
|
|
124
|
-
styleObjectToString(
|
|
125
|
-
{
|
|
126
|
-
position: 'relative',
|
|
127
|
-
width: '100%',
|
|
128
|
-
height: '100%',
|
|
129
|
-
display: 'block',
|
|
130
|
-
boxSizing: 'border-box',
|
|
131
|
-
...(el.style || {}),
|
|
132
|
-
},
|
|
133
|
-
unit,
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
const buildTextContentStyle = (el: TextElement, unit: 'px' | 'rpx') => {
|
|
137
|
-
const textAlign =
|
|
138
|
-
(el.style?.textAlign as string | undefined) || el.align || undefined;
|
|
139
|
-
const style: Record<string, any> = {
|
|
140
|
-
...el.style,
|
|
141
|
-
whiteSpace: 'pre-wrap',
|
|
142
|
-
wordBreak: 'break-word',
|
|
143
|
-
lineHeight:
|
|
144
|
-
el.style?.lineHeight !== undefined && el.style?.lineHeight !== null
|
|
145
|
-
? el.style.lineHeight
|
|
146
|
-
: '1.2',
|
|
147
|
-
display: 'inline-flex',
|
|
148
|
-
alignItems: 'center',
|
|
149
|
-
};
|
|
150
|
-
if (textAlign) style.textAlign = textAlign;
|
|
151
|
-
return styleObjectToString(style, unit);
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
const buildBaseContentStyle = (el: CardElement, unit: 'px' | 'rpx') =>
|
|
155
|
-
styleObjectToString(
|
|
156
|
-
{
|
|
157
|
-
...(el.style || {}),
|
|
158
|
-
boxSizing: 'border-box',
|
|
159
|
-
},
|
|
160
|
-
unit,
|
|
161
|
-
);
|
|
162
|
-
|
|
163
34
|
const mapIconGlyph = (name?: string, fallback?: string) => {
|
|
164
35
|
if (!name) return fallback;
|
|
165
36
|
const glyph = ICON_CODE_MAP[name];
|
|
@@ -167,161 +38,38 @@ const mapIconGlyph = (name?: string, fallback?: string) => {
|
|
|
167
38
|
return fallback || name;
|
|
168
39
|
};
|
|
169
40
|
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
if (style === 'dot') name = 'round';
|
|
181
|
-
else if (style === 'line') name = baseName ? `${baseName}-line` : undefined;
|
|
182
|
-
else name = baseName || undefined;
|
|
183
|
-
if (!name) return undefined;
|
|
184
|
-
|
|
185
|
-
const size =
|
|
186
|
-
icon.size !== undefined && icon.size !== null
|
|
187
|
-
? icon.size
|
|
188
|
-
: (el.style?.fontSize as number | string | undefined);
|
|
189
|
-
const gap = icon.gap !== undefined && icon.gap !== null ? icon.gap : 4;
|
|
190
|
-
const color =
|
|
191
|
-
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;
|
|
192
51
|
|
|
193
|
-
const text = mapIconGlyph(name, name);
|
|
194
52
|
return {
|
|
195
|
-
|
|
196
|
-
text,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
wrapperStyle: styleObjectToString(
|
|
200
|
-
{
|
|
201
|
-
display: 'inline-flex',
|
|
202
|
-
alignItems: 'center',
|
|
203
|
-
height: el.style?.lineHeight || 'auto',
|
|
204
|
-
},
|
|
205
|
-
unit,
|
|
206
|
-
),
|
|
207
|
-
color,
|
|
208
|
-
align: icon.align || 'left',
|
|
53
|
+
...node,
|
|
54
|
+
text: mappedText,
|
|
55
|
+
icon,
|
|
56
|
+
children,
|
|
209
57
|
};
|
|
210
58
|
};
|
|
211
59
|
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
id: el.id,
|
|
224
|
-
type: el.type,
|
|
225
|
-
wrapperStyle,
|
|
226
|
-
contentStyle: buildPanelContentStyle(panel, unit),
|
|
227
|
-
children: buildRenderNodes(panel.children || [], data, unit),
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if (el.type === 'text') {
|
|
232
|
-
const textValue =
|
|
233
|
-
resolveBindingValue(el.binding, data) ?? el.defaultValue ?? '';
|
|
234
|
-
return {
|
|
235
|
-
id: el.id,
|
|
236
|
-
type: el.type,
|
|
237
|
-
wrapperStyle,
|
|
238
|
-
contentStyle: buildTextContentStyle(el as TextElement, unit),
|
|
239
|
-
text: `${textValue}`,
|
|
240
|
-
icon: buildTextIcon(el as TextElement, unit),
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (el.type === 'image') {
|
|
245
|
-
const style: Record<string, any> = { ...(el.style || {}) };
|
|
246
|
-
const borderWidth = Number(style.borderWidth);
|
|
247
|
-
if (Number.isFinite(borderWidth) && borderWidth > 0) {
|
|
248
|
-
if (!style.borderStyle) style.borderStyle = 'solid';
|
|
249
|
-
if (!style.borderColor) style.borderColor = '#000000';
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const src =
|
|
253
|
-
resolveBindingValue(el.binding, data) ??
|
|
254
|
-
(el as ImageElement).defaultUrl ??
|
|
255
|
-
el.defaultValue ??
|
|
256
|
-
'';
|
|
257
|
-
const mode =
|
|
258
|
-
(el as ImageElement).fit === 'contain' ? 'aspectFit' : 'aspectFill';
|
|
259
|
-
return {
|
|
260
|
-
id: el.id,
|
|
261
|
-
type: el.type,
|
|
262
|
-
wrapperStyle,
|
|
263
|
-
contentStyle: styleObjectToString(style, unit),
|
|
264
|
-
src,
|
|
265
|
-
mode,
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (el.type === 'icon') {
|
|
270
|
-
const resolved =
|
|
271
|
-
resolveBindingValue(el.binding, data) ??
|
|
272
|
-
(el as IconElement).name ??
|
|
273
|
-
el.defaultValue ??
|
|
274
|
-
'';
|
|
275
|
-
const text = mapIconGlyph(`${resolved}`, `${resolved}`);
|
|
276
|
-
return {
|
|
277
|
-
id: el.id,
|
|
278
|
-
type: el.type,
|
|
279
|
-
wrapperStyle,
|
|
280
|
-
contentStyle: buildBaseContentStyle(el, unit),
|
|
281
|
-
name: `${resolved}`,
|
|
282
|
-
text,
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (el.type === 'custom') {
|
|
287
|
-
return {
|
|
288
|
-
id: el.id,
|
|
289
|
-
type: el.type,
|
|
290
|
-
wrapperStyle,
|
|
291
|
-
contentStyle: buildBaseContentStyle(el, unit),
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
return null;
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
const buildRenderNodes = (
|
|
299
|
-
children: CardElement[],
|
|
300
|
-
data: LayoutData,
|
|
301
|
-
unit: 'px' | 'rpx',
|
|
302
|
-
) => {
|
|
303
|
-
if (!Array.isArray(children)) return [];
|
|
304
|
-
const nodes: RenderElement[] = [];
|
|
305
|
-
children.forEach(el => {
|
|
306
|
-
if (!el || el.visible === false) return;
|
|
307
|
-
const node = buildRenderNode(el, data, unit);
|
|
308
|
-
if (node) nodes.push(node);
|
|
309
|
-
});
|
|
310
|
-
return nodes;
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
const buildCards = (
|
|
314
|
-
layouts: CardLayoutInput,
|
|
315
|
-
data: LayoutData,
|
|
316
|
-
unit: 'px' | 'rpx',
|
|
317
|
-
) =>
|
|
318
|
-
layouts.map(layout => ({
|
|
319
|
-
id: layout.name || (layout as any).id || '',
|
|
320
|
-
cardStyle: buildCardStyle(layout, unit),
|
|
321
|
-
backgroundImage: layout.backgroundImage || '',
|
|
322
|
-
backgroundStyle: buildBackgroundStyle(layout, unit),
|
|
323
|
-
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),
|
|
324
71
|
}));
|
|
72
|
+
};
|
|
325
73
|
|
|
326
74
|
Component({
|
|
327
75
|
options: {
|
|
@@ -367,12 +115,7 @@ Component({
|
|
|
367
115
|
}
|
|
368
116
|
|
|
369
117
|
const normalizedLayouts = normalizeLayout(layoutInput);
|
|
370
|
-
const cards = buildCards(normalizedLayouts, dataInput
|
|
371
|
-
(card, idx) => ({
|
|
372
|
-
...card,
|
|
373
|
-
id: pickCardId(layoutInput[idx], idx),
|
|
374
|
-
}),
|
|
375
|
-
);
|
|
118
|
+
const cards = buildCards(normalizedLayouts, dataInput);
|
|
376
119
|
|
|
377
120
|
this.setData({ cards });
|
|
378
121
|
},
|
|
@@ -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';
|