km-card-layout-component-miniprogram 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/example/pages/home/index.js +107 -16
  2. package/miniprogram_dist/components/card-layout/elements/custom-element/index.js +27 -0
  3. package/miniprogram_dist/components/card-layout/elements/custom-element/index.json +3 -0
  4. package/miniprogram_dist/components/card-layout/elements/custom-element/index.wxml +5 -0
  5. package/miniprogram_dist/components/card-layout/elements/custom-element/index.wxss +14 -0
  6. package/miniprogram_dist/components/card-layout/elements/icon-element/index.js +39 -0
  7. package/miniprogram_dist/components/card-layout/elements/icon-element/index.json +3 -0
  8. package/miniprogram_dist/components/card-layout/elements/icon-element/index.wxml +5 -0
  9. package/miniprogram_dist/components/card-layout/elements/icon-element/index.wxss +37 -0
  10. package/miniprogram_dist/components/card-layout/elements/image-element/index.js +31 -0
  11. package/miniprogram_dist/components/card-layout/elements/image-element/index.json +3 -0
  12. package/miniprogram_dist/components/card-layout/elements/image-element/index.wxml +8 -0
  13. package/miniprogram_dist/components/card-layout/elements/image-element/index.wxss +10 -0
  14. package/miniprogram_dist/components/card-layout/elements/text-element/index.js +47 -0
  15. package/miniprogram_dist/components/card-layout/elements/text-element/index.json +3 -0
  16. package/miniprogram_dist/components/card-layout/elements/text-element/index.wxml +29 -0
  17. package/miniprogram_dist/components/card-layout/elements/text-element/index.wxss +59 -0
  18. package/miniprogram_dist/components/card-layout/index.js +16 -201
  19. package/miniprogram_dist/components/card-layout/index.json +7 -1
  20. package/miniprogram_dist/components/card-layout/index.wxml +15 -63
  21. package/miniprogram_dist/components/card-layout/index.wxss +0 -63
  22. package/miniprogram_dist/utils/card-schema.js +12 -3
  23. package/miniprogram_dist/vendor/km-card-layout-core/bindings.js +78 -0
  24. package/miniprogram_dist/vendor/km-card-layout-core/data.js +38 -0
  25. package/miniprogram_dist/vendor/km-card-layout-core/helpers.js +72 -0
  26. package/miniprogram_dist/vendor/km-card-layout-core/index.js +46 -367
  27. package/miniprogram_dist/vendor/km-card-layout-core/interface/index.js +1 -1
  28. package/miniprogram_dist/vendor/km-card-layout-core/layout.js +117 -0
  29. package/miniprogram_dist/vendor/km-card-layout-core/ops/changeBackground.js +142 -0
  30. package/miniprogram_dist/vendor/km-card-layout-core/render/helpers.js +133 -0
  31. package/miniprogram_dist/vendor/km-card-layout-core/render/tool.js +16 -0
  32. package/miniprogram_dist/vendor/km-card-layout-core/utils.js +23 -130
  33. package/package.json +1 -1
  34. package/script/sync-core.js +13 -2
  35. package/src/components/card-layout/elements/custom-element/index.json +3 -0
  36. package/src/components/card-layout/elements/custom-element/index.ts +30 -0
  37. package/src/components/card-layout/elements/custom-element/index.wxml +5 -0
  38. package/src/components/card-layout/elements/custom-element/index.wxss +14 -0
  39. package/src/components/card-layout/elements/icon-element/index.json +3 -0
  40. package/src/components/card-layout/elements/icon-element/index.ts +42 -0
  41. package/src/components/card-layout/elements/icon-element/index.wxml +5 -0
  42. package/src/components/card-layout/elements/icon-element/index.wxss +37 -0
  43. package/src/components/card-layout/elements/image-element/index.json +3 -0
  44. package/src/components/card-layout/elements/image-element/index.ts +35 -0
  45. package/src/components/card-layout/elements/image-element/index.wxml +8 -0
  46. package/src/components/card-layout/elements/image-element/index.wxss +10 -0
  47. package/src/components/card-layout/elements/text-element/index.json +3 -0
  48. package/src/components/card-layout/elements/text-element/index.ts +52 -0
  49. package/src/components/card-layout/elements/text-element/index.wxml +29 -0
  50. package/src/components/card-layout/elements/text-element/index.wxss +59 -0
  51. package/src/components/card-layout/index.json +7 -1
  52. package/src/components/card-layout/index.ts +30 -296
  53. package/src/components/card-layout/index.wxml +15 -63
  54. package/src/components/card-layout/index.wxss +0 -63
  55. package/src/utils/card-schema.ts +11 -4
  56. package/src/vendor/km-card-layout-core/bindings.ts +87 -0
  57. package/src/vendor/km-card-layout-core/data.ts +39 -0
  58. package/src/vendor/km-card-layout-core/helpers.ts +76 -0
  59. package/src/vendor/km-card-layout-core/index.ts +53 -460
  60. package/src/vendor/km-card-layout-core/interface/context.ts +6 -0
  61. package/src/vendor/km-card-layout-core/interface/data/payload.ts +1 -0
  62. package/src/vendor/km-card-layout-core/interface/index.ts +2 -2
  63. package/src/vendor/km-card-layout-core/layout.ts +129 -0
  64. package/src/vendor/km-card-layout-core/ops/changeBackground.ts +179 -0
  65. package/src/vendor/km-card-layout-core/render/helpers.ts +144 -0
  66. package/src/vendor/km-card-layout-core/render/tool.ts +21 -0
  67. package/src/vendor/km-card-layout-core/types.d.ts +166 -15
  68. package/src/vendor/km-card-layout-core/utils.ts +13 -141
  69. package/src/vendor/km-card-layout-core/interface/render.ts +0 -52
  70. /package/miniprogram_dist/vendor/km-card-layout-core/interface/{render.js → context.js} +0 -0
