km-card-layout-core 0.1.24 → 0.1.26

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/README.md CHANGED
@@ -1,18 +1,16 @@
1
1
  # km-card-layout-core
2
2
 
3
- 纯函数渲染核心:负责将布局 JSON 与数据合成渲染树,处理绑定路径、样式单位(px/rpx)等。
3
+ Utilities for working with card layout schemas: sanitize layouts, handle bindings, convert style units, and apply background/decoration helpers. Rendering now uses `CardElement` directly without intermediate RenderNode conversion.
4
4
 
5
5
  ## API
6
6
 
7
- - `normalizeLayout(layout)`:清洗/容错布局对象或 JSON 字符串,补齐默认尺寸/children。
8
- - `buildRenderResult(layout, data, unit?)`:返回 `{ renderTree, cardStyle, backgroundImage, backgroundStyle }`,可直接用于 PC/Vue、小程序等多端。
9
- - `buildRenderNodes(children, data, unit?, context?)`:仅展开 children 为渲染节点列表。
10
- - 其他工具:`resolveBindingValue`(绑定读取,支持 `$item.` dataPath 上下文)、`styleObjectToString`、`addUnit`。
7
+ - `normalizeLayout(layout)`: sanitize layout objects and fill defaults.
8
+ - `resolveBindingValue(path, data, context?)`: read bound data with optional context.
9
+ - `styleObjectToString(style, unit?)`: convert a style object to a CSS string.
10
+ - `addUnit(value, unit)`: append px/rpx to numbers or numeric strings.
11
+ - Background helpers: `applyBackground`, `applySpecialStyle`, `backgroundChange`, `buildRenderData`, etc.
11
12
 
12
- ## 适用场景
13
+ ## Usage
13
14
 
14
- - PC 端:在 Vue 组件里调用 `buildRenderResult`,把 renderTree 映射为 VDOM。
15
- - 小程序:被 `km-card-layout-component-miniprogram` 依赖,组件中通过 core 得到 renderTree。
16
- - 预渲染/快照:Node 环境按相同逻辑生成渲染树后做静态输出或图片化。
15
+ Use the layout schema and card elements directly for rendering on web or mini-program targets—no extra RenderNode transformation layer is required. The core is platform-agnostic and can be imported via `require('km-card-layout-core')`.
17
16
 