@@ -0,0 +1,8 @@
1
+ <view class="km-node" style="{{wrapperStyle}}">
2
+ <image
3
+ class="km-node__image"
4
+ style="{{contentStyle}}"
5
+ src="{{imageSrc}}"
6
+ mode="{{mode}}"
7
+ />
8
+ </view>
@@ -0,0 +1,10 @@
1
+ .km-node {
2
+ box-sizing: border-box;
3
+ color: inherit;
4
+ }
5
+
6
+ .km-node__image {
7
+ width: 100%;
8
+ height: 100%;
9
+ display: block;
10
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "component": true
3
+ }
@@ -0,0 +1,52 @@
1
+ import {
2
+ buildTextContentStyle,
3
+ buildTextIconMeta,
4
+ buildWrapperStyle,
5
+ getTextValue,
6
+ styleObjectToString,
7
+ type TextElement,
8
+ } from '../../../../vendor/km-card-layout-core/index';
9
+ import { ICON_CODE_MAP } from '../../icon-map';
10
+
11
+ const mapIconGlyph = (name?: string, fallback?: string) => {
12
+ if (!name) return fallback;
13
+ const glyph = ICON_CODE_MAP[name];
14
+ if (glyph) return String.fromCharCode(parseInt(glyph, 16));
15
+ return fallback || name;
16
+ };
17
+
18
+ Component({
19
+ options: {
20
+ styleIsolation: 'apply-shared',
21
+ },
22
+ properties: {
23
+ element: {
24
+ type: Object,
25
+ value: {},
26
+ },
27
+ },
28
+ data: {
29
+ wrapperStyle: '',
30
+ contentStyle: '',
31
+ textValue: '',
32
+ iconMeta: null as any,
33
+ },
34
+ observers: {
35
+ element(el: TextElement) {
36
+ if (!el) return;
37
+ const wrapperStyle = styleObjectToString(buildWrapperStyle(el, 'rpx'), 'rpx');
38
+ const contentStyle = styleObjectToString(buildTextContentStyle(el, 'rpx'), 'rpx');
39
+ const textValue = getTextValue(el);
40
+ const iconRaw = buildTextIconMeta(el, 'rpx');
41
+ const iconMeta =
42
+ iconRaw && iconRaw.name
43
+ ? {
44
+ ...iconRaw,
45
+ text: mapIconGlyph(iconRaw.name, iconRaw.name),
46
+ wrapperStyle: styleObjectToString(iconRaw.wrapperStyle, 'rpx'),
47
+ }
48
+ : iconRaw;
49
+ this.setData({ wrapperStyle, contentStyle, textValue, iconMeta });
50
+ },
51
+ },
52
+ });
@@ -0,0 +1,29 @@
1
+ <view class="km-node km-node--text" style="{{wrapperStyle}}">
2
+ <view class="km-node__text" style="{{contentStyle}}">
3
+ <block wx:if="{{iconMeta && iconMeta.name}}">
4
+ <view class="km-node__text-content">
5
+ <block wx:if="{{iconMeta.align === 'right'}}">
6
+ <text class="km-node__text-value">{{textValue || ''}}</text>
7
+ <view style="{{iconMeta.wrapperStyle}}" class="km-node__text-icon--wrapper" >
8
+ <text
9
+ class="km-node__text-icon icon"
10
+ style="font-size: {{iconMeta.size || '16px'}}; color: {{iconMeta.color || ''}}; margin-right: {{iconMeta.gap || ''}};"
11
+ >{{iconMeta.text || iconMeta.name || ''}}</text>
12
+ </view>
13
+ </block>
14
+ <block wx:else>
15
+ <view style="{{iconMeta.wrapperStyle}}" class="km-node__text-icon--wrapper">
16
+ <text
17
+ class="km-node__text-icon icon"
18
+ style="font-size: {{iconMeta.size || '16px'}}; color: {{iconMeta.color || ''}}; margin-right: {{iconMeta.gap || ''}};"
19
+ >{{iconMeta.text || iconMeta.name || ''}}</text>
20
+ </view>
21
+ <text class="km-node__text-value">{{textValue || ''}}</text>
22
+ </block>
23
+ </view>
24
+ </block>
25
+ <block wx:else>
26
+ <text class="km-node__text-value">{{textValue || ''}}</text>
27
+ </block>
28
+ </view>
29
+ </view>
@@ -0,0 +1,59 @@
1
+ .km-node {
2
+ box-sizing: border-box;
3
+ color: inherit;
4
+ }
5
+
6
+ .km-node--text {
7
+ /* overflow hidden if needed */
8
+ }
9
+
10
+ .km-node--text text {
11
+ display: inline;
12
+ }
13
+
14
+ .km-node__text {
15
+ width: 100%;
16
+ height: 100%;
17
+ display: block;
18
+ box-sizing: border-box;
19
+ text-align: inherit;
20
+ }
21
+
22
+ .km-node__text-content {
23
+ display: inline-block;
24
+ vertical-align: middle;
25
+ height: 100%;
26
+ }
27
+
28
+ .km-node__text-icon {
29
+ display: inline-flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ }
33
+
34
+ .km-node__text-value {
35
+ display: inline-block;
36
+ white-space: pre-wrap;
37
+ word-break: break-word;
38
+ vertical-align: middle;
39
+ }
40
+
41
+ @font-face {
42
+ font-family: 'km-icon';
43
+ src: url('data:font/woff;charset=utf-8;base64,d09GRgABAAAAAEl4AA0AAAAAcmgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAABJXAAAABoAAAAcrMtJV0dERUYAAEk8AAAAHgAAAB4AKQByT1MvMgAAAaQAAABGAAAAYDw3SVljbWFwAAAC7AAAAM8AAAIW8XL3K2dhc3AAAEk0AAAACAAAAAj//wADZ2x5ZgAABJgAAEBZAABkZPJymXJoZWFkAAABMAAAADEAAAA2MtZiFmhoZWEAAAFkAAAAIAAAACQNagmCaG10eAAAAewAAAD/AAABqqs3Ii9sb2NhAAADvAAAANoAAADaKv0P7G1heHAAAAGEAAAAHwAAACABmQHEbmFtZQAARPQAAAFGAAACgl6CAQJwb3N0AABGPAAAAvUAAATh1g15W3jaY2BkYGAA4lqffPd4fpuvDNwsDCDwVIyfA0b///i/gXMWcyeQy8HABBIFAAVdCfwAAAB42mNgZGBgbvjfwBDDOfP/x///OWcxAEVQQCYAuxgH/XjaY2BkYGDIYdzBoMwAAkxAzAWEDAz/wXwGACjlAl8AeNpjYGFRYJzAwMrAwNTJdIaBgaEfQjO+ZjBi5ACKMrAyM2AFAWmuKQwHnjE+y2Ju+N/AwMB8h6ERKMyIpESBgREAenQNCwAAeNo90cErBGEYx/Hf1LMH7MVxoigHtS600pzWnMjBlt2dFAeiNuWgXLgokgslbpyE/Aduyl38J3ty4aCs7/vOk6lPv+d5531n3nfGVF5JIZlUx9fAbawnEfIFq14/YhddFPjFmynZ9n4TbYzg2tcMW6Epr4NQT3jSJ2lcW9ec1fSEAheMnVume7KKBbQwiMye+5/kEpqYwQoOY59pn1xGw3Lt8NwHS7UY35frivqbet2fNYZp+4j76vj+GpUhjZJreLfxODecay/eTzVPzmIj9uX7VLnUmfdb/2fN4trcv0kYv8Oxe/V5Rzhg7inZ8wzjN5b0f6z8PV2d/AHivi0JAHja3dBFUoVRDITR88PD3d3d3d3d3d33zQqYwwVGbIGk8qV6kK7qIN7vlIsCRdlBRT865iPsWOig318/PwOjbwYd+7mKSZAoSbIUqdKky5ApS7YcufLkK1CoSLESpcqCZ4VKVarVqFWnXoNGTZq1aNWmXYdOXbr16NWn34BBQ4aNGDVm3IRJU6bNmDVn3oJFS5atWLVm3YZNW7bt2LVn34FDR46dOHXm3IVLV67duHXn3oNHT8Hv2YtXbyFaot9HfMeMC4jztyL/vr4AXx4eawAAAAAAAAAAAACwAPIDSgQ8BLIFUgWUBcIF/gY8BpIHCgdAB3wHoAgOCHAIxgk+CV4JzAnqCkQKrgtUC8QMEAxsDNQNFA1SDegONg6qDyQPgg/CEAIQxBEwEaQSHBLYE14T4hRcFPIVTBYMFkwWqBckGGAYxhmYGegaEBpeGuIbXhvwHPQd5B62Hygf6CBeILog9CFUIbgiBCJ0ItQjbCQSJGgkuCVsJcImKib0J44ocijOKSApUCo2KmQqtituK34sJixkLMgtdC3WLpgvPC+QMBww/DGCMagyMgAA') format('woff');
44
+ font-weight: normal;
45
+ font-style: normal;
46
+ font-display: swap;
47
+ }
48
+
49
+ .icon {
50
+ font-family: 'km-icon' !important;
51
+ font-size: 16px;
52
+ font-style: normal;
53
+ -webkit-font-smoothing: antialiased;
54
+ -moz-osx-font-smoothing: grayscale;
55
+ }
56
+
57
+ .km-node__text-icon--wrapper{
58
+ display: inline-block;
59
+ }
@@ -1,3 +1,9 @@
1
1
  {
2
- "component": true
2
+ "component": true,
3
+ "usingComponents": {
4
+ "text-element": "./elements/text-element/index",
5
+ "image-element": "./elements/image-element/index",
6
+ "icon-element": "./elements/icon-element/index",
7
+ "custom-element": "./elements/custom-element/index"
8
+ }
3
9
  }
@@ -2,53 +2,32 @@ import type {
2
2
  CardElement,
3
3
  CardLayoutInput,
4
4
  CardLayoutSchema,
5
- IconElement,
6
- ImageElement,
7
5
  LayoutPanelElement,
8
- TextElement,
9
6
  } from '../../vendor/km-card-layout-core/index';
10
7
  import {
11
- addUnit,
8
+ buildBackgroundStyle,
9
+ buildCardStyle,
10
+ buildPanelContentStyle,
11
+ buildWrapperStyle,
12
12
  normalizeLayout,
13
- resolveBindingValue,
14
13
  styleObjectToString,
15
14
  } from '../../vendor/km-card-layout-core/index';
16
- import { ICON_CODE_MAP } from './icon-map';
17
15
 
18
- type LayoutData = {
19
- [key: string]: any;
20
- };
21
-
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'];
16
+ type PanelElement = LayoutPanelElement & {
35
17
  wrapperStyle: string;
36
18
  contentStyle: string;
37
- name?: string;
38
- text?: string;
39
- src?: string;
40
- mode?: string;
41
- icon?: RenderIcon;
42
19
  children?: RenderElement[];
43
- }
20
+ };
44
21
 
45
- interface RenderCard {
22
+ type RenderElement = CardElement | PanelElement;
23
+
24
+ type RenderCard = {
46
25
  id: string;
47
26
  cardStyle: string;
48
27
  backgroundImage?: string;
49
28
  backgroundStyle: string;
50
- nodes: RenderElement[];
51
- }
29
+ elements: RenderElement[];
30
+ };
52
31
 