18
- 核心不依赖 DOM/平台 API,可直接通过 `require('km-card-layout-core')` 使用。
package/data.ts CHANGED
@@ -29,8 +29,7 @@ const readByPath = (data: any, path: string): any => {
29
29
 
30
30
  export const resolveBindingValue = (
31
31
  binding: string | undefined,
32
- rootData: Record<string, any>,
33
- context?: Record<string, any>
32
+ rootData: Record<string, any>
34
33
  ): any => {
35
34
  if (!binding) return undefined;
36
35
  const value = readByPath(rootData, binding);
package/dist/data.js CHANGED
@@ -29,7 +29,7 @@ const readByPath = (data, path) => {
29
29
  }
30
30
  return cursor;
31
31
  };
32
- const resolveBindingValue = (binding, rootData, context) => {
32
+ const resolveBindingValue = (binding, rootData) => {
33
33
  if (!binding)
34
34
  return undefined;
35
35
  const value = readByPath(rootData, binding);
package/dist/index.js CHANGED
@@ -20,12 +20,30 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
20
20
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
21
21
  };
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.updateElementsStyle = exports.applyBackground = exports.applySpecialStyle = exports.resolveSpecialStyle = exports.DEFAULT_DECOR_COLOR = exports.backgroundChange = void 0;
23
+ exports.buildTextIconMeta = exports.getIconName = exports.getImageSrc = exports.getTextValue = exports.buildImageContentStyle = exports.buildTextContentStyle = exports.buildPanelContentStyle = exports.buildBaseContentStyle = exports.buildBackgroundStyle = exports.buildCardStyle = exports.buildWrapperStyle = exports.buildRenderData = exports.updateElementsStyle = exports.applyBackground = exports.applySpecialStyle = exports.resolveSpecialStyle = exports.DEFAULT_DECOR_COLOR = exports.backgroundChange = exports.getTemplateBackgrounds = exports.getTemplateItems = exports.applyItemCollectBindings = exports.stripLayoutBindings = exports.resolveBindingValue = exports.areChildrenEqual = exports.parseLayout = exports.normalizeId = exports.collectBindings = exports.getAbsLayout = exports.roundToInt = exports.sanitizeElement = exports.sanitizeLayout = exports.normalizeLayout = exports.isObject = exports.toNumber = exports.styleObjectToString = exports.addUnit = void 0;
24
24
  __exportStar(require("./interface/index"), exports);
25
- __exportStar(require("./helpers"), exports);
26
- __exportStar(require("./layout"), exports);
27
- __exportStar(require("./data"), exports);
28
- __exportStar(require("./bindings"), exports);
25
+ var helpers_1 = require("./helpers");
26
+ Object.defineProperty(exports, "addUnit", { enumerable: true, get: function () { return helpers_1.addUnit; } });
27
+ Object.defineProperty(exports, "styleObjectToString", { enumerable: true, get: function () { return helpers_1.styleObjectToString; } });
28
+ Object.defineProperty(exports, "toNumber", { enumerable: true, get: function () { return helpers_1.toNumber; } });
29
+ Object.defineProperty(exports, "isObject", { enumerable: true, get: function () { return helpers_1.isObject; } });
30
+ var layout_1 = require("./layout");
31
+ Object.defineProperty(exports, "normalizeLayout", { enumerable: true, get: function () { return layout_1.normalizeLayout; } });
32
+ Object.defineProperty(exports, "sanitizeLayout", { enumerable: true, get: function () { return layout_1.sanitizeLayout; } });
33
+ Object.defineProperty(exports, "sanitizeElement", { enumerable: true, get: function () { return layout_1.sanitizeElement; } });
34
+ Object.defineProperty(exports, "roundToInt", { enumerable: true, get: function () { return layout_1.roundToInt; } });
35
+ Object.defineProperty(exports, "getAbsLayout", { enumerable: true, get: function () { return layout_1.getAbsLayout; } });
36
+ Object.defineProperty(exports, "collectBindings", { enumerable: true, get: function () { return layout_1.collectBindings; } });
37
+ Object.defineProperty(exports, "normalizeId", { enumerable: true, get: function () { return layout_1.normalizeId; } });
38
+ Object.defineProperty(exports, "parseLayout", { enumerable: true, get: function () { return layout_1.parseLayout; } });
39
+ Object.defineProperty(exports, "areChildrenEqual", { enumerable: true, get: function () { return layout_1.areChildrenEqual; } });
40
+ var data_1 = require("./data");
41
+ Object.defineProperty(exports, "resolveBindingValue", { enumerable: true, get: function () { return data_1.resolveBindingValue; } });
42
+ var bindings_1 = require("./bindings");
43
+ Object.defineProperty(exports, "stripLayoutBindings", { enumerable: true, get: function () { return bindings_1.stripLayoutBindings; } });
44
+ Object.defineProperty(exports, "applyItemCollectBindings", { enumerable: true, get: function () { return bindings_1.applyItemCollectBindings; } });
45
+ Object.defineProperty(exports, "getTemplateItems", { enumerable: true, get: function () { return bindings_1.getTemplateItems; } });
46
+ Object.defineProperty(exports, "getTemplateBackgrounds", { enumerable: true, get: function () { return bindings_1.getTemplateBackgrounds; } });
29
47
  var changeBackground_1 = require("./ops/changeBackground");
30
48
  Object.defineProperty(exports, "backgroundChange", { enumerable: true, get: function () { return changeBackground_1.backgroundChange; } });
31
49
  Object.defineProperty(exports, "DEFAULT_DECOR_COLOR", { enumerable: true, get: function () { return changeBackground_1.DEFAULT_DECOR_COLOR; } });
@@ -33,5 +51,17 @@ Object.defineProperty(exports, "resolveSpecialStyle", { enumerable: true, get: f
33
51
  Object.defineProperty(exports, "applySpecialStyle", { enumerable: true, get: function () { return changeBackground_1.applySpecialStyle; } });
34
52
  Object.defineProperty(exports, "applyBackground", { enumerable: true, get: function () { return changeBackground_1.applyBackground; } });
35
53
  Object.defineProperty(exports, "updateElementsStyle", { enumerable: true, get: function () { return changeBackground_1.updateElementsStyle; } });
36
- __exportStar(require("./render/builder"), exports);
37
- __exportStar(require("./render/tool"), exports);
54
+ var tool_1 = require("./render/tool");
55
+ Object.defineProperty(exports, "buildRenderData", { enumerable: true, get: function () { return tool_1.buildRenderData; } });
56
+ var helpers_2 = require("./render/helpers");
57
+ Object.defineProperty(exports, "buildWrapperStyle", { enumerable: true, get: function () { return helpers_2.buildWrapperStyle; } });
58
+ Object.defineProperty(exports, "buildCardStyle", { enumerable: true, get: function () { return helpers_2.buildCardStyle; } });
59
+ Object.defineProperty(exports, "buildBackgroundStyle", { enumerable: true, get: function () { return helpers_2.buildBackgroundStyle; } });
60
+ Object.defineProperty(exports, "buildBaseContentStyle", { enumerable: true, get: function () { return helpers_2.buildBaseContentStyle; } });
61
+ Object.defineProperty(exports, "buildPanelContentStyle", { enumerable: true, get: function () { return helpers_2.buildPanelContentStyle; } });
62
+ Object.defineProperty(exports, "buildTextContentStyle", { enumerable: true, get: function () { return helpers_2.buildTextContentStyle; } });
63
+ Object.defineProperty(exports, "buildImageContentStyle", { enumerable: true, get: function () { return helpers_2.buildImageContentStyle; } });
64
+ Object.defineProperty(exports, "getTextValue", { enumerable: true, get: function () { return helpers_2.getTextValue; } });
65
+ Object.defineProperty(exports, "getImageSrc", { enumerable: true, get: function () { return helpers_2.getImageSrc; } });
66
+ Object.defineProperty(exports, "getIconName", { enumerable: true, get: function () { return helpers_2.getIconName; } });
67
+ Object.defineProperty(exports, "buildTextIconMeta", { enumerable: true, get: function () { return helpers_2.buildTextIconMeta; } });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -16,5 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./elements"), exports);
18
18
  __exportStar(require("./layout"), exports);
19
- __exportStar(require("./render"), exports);
20
19
  __exportStar(require("./data/payload"), exports);
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildTextIconMeta = exports.getIconName = exports.getImageSrc = exports.getTextValue = exports.buildImageContentStyle = exports.buildTextContentStyle = exports.buildPanelContentStyle = exports.buildBaseContentStyle = exports.buildBackgroundStyle = exports.buildCardStyle = exports.buildWrapperStyle = void 0;
4
+ const helpers_1 = require("../helpers");
5
+ const layout_1 = require("../layout");
6
+ const data_1 = require("../data");
7
+ const buildWrapperStyle = (el, unit = 'px') => {
8
+ const abs = (0, layout_1.getAbsLayout)(el);
9
+ if (!abs)
10
+ return {};
11
+ return {
12
+ position: 'absolute',
13
+ left: (0, helpers_1.addUnit)(abs.x, unit),
14
+ top: (0, helpers_1.addUnit)(abs.y, unit),
15
+ width: (0, helpers_1.addUnit)(abs.width, unit),
16
+ height: (0, helpers_1.addUnit)(abs.height, unit),
17
+ zIndex: abs.zIndex,
18
+ boxSizing: 'border-box',
19
+ };
20
+ };
21
+ exports.buildWrapperStyle = buildWrapperStyle;
22
+ const buildCardStyle = (layout, unit = 'px') => ({
23
+ width: (0, helpers_1.addUnit)(layout.width, unit),
24
+ height: (0, helpers_1.addUnit)(layout.height, unit),
25
+ color: layout.fontColor,
26
+ borderRadius: layout.borderRadius !== undefined
27
+ ? (0, helpers_1.addUnit)(layout.borderRadius, unit)
28
+ : undefined,
29
+ padding: layout.padding !== undefined ? (0, helpers_1.addUnit)(layout.padding, unit) : undefined,
30
+ position: 'relative',
31
+ overflow: 'hidden',
32
+ boxSizing: 'border-box',
33
+ backgroundColor: 'transparent',
34
+ });
35
+ exports.buildCardStyle = buildCardStyle;
36
+ const buildBackgroundStyle = (layout, unit = 'px') => ({
37
+ zIndex: layout.backgroundZIndex,
38
+ borderRadius: layout.borderRadius !== undefined
39
+ ? (0, helpers_1.addUnit)(layout.borderRadius, unit)
40
+ : undefined,
41
+ width: '100%',
42
+ height: '100%',
43
+ position: 'absolute',
44
+ left: 0,
45
+ top: 0,
46
+ });
47
+ exports.buildBackgroundStyle = buildBackgroundStyle;
48
+ const buildBaseContentStyle = (el) => ({
49
+ ...(el.style || {}),
50
+ boxSizing: 'border-box',
51
+ });
52
+ exports.buildBaseContentStyle = buildBaseContentStyle;
53
+ const buildPanelContentStyle = (el, unit = 'px') => ({
54
+ position: 'relative',
55
+ width: '100%',
56
+ height: '100%',
57
+ display: 'block',
58
+ boxSizing: 'border-box',
59
+ ...(el.style || {}),
60
+ });
61
+ exports.buildPanelContentStyle = buildPanelContentStyle;
62
+ const buildTextContentStyle = (el, unit = 'px') => {
63
+ var _a, _b, _c, _d;
64
+ const textAlign = ((_a = el.style) === null || _a === void 0 ? void 0 : _a.textAlign) || el.align || undefined;
65
+ const style = {
66
+ ...(el.style || {}),
67
+ fontSize: (0, helpers_1.addUnit)((_b = el.style) === null || _b === void 0 ? void 0 : _b.fontSize, unit),
68
+ whiteSpace: 'pre-wrap',
69
+ wordBreak: 'break-word',
70
+ lineHeight: ((_c = el.style) === null || _c === void 0 ? void 0 : _c.lineHeight) !== undefined && ((_d = el.style) === null || _d === void 0 ? void 0 : _d.lineHeight) !== null
71
+ ? (0, helpers_1.addUnit)(el.style.lineHeight, unit)
72
+ : '1',
73
+ };
74
+ if (textAlign)
75
+ style.textAlign = textAlign;
76
+ return style;
77
+ };
78
+ exports.buildTextContentStyle = buildTextContentStyle;
79
+ const buildImageContentStyle = (el) => {
80
+ const style = { ...(el.style || {}) };
81
+ const borderWidth = Number(style.borderWidth);
82
+ if (Number.isFinite(borderWidth) && borderWidth > 0) {
83
+ if (!style.borderStyle)
84
+ style.borderStyle = 'solid';
85
+ if (!style.borderColor)
86
+ style.borderColor = '#000000';
87
+ }
88
+ return style;
89
+ };
90
+ exports.buildImageContentStyle = buildImageContentStyle;
91
+ const getTextValue = (el, data) => {
92
+ const bound = el.binding && data ? (0, data_1.resolveBindingValue)(el.binding, data) : undefined;
93
+ const val = bound !== undefined && bound !== null
94
+ ? bound
95
+ : el.defaultValue !== undefined && el.defaultValue !== null
96
+ ? el.defaultValue
97
+ : '';
98
+ return `${val !== null && val !== void 0 ? val : ''}`;
99
+ };
100
+ exports.getTextValue = getTextValue;
101
+ const getImageSrc = (el, data) => {
102
+ const bound = el.binding && data ? (0, data_1.resolveBindingValue)(el.binding, data) : undefined;
103
+ return bound || el.defaultUrl || el.defaultValue || '';
104
+ };
105
+ exports.getImageSrc = getImageSrc;
106
+ const getIconName = (el) => (el.name || el.defaultValue || '');
107
+ exports.getIconName = getIconName;
108
+ const buildTextIconMeta = (el, unit = 'px') => {
109
+ var _a, _b, _c, _d, _e, _f;
110
+ const icon = el.icon;
111
+ const enabled = (icon === null || icon === void 0 ? void 0 : icon.enable) === true;
112
+ if (!icon || !enabled)
113
+ return null;
114
+ const style = icon.style || 'fill';
115
+ const baseName = icon.name || el.key || el.binding || el.id;
116
+ let name;
117
+ if (style === 'dot')
118
+ name = 'round';
119
+ else if (style === 'line')
120
+ name = baseName ? `${baseName}-line` : undefined;
121
+ else
122
+ name = baseName || undefined;
123
+ if (!name)
124
+ return null;
125
+ const size = icon.size !== undefined && icon.size !== null
126
+ ? icon.size
127
+ : (_a = el.style) === null || _a === void 0 ? void 0 : _a.fontSize;
128
+ const gap = icon.gap !== undefined && icon.gap !== null ? icon.gap : 4;
129
+ const color = (_b = icon.color) !== null && _b !== void 0 ? _b : (typeof ((_c = el.style) === null || _c === void 0 ? void 0 : _c.color) === 'string' ? el.style.color : undefined);
130
+ return {
131
+ name: `${name}`,
132
+ size: (0, helpers_1.addUnit)(size, unit),
133
+ gap: (0, helpers_1.addUnit)(gap, unit),
134
+ color,
135
+ align: icon.align || 'left',
136
+ wrapperStyle: {
137
+ height: ((_d = el.style) === null || _d === void 0 ? void 0 : _d.lineHeight) !== undefined && ((_e = el.style) === null || _e === void 0 ? void 0 : _e.lineHeight) !== null
138
+ ? (0, helpers_1.addUnit)(el.style.lineHeight, unit)
139
+ : (_f = el.style) === null || _f === void 0 ? void 0 : _f.fontSize,
140
+ },
141
+ };
142
+ };
143
+ exports.buildTextIconMeta = buildTextIconMeta;
package/index.ts CHANGED
@@ -10,10 +10,25 @@
10
10
 
11
11
 
12
12
  export * from './interface/index';
13
- export * from './helpers';
14
- export * from './layout';
15
- export * from './data';
16
- export * from './bindings';
13
+ export { addUnit, styleObjectToString, toNumber, isObject } from './helpers';
14
+ export {
15
+ normalizeLayout,
16
+ sanitizeLayout,
17
+ sanitizeElement,
18
+ roundToInt,
19
+ getAbsLayout,
20
+ collectBindings,
21
+ normalizeId,
22
+ parseLayout,
23
+ areChildrenEqual,
24
+ } from './layout';
25
+ export { resolveBindingValue } from './data';
26
+ export {
27
+ stripLayoutBindings,
28
+ applyItemCollectBindings,
29
+ getTemplateItems,
30
+ getTemplateBackgrounds,
31
+ } from './bindings';
17
32
  export {
18
33
  backgroundChange,
19
34
  DEFAULT_DECOR_COLOR,
@@ -22,7 +37,17 @@ export {
22
37
  applyBackground,
23
38
  updateElementsStyle,
24
39
  } from './ops/changeBackground';
25
- export * from './render/builder';
26
- export * from './render/tool';
27
-
28
-
40
+ export { buildRenderData } from './render/tool';
41
+ export {
42
+ buildWrapperStyle,
43
+ buildCardStyle,
44
+ buildBackgroundStyle,
45
+ buildBaseContentStyle,
46
+ buildPanelContentStyle,
47
+ buildTextContentStyle,
48
+ buildImageContentStyle,
49
+ getTextValue,
50
+ getImageSrc,
51
+ getIconName,
52
+ buildTextIconMeta,
53
+ } from './render/helpers';
@@ -1,4 +1,3 @@
1
1
  export * from './elements';
2
2
  export * from './layout';
3
- export * from './render';
4
- export * from './data/payload';
3
+ export * from './data/payload';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "km-card-layout-core",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "description": "Shared render helpers for CardMaster layout JSON (binding resolution, layout normalization).",
5
5
  "main": "dist/index.js",
6
6
  "types": "types.d.ts",
@@ -0,0 +1,159 @@
1
+ import { addUnit } from '../helpers';
2
+ import { getAbsLayout } from '../layout';
3
+ import { resolveBindingValue } from '../data';
4
+ import type {
5
+ CardElement,
6
+ CardLayoutSchema,
7
+ IconElement,
8
+ ImageElement,
9
+ LayoutPanelElement,
10
+ TextElement,
11
+ } from '../interface';
12
+
13
+ export const buildWrapperStyle = (el: CardElement, unit: 'px' | 'rpx' = 'px') => {
14
+ const abs = getAbsLayout(el);
15
+ if (!abs) return {};
16
+ return {
17
+ position: 'absolute',
18
+ left: addUnit(abs.x, unit),
19
+ top: addUnit(abs.y, unit),
20
+ width: addUnit(abs.width, unit),
21
+ height: addUnit(abs.height, unit),
22
+ zIndex: abs.zIndex,
23
+ boxSizing: 'border-box',
24
+ };
25
+ };
26
+
27
+ export const buildCardStyle = (layout: CardLayoutSchema, unit: 'px' | 'rpx' = 'px') => ({
28
+ width: addUnit(layout.width, unit),
29
+ height: addUnit(layout.height, unit),
30
+ color: layout.fontColor,
31
+ borderRadius:
32
+ layout.borderRadius !== undefined
33
+ ? addUnit(layout.borderRadius, unit)
34
+ : undefined,
35
+ padding:
36
+ layout.padding !== undefined ? addUnit(layout.padding, unit) : undefined,
37
+ position: 'relative',
38
+ overflow: 'hidden',
39
+ boxSizing: 'border-box',
40
+ backgroundColor: 'transparent',
41
+ });
42
+
43
+ export const buildBackgroundStyle = (layout: CardLayoutSchema, unit: 'px' | 'rpx' = 'px') => ({
44
+ zIndex: layout.backgroundZIndex,
45
+ borderRadius:
46
+ layout.borderRadius !== undefined
47
+ ? addUnit(layout.borderRadius, unit)
48
+ : undefined,
49
+ width: '100%',
50
+ height: '100%',
51
+ position: 'absolute',
52
+ left: 0,
53
+ top: 0,
54
+ });
55
+
56
+ export const buildBaseContentStyle = (el: CardElement) => ({
57
+ ...(el.style || {}),
58
+ boxSizing: 'border-box',
59
+ });
60
+
61
+ export const buildPanelContentStyle = (el: LayoutPanelElement, unit: 'px' | 'rpx' = 'px') => ({
62
+ position: 'relative',
63
+ width: '100%',
64
+ height: '100%',
65
+ display: 'block',
66
+ boxSizing: 'border-box',
67
+ ...(el.style || {}),
68
+ });
69
+
70
+ export const buildTextContentStyle = (el: TextElement, unit: 'px' | 'rpx' = 'px') => {
71
+ const textAlign =
72
+ (el.style?.textAlign as string | undefined) || el.align || undefined;
73
+ const style: Record<string, any> = {
74
+ ...(el.style || {}),
75
+ fontSize: addUnit(el.style?.fontSize, unit),
76
+ whiteSpace: 'pre-wrap',
77
+ wordBreak: 'break-word',
78
+ lineHeight:
79
+ el.style?.lineHeight !== undefined && el.style?.lineHeight !== null
80
+ ? addUnit(el.style.lineHeight as any, unit)
81
+ : '1',
82
+ };
83
+ if (textAlign) style.textAlign = textAlign;
84
+ return style;
85
+ };
86
+
87
+ export const buildImageContentStyle = (el: ImageElement) => {
88
+ const style: Record<string, any> = { ...(el.style || {}) };
89
+ const borderWidth = Number(style.borderWidth);
90
+ if (Number.isFinite(borderWidth) && borderWidth > 0) {
91
+ if (!style.borderStyle) style.borderStyle = 'solid';
92
+ if (!style.borderColor) style.borderColor = '#000000';
93
+ }
94
+ return style;
95
+ };
96
+
97
+ export const getTextValue = (
98
+ el: TextElement,
99
+ data?: Record<string, any>
100
+ ) => {
101
+ const bound = el.binding && data ? resolveBindingValue(el.binding, data) : undefined;
102
+ const val =
103
+ bound !== undefined && bound !== null
104
+ ? bound
105
+ : el.defaultValue !== undefined && el.defaultValue !== null
106
+ ? el.defaultValue
107
+ : '';
108
+ return `${val ?? ''}`;
109
+ };
110
+
111
+ export const getImageSrc = (
112
+ el: ImageElement,
113
+ data?: Record<string, any>
114
+ ) => {
115
+ const bound = el.binding && data ? resolveBindingValue(el.binding, data) : undefined;
116
+ return (bound as any) || el.defaultUrl || el.defaultValue || '';
117
+ };
118
+
119
+ export const getIconName = (el: IconElement) =>
120
+ (el.name || el.defaultValue || '') as string;
121
+
122
+ export const buildTextIconMeta = (el: TextElement, unit: 'px' | 'rpx' = 'px') => {
123
+ const icon = el.icon;
124
+ const enabled = icon?.enable === true;
125
+ if (!icon || !enabled) return null;
126
+
127
+ const style = icon.style || 'fill';
128
+ const baseName = icon.name || el.key || el.binding || el.id;
129
+ let name: string | undefined;
130
+ if (style === 'dot') name = 'round';
131
+ else if (style === 'line') name = baseName ? `${baseName}-line` : undefined;
132
+ else name = baseName || undefined;
133
+ if (!name) return null;
134
+
135
+ const size =
136
+ icon.size !== undefined && icon.size !== null
137
+ ? icon.size
138
+ : (el.style?.fontSize as any);
139
+ const gap = icon.gap !== undefined && icon.gap !== null ? icon.gap : 4;
140
+ const color =
141
+ icon.color ??
142
+ ((typeof el.style?.color === 'string' ? el.style.color : undefined) as
143
+ | string
144
+ | undefined);
145
+
146
+ return {
147
+ name: `${name}`,
148
+ size: addUnit(size as any, unit),
149
+ gap: addUnit(gap as any, unit),
150
+ color,
151
+ align: icon.align || 'left',
152
+ wrapperStyle: {
153
+ height:
154
+ el.style?.lineHeight !== undefined && el.style?.lineHeight !== null
155
+ ? addUnit(el.style.lineHeight, unit)
156
+ : el.style?.fontSize,
157
+ },
158
+ };
159
+ };
package/types.d.ts CHANGED
@@ -6,12 +6,9 @@
6
6
  export * from './interface';
7
7
 
8
8
  import type {
9
- BindingContext,
10
9
  CardElement,
11
10
  CardLayoutInput,
12
11
  CardLayoutSchema,
13
- RenderNode,
14
- RenderResult,
15
12
  TemplateItem,
16
13
  TemplateBackground
17
14
  } from './interface';
@@ -68,8 +65,7 @@ export function areChildrenEqual(
68
65
 
69
66
  export function resolveBindingValue(
70
67
  binding: string | undefined,
71
- rootData: Record<string, any>,
72
- context?: BindingContext
68
+ rootData: Record<string, any>
73
69
  ): any;
74
70
 
75
71
  export function stripLayoutBindings(
@@ -148,22 +144,67 @@ export function updateElementsStyle(
148
144
  updates: Record<string, any>
149
145
  ): CardLayoutSchema;
150
146
 
151
- export function buildRenderNodes(
152
- children: CardElement[],
153
- data: Record<string, any>,
154
- unit?: 'px' | 'rpx',
155
- context?: BindingContext
156
- ): RenderNode[];
147
+ export function buildWrapperStyle(
148
+ el: CardElement,
149
+ unit?: 'px' | 'rpx'
150
+ ): Record<string, any>;
157
151
 
158
- export function buildRenderResult(
159
- layout: CardLayoutInput,
160
- data: Record<string, any>,
152
+ export function buildCardStyle(
153
+ layout: CardLayoutSchema,
154
+ unit?: 'px' | 'rpx'
155
+ ): Record<string, any>;
156
+
157
+ export function buildBackgroundStyle(
158
+ layout: CardLayoutSchema,
161
159
  unit?: 'px' | 'rpx'
162
- ): RenderResult;
160
+ ): Record<string, any>;
163
161
 
162
+ export function buildBaseContentStyle(
163
+ el: CardElement
164
+ ): Record<string, any>;
165
+
166
+ export function buildPanelContentStyle(
167
+ el: import('./interface/elements').LayoutPanelElement,
168
+ unit?: 'px' | 'rpx'
169
+ ): Record<string, any>;
170
+
171
+ export function buildTextContentStyle(
172
+ el: import('./interface/elements').TextElement,
173
+ unit?: 'px' | 'rpx'
174
+ ): Record<string, any>;
175
+
176
+ export function buildImageContentStyle(
177
+ el: import('./interface/elements').ImageElement
178
+ ): Record<string, any>;
179
+
180
+ export function getTextValue(
181
+ el: import('./interface/elements').TextElement,
182
+ data?: Record<string, any>
183
+ ): string;
184
+
185
+ export function getImageSrc(
186
+ el: import('./interface/elements').ImageElement,
187
+ data?: Record<string, any>
188
+ ): string;
189
+
190
+ export function getIconName(
191
+ el: import('./interface/elements').IconElement
192
+ ): string;
193
+
194
+ export function buildTextIconMeta(
195
+ el: import('./interface/elements').TextElement,
196
+ unit?: 'px' | 'rpx'
197
+ ): {
198
+ name: string;
199
+ size?: string;
200
+ gap?: string;
201
+ color?: string;
202
+ align: 'left' | 'right';
203
+ wrapperStyle?: Record<string, any>;
204
+ } | null;
164
205
 
165
206
  export function buildRenderData (
166
207
  layout: CardLayoutSchema[],
167
208
  items: TemplateItem[],
168
209
  config: Config
169
- ): CardLayoutSchema[];
210
+ ): CardLayoutSchema[];
@@ -1,53 +0,0 @@
1
- import type { CardElementType, CardElement } from './elements';
2
- import type { CardLayoutInput, CardLayoutSchema } from './layout';
3
-
4
- export interface RenderNodeIcon {
5
- name: string;
6
- text?: string;
7
- size?: string;
8
- color?: string;
9
- gap?: string;
10
- align?: 'left' | 'right';
11
- wrapperStyle?: string;
12
- }
13
-
14
- export interface RenderNode {
15
- id: string;
16
- type: CardElementType | 'text';
17
- wrapperStyle: string;
18
- contentStyle: string;
19
- name?: string;
20
- text?: string;
21
- src?: string;
22
- mode?: string;
23
- children?: RenderNode[];
24
- visible?: boolean;
25
- icon?: RenderNodeIcon;
26
- }
27
-
28
- export interface RenderPageResult {
29
- renderTree: RenderNode[];
30
- cardStyle: string;
31
- backgroundImage: string;
32
- backgroundStyle: string;
33
- }
34
-
35
- export type RenderResult = RenderPageResult[];
36
-
37
- export interface BindingContext {
38
- /**
39
- * 当前上下文数据的绑定前缀(预留给嵌套场景)
40
- */
41
- contextBinding?: string;
42
- /**
43
- * 当前上下文数据(预留给嵌套场景)
44
- */
45
- contextData?: any;
46
- }
47
-
48
- export type {
49
- CardElement,
50
- CardElementType,
51
- CardLayoutInput,
52
- CardLayoutSchema,
53
- };
package/render/builder.ts DELETED
@@ -1,287 +0,0 @@
1
- import type {
2
- CardElement,
3
- IconElement,
4
- ImageElement,
5
- LayoutPanelElement,
6
- TextElement,
7
- } from '../interface/elements';
8
- import type { CardLayoutSchema, CardLayoutInput } from '../interface/layout';
9
- import type {
10
- BindingContext,
11
- RenderNode,
12
- RenderResult,
13
- } from '../interface/render';
14
- import { addUnit, styleObjectToString } from '../helpers';
15
- import { getAbsLayout, normalizeLayout } from '../layout';
16
- import { resolveBindingValue } from '../data';
17
-
18
- const buildCardStyle = (layout: CardLayoutSchema, unit: 'px' | 'rpx') =>
19
- styleObjectToString(
20
- {
21
- width: addUnit(layout.width, unit),
22
- height: addUnit(layout.height, unit),
23
- color: layout.fontColor,
24
- borderRadius:
25
- layout.borderRadius !== undefined
26
- ? addUnit(layout.borderRadius, unit)
27
- : undefined,
28
- padding:
29
- layout.padding !== undefined ? addUnit(layout.padding, unit) : undefined,
30
- position: 'relative',
31
- overflow: 'hidden',
32
- boxSizing: 'border-box',
33
- backgroundColor: 'transparent',
34
- },
35
- unit
36
- );
37
-
38
- const buildBackgroundStyle = (layout: CardLayoutSchema, unit: 'px' | 'rpx') =>
39
- styleObjectToString(
40
- {
41
- zIndex: layout.backgroundZIndex,
42
- borderRadius:
43
- layout.borderRadius !== undefined
44
- ? addUnit(layout.borderRadius, unit)
45
- : undefined,
46
- width: '100%',
47
- height: '100%',
48
- position: 'absolute',
49
- left: 0,
50
- top: 0,
51
- },
52
- unit
53
- );
54
-
55
- const buildWrapperStyle = (el: CardElement, unit: 'px' | 'rpx'): string => {
56
- const abs = getAbsLayout(el);
57
- if (!abs) return '';
58
- return styleObjectToString(
59
- {
60
- position: 'absolute',
61
- left: addUnit(abs.x, unit),
62
- top: addUnit(abs.y, unit),
63
- width: addUnit(abs.width, unit),
64
- height: addUnit(abs.height, unit),
65
- zIndex: abs.zIndex,
66
- boxSizing: 'border-box',
67
- },
68
- unit
69
- );
70
- };
71
-
72
- const buildPanelContentStyle = (
73
- el: LayoutPanelElement,
74
- unit: 'px' | 'rpx'
75
- ) =>
76
- styleObjectToString(
77
- {
78
- position: 'relative',
79
- width: '100%',
80
- height: '100%',
81
- display: 'block',
82
- boxSizing: 'border-box',
83
- ...(el.style || {}),
84
- },
85
- unit
86
- );
87
-
88
- const buildTextContentStyle = (el: TextElement, unit: 'px' | 'rpx') => {
89
- const textAlign =
90
- (el.style?.textAlign as string | undefined) || el.align || undefined;
91
- const style: Record<string, any> = {
92
- ...(el.style || {}),
93
- whiteSpace: 'pre-wrap',
94
- wordBreak: 'break-word',
95
- lineHeight:
96
- el.style?.lineHeight !== undefined && el.style?.lineHeight !== null
97
- ? el.style.lineHeight
98
- : '1',
99
- };
100
- if (textAlign) style.textAlign = textAlign;
101
- return styleObjectToString(style, unit);
102
- };
103
-
104
- const buildBaseContentStyle = (el: CardElement, unit: 'px' | 'rpx') =>
105
- styleObjectToString(
106
- {
107
- ...(el.style || {}),
108
- boxSizing: 'border-box',
109
- },
110
- unit
111
- );
112
-
113
- const buildImageContentStyle = (el: ImageElement, unit: 'px' | 'rpx') => {
114
- const style: Record<string, any> = { ...(el.style || {}) };
115
- const borderWidth = Number(style.borderWidth);
116
- if (Number.isFinite(borderWidth) && borderWidth > 0) {
117
- if (!style.borderStyle) style.borderStyle = 'solid';
118
- if (!style.borderColor) style.borderColor = '#000000';
119
- }
120
- return styleObjectToString(style, unit);
121
- };
122
-
123
- const buildTextIcon = (
124
- el: TextElement,
125
- unit: 'px' | 'rpx'
126
- ): RenderNode['icon'] | undefined => {
127
- const icon = el.icon;
128
- const enabled = icon?.enable === true;
129
- if (!icon || !enabled) return undefined;
130
-
131
- const style = icon.style || 'fill';
132
- const baseName = icon.name || el.key || el.binding || el.id;
133
- let name: string | undefined;
134
- if (style === 'dot') name = 'round';
135
- else if (style === 'line') name = baseName ? `${baseName}-line` : undefined;
136
- else name = baseName || undefined;
137
- if (!name) return undefined;
138
-
139
- const size =
140
- icon.size !== undefined && icon.size !== null
141
- ? icon.size
142
- : (el.style?.fontSize as any);
143
- const gap = icon.gap !== undefined && icon.gap !== null ? icon.gap : 4;
144
- const color =
145
- icon.color ??
146
- ((typeof el.style?.color === 'string' ? el.style.color : undefined) as
147
- | string
148
- | undefined);
149
-
150
- return {
151
- name: `${name}`,
152
- text: `${name}`,
153
- size: addUnit(size as any, unit),
154
- gap: addUnit(gap as any, unit),
155
- color: color as any,
156
- align: icon.align || 'left',
157
- wrapperStyle: styleObjectToString(
158
- {
159
- height: el.style?.lineHeight || el.style?.fontSize,
160
- },
161
- unit
162
- ),
163
- };
164
- };
165
-
166
- const buildNode = (
167
- el: CardElement,
168
- rootData: Record<string, any>,
169
- unit: 'px' | 'rpx',
170
- context: BindingContext
171
- ): RenderNode | null => {
172
- if (!el || el.visible === false) return null;
173
- const wrapperStyle = buildWrapperStyle(el, unit);
174
-
175
- if (el.type === 'layout-panel') {
176
- return {
177
- id: el.id,
178
- type: el.type,
179
- visible: el.visible,
180
- wrapperStyle,
181
- contentStyle: buildPanelContentStyle(el as LayoutPanelElement, unit),
182
- children: buildRenderNodes(el.children || [], rootData, unit, context),
183
- };
184
- }
185
-
186
- const baseStyle = buildBaseContentStyle(el, unit);
187
- if (el.type === 'text') {
188
- const value =
189
- resolveBindingValue(el.binding, rootData, context) ??
190
- el.defaultValue ??
191
- '';
192
- return {
193
- id: el.id,
194
- type: el.type,
195
- wrapperStyle,
196
- contentStyle: buildTextContentStyle(el as TextElement, unit),
197
- text: `${value}`,
198
- visible: el.visible,
199
- icon: buildTextIcon(el as TextElement, unit),
200
- };
201
- }
202
-
203
- if (el.type === 'image') {
204
- const src =
205
- resolveBindingValue(el.binding, rootData, context) ??
206
- (el as ImageElement).defaultUrl ??
207
- el.defaultValue ??
208
- '';
209
- const mode =
210
- (el as ImageElement).fit === 'contain' ? 'aspectFit' : 'aspectFill';
211
- return {
212
- id: el.id,
213
- type: el.type,
214
- wrapperStyle,
215
- contentStyle: buildImageContentStyle(el as ImageElement, unit),
216
- src,
217
- mode,
218
- visible: el.visible,
219
- };
220
- }
221
-
222
- if (el.type === 'icon') {
223
- const name =
224
- resolveBindingValue(el.binding, rootData, context) ??
225
- (el as IconElement).name ??
226
- el.defaultValue ??
227
- '';
228
- return {
229
- id: el.id,
230
- type: el.type,
231
- wrapperStyle,
232
- contentStyle: baseStyle,
233
- name: `${name}`,
234
- text: `${name}`,
235
- visible: el.visible,
236
- };
237
- }
238
-
239
- if (el.type === 'custom') {
240
- return {
241
- id: el.id,
242
- type: el.type,
243
- wrapperStyle,
244
- contentStyle: baseStyle,
245
- visible: el.visible,
246
- };
247
- }
248
-
249
- return null;
250
- };
251
-
252
- export const buildRenderNodes = (
253
- children: CardElement[],
254
- rootData: Record<string, any>,
255
- unit: 'px' | 'rpx' = 'px',
256
- context: BindingContext = {}
257
- ): RenderNode[] => {
258
- if (!Array.isArray(children)) return [];
259
-
260
- const nodes: RenderNode[] = [];
261
- children.forEach(el => {
262
- if (!el || el.visible === false) return;
263
- const node = buildNode(el, rootData, unit, context);
264
- if (node) nodes.push(node);
265
- });
266
-
267
- return nodes;
268
- };
269
-
270
- export const buildRenderResult = (
271
- layoutInput: CardLayoutInput,
272
- dataInput: Record<string, any>,
273
- unit: 'px' | 'rpx' = 'px'
274
- ): RenderResult => {
275
- const layouts = normalizeLayout(layoutInput);
276
- return layouts.map(layout => {
277
- const cardStyle = buildCardStyle(layout, unit);
278
- const bgStyle = buildBackgroundStyle(layout, unit);
279
- const renderTree = buildRenderNodes(layout.children || [], dataInput || {}, unit);
280
- return {
281
- renderTree,
282
- cardStyle,
283
- backgroundImage: layout.backgroundImage || '',
284
- backgroundStyle: bgStyle,
285
- };
286
- });
287
- };