53
32
  const ensureArray = (input: CardLayoutInput | any): CardLayoutInput => {
54
33
  if (!input) return [];
@@ -60,268 +39,29 @@ const pickCardId = (layout: any, idx: number) => {
60
39
  return `card-${idx}`;
61
40
  };
62
41
 
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
- const mapIconGlyph = (name?: string, fallback?: string) => {
164
- if (!name) return fallback;
165
- const glyph = ICON_CODE_MAP[name];
166
- if (glyph) return String.fromCharCode(parseInt(glyph, 16));
167
- return fallback || name;
168
- };
169
-
170
- const buildTextIcon = (
171
- el: TextElement,
172
- unit: 'px' | 'rpx',
173
- ): RenderIcon | undefined => {
174
- const icon = el.icon;
175
- if (!icon || icon.enable === false) return undefined;
176
-
177
- const style = icon.style || 'fill';
178
- const baseName = el.key || el.binding || el.id;
179
- let name: string | undefined;
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;
192
-
193
- const text = mapIconGlyph(name, name);
194
- return {
195
- name,
196
- text,
197
- size: size !== undefined ? withUnit(size, unit) : undefined,
198
- gap: gap !== undefined ? withUnit(gap, unit) : undefined,
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',
209
- };
210
- };
211
-
212
- const buildRenderNode = (
213
- el: CardElement,
214
- data: LayoutData,
215
- unit: 'px' | 'rpx',
216
- ): RenderElement | null => {
217
- if (!el || el.visible === false) return null;
218
- const wrapperStyle = buildWrapperStyle(el, unit);
219
-
220
- if (el.type === 'layout-panel') {
221
- const panel = el as LayoutPanelElement;
222
- return {
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';
42
+ const decorateElements = (children: CardElement[] = []): RenderElement[] =>
43
+ (children || []).map(el => {
44
+ if (el.type === 'layout-panel') {
45
+ const panel = el as LayoutPanelElement;
46
+ return {
47
+ ...panel,
48
+ wrapperStyle: styleObjectToString(buildWrapperStyle(panel, 'rpx'), 'rpx'),
49
+ contentStyle: styleObjectToString(buildPanelContentStyle(panel, 'rpx'), 'rpx'),
50
+ children: decorateElements(panel.children || []),
51
+ };
250
52
  }
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);
53
+ return el;
309
54
  });
310
- return nodes;
311
- };
312
55
 
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),
56
+ const buildCards = (layouts: CardLayoutSchema[]) => {
57
+ return layouts.map((layout, idx) => ({
58
+ id: pickCardId(layouts[idx], idx),
59
+ cardStyle: styleObjectToString(buildCardStyle(layout, 'rpx'), 'rpx'),
321
60
  backgroundImage: layout.backgroundImage || '',
322
- backgroundStyle: buildBackgroundStyle(layout, unit),
323
- nodes: buildRenderNodes(layout.children || [], data, unit),
61
+ backgroundStyle: styleObjectToString(buildBackgroundStyle(layout, 'rpx'), 'rpx'),
62
+ elements: decorateElements(layout.children || []),
324
63
  }));
64
+ };
325
65
 
326
66
  Component({
327
67
  options: {
@@ -359,7 +99,6 @@ Component({
359
99
  methods: {
360
100
  rebuild() {
361
101
  const layoutInput = ensureArray(this.data.layout as CardLayoutInput);
362
- const dataInput = (this.data.data || {}) as LayoutData;
363
102
 
364
103
  if (!layoutInput.length) {
365
104
  this.setData({ cards: [] });
@@ -367,12 +106,7 @@ Component({
367
106
  }
368
107
 
369
108
  const normalizedLayouts = normalizeLayout(layoutInput);
370
- const cards = buildCards(normalizedLayouts, dataInput, 'rpx').map(
371
- (card, idx) => ({
372
- ...card,
373
- id: pickCardId(layoutInput[idx], idx),
374
- }),
375
- );
109
+ const cards = buildCards(normalizedLayouts);
376
110
 
377
111
  this.setData({ cards });
378
112
  },
@@ -9,82 +9,34 @@
9
9
  src="{{item.backgroundImage}}"
10
10
  mode="aspectFill"
11
11
  />
12
- <block wx:for="{{item.nodes}}" wx:key="id">
13
- <template is="render-node" data="{{node:item}}" />
12
+ <block wx:for="{{item.elements}}" wx:key="id">
13
+ <template is="render-element" data="{{el:item}}" />
14
14
  </block>
15
15
  </view>
16
16
  </view>
17
17
  </block>
18
18
  </view>
19
19
 
20
- <template name="render-node">
21
- <block wx:if="{{node.type === 'image'}}">
22
- <view class="km-node" style="{{node.wrapperStyle}}">
23
- <image
24
- class="km-node__image"
25
- style="{{node.contentStyle}}"
26
- src="{{node.src}}"
27
- mode="{{node.mode || 'aspectFill'}}"
28
- />
29
- </view>
20
+ <template name="render-element">
21
+ <block wx:if="{{el.type === 'image'}}">
22
+ <image-element element="{{el}}" />
30
23
  </block>
31
- <block wx:elif="{{node.type === 'icon'}}">
32
- <view class="km-node km-node--icon" style="{{node.wrapperStyle}}">
33
- <view
34
- wx:if="{{node.name === 'dot' || node.name === 'round'}}"
35
- class="km-node__icon-dot"
36
- style="{{node.contentStyle}}"
37
- />
38
- <view
39
- wx:else
40
- class="km-node__icon icon"
41
- style="{{node.contentStyle}}"
42
- >{{node.text || ''}}</view>
43
- </view>
24
+ <block wx:elif="{{el.type === 'icon'}}">
25
+ <icon-element element="{{el}}" />
44
26
  </block>
45
- <block wx:elif="{{node.type === 'layout-panel'}}">
46
- <view class="km-node" style="{{node.wrapperStyle}}">
47
- <view class="km-node__panel" style="{{node.contentStyle}}">
48
- <block wx:for="{{node.children}}" wx:key="id">
49
- <template is="render-node" data="{{node:item}}" />
27
+ <block wx:elif="{{el.type === 'layout-panel'}}">
28
+ <view class="km-node" style="{{el.wrapperStyle}}">
29
+ <view class="km-node__panel" style="{{el.contentStyle}}">
30
+ <block wx:for="{{el.children}}" wx:key="id">
31
+ <template is="render-element" data="{{el:item}}" />
50
32
  </block>
51
33
  </view>
52
34
  </view>
53
35
  </block>
54
- <block wx:elif="{{node.type === 'custom'}}">
55
- <view class="km-node km-node--custom" style="{{node.wrapperStyle}}">
56
- <view class="km-node__custom" style="{{node.contentStyle}}">
57
- <slot name="{{node.id}}"></slot>
58
- </view>
59
- </view>
36
+ <block wx:elif="{{el.type === 'custom'}}">
37
+ <custom-element element="{{el}}" />
60
38
  </block>
61
39
  <block wx:else>
62
- <view class="km-node km-node--text" style="{{node.wrapperStyle}}">
63
- <view class="km-node__text" style="{{node.contentStyle}}">
64
- <block wx:if="{{node.icon && node.icon.name}}">
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>
82
- </view>
83
- </block>
84
- <block wx:else>
85
- <text class="km-node__text-value">{{node.text || ''}}</text>
86
- </block>
87
- </view>
88
- </view>
40
+ <text-element element="{{el}}" />
89
41
  </block>
90
42
  </template>