@open-feishu-card/renderer 0.2.11 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/all.css +10 -5
- package/dist/index.cjs +36 -10
- package/dist/index.js +37 -11
- package/dist/styles.css +10 -5
- package/package.json +2 -2
package/dist/all.css
CHANGED
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
line-height: 1.6;
|
|
19
19
|
color: #1f2329;
|
|
20
20
|
background-color: #fff;
|
|
21
|
+
position: relative;
|
|
21
22
|
border-radius: 8px;
|
|
22
|
-
border:
|
|
23
|
+
/* 对齐飞书网页版 --line-border-card: var(--N300);独立渲染器无消息气泡外包层,边框在 root */
|
|
24
|
+
border: 1px solid var(--N300);
|
|
23
25
|
overflow: hidden;
|
|
24
26
|
width: 100%;
|
|
25
27
|
max-width: 605px;
|
|
26
28
|
box-sizing: border-box;
|
|
27
|
-
box-shadow: 0 4px 14px rgba(31, 35, 41, 0.08);
|
|
28
29
|
/* BEGIN PALETTE VARS (auto-generated from constants.ts PALETTE) */
|
|
29
30
|
/* 正文 color:var(--O400) 等依赖这些变量;与飞书 :root light 色阶对齐 */
|
|
30
31
|
--B50: #f0f4ff;
|
|
@@ -271,7 +272,8 @@
|
|
|
271
272
|
padding: 12px;
|
|
272
273
|
display: flex;
|
|
273
274
|
flex-direction: column;
|
|
274
|
-
row-gap:
|
|
275
|
+
row-gap: 12px;
|
|
276
|
+
column-gap: 12px;
|
|
275
277
|
align-items: flex-start;
|
|
276
278
|
}
|
|
277
279
|
.universal-card-body > * { width: 100%; box-sizing: border-box; }
|
|
@@ -509,9 +511,12 @@
|
|
|
509
511
|
.universal-card-interactive-container {
|
|
510
512
|
display: flex; flex-direction: column; box-sizing: border-box;
|
|
511
513
|
border-radius: 6px; padding: 0; text-decoration: none; color: inherit;
|
|
512
|
-
|
|
514
|
+
row-gap: 4px;
|
|
515
|
+
transition: background-color .1s;
|
|
513
516
|
}
|
|
514
|
-
|
|
517
|
+
/* 真机:cursor:pointer 与 hover 底只在 __action 层;纯展示容器(无 actions/url)保持默认箭头 */
|
|
518
|
+
.universal-card-interactive-container--action { cursor: pointer; }
|
|
519
|
+
.universal-card-interactive-container--action:not(.universal-card-interactive-container--disabled):hover {
|
|
515
520
|
background-color: rgba(31, 35, 41, 0.05);
|
|
516
521
|
}
|
|
517
522
|
.universal-card-interactive-container--bordered { border: 1px solid #dee0e3; }
|
package/dist/index.cjs
CHANGED
|
@@ -706,13 +706,25 @@ function resolveURL(url) {
|
|
|
706
706
|
function sizeToPx(v) {
|
|
707
707
|
return typeof v === "number" ? v + "px" : String(v);
|
|
708
708
|
}
|
|
709
|
+
function marginToStyle(margin) {
|
|
710
|
+
if (typeof margin === "string" && margin.trim()) return margin.trim();
|
|
711
|
+
return boxToStyle(margin);
|
|
712
|
+
}
|
|
713
|
+
function resolveCornerRadius(property) {
|
|
714
|
+
if (!property) return void 0;
|
|
715
|
+
const direct = property.corner_radius ?? property.cornerRadius;
|
|
716
|
+
if (direct != null) return sizeToPx(direct);
|
|
717
|
+
const echo = property.cornerRadiusValue;
|
|
718
|
+
if (echo && typeof echo.value === "number") return echo.value + "px";
|
|
719
|
+
if (echo && typeof echo.value === "string" && echo.value.trim()) return sizeToPx(echo.value);
|
|
720
|
+
return void 0;
|
|
721
|
+
}
|
|
709
722
|
function boxToStyle(box) {
|
|
710
723
|
if (!box || typeof box !== "object") return null;
|
|
711
724
|
const t = box.top?.value ?? 0;
|
|
712
725
|
const r = box.right?.value ?? 0;
|
|
713
726
|
const b = box.bottom?.value ?? 0;
|
|
714
727
|
const l = box.left?.value ?? 0;
|
|
715
|
-
if (!t && !r && !b && !l) return null;
|
|
716
728
|
return `${t}px ${r}px ${b}px ${l}px`;
|
|
717
729
|
}
|
|
718
730
|
function bgStyleToColor(style) {
|
|
@@ -843,13 +855,14 @@ var BASE_STYLES_CSS = `/**
|
|
|
843
855
|
line-height: 1.6;
|
|
844
856
|
color: #1f2329;
|
|
845
857
|
background-color: #fff;
|
|
858
|
+
position: relative;
|
|
846
859
|
border-radius: 8px;
|
|
847
|
-
border:
|
|
860
|
+
/* \u5BF9\u9F50\u98DE\u4E66\u7F51\u9875\u7248 --line-border-card: var(--N300)\uFF1B\u72EC\u7ACB\u6E32\u67D3\u5668\u65E0\u6D88\u606F\u6C14\u6CE1\u5916\u5305\u5C42\uFF0C\u8FB9\u6846\u5728 root */
|
|
861
|
+
border: 1px solid var(--N300);
|
|
848
862
|
overflow: hidden;
|
|
849
863
|
width: 100%;
|
|
850
864
|
max-width: 605px;
|
|
851
865
|
box-sizing: border-box;
|
|
852
|
-
box-shadow: 0 4px 14px rgba(31, 35, 41, 0.08);
|
|
853
866
|
/* BEGIN PALETTE VARS (auto-generated from constants.ts PALETTE) */
|
|
854
867
|
/* \u6B63\u6587 color:var(--O400) \u7B49\u4F9D\u8D56\u8FD9\u4E9B\u53D8\u91CF\uFF1B\u4E0E\u98DE\u4E66 :root light \u8272\u9636\u5BF9\u9F50 */
|
|
855
868
|
--B50: #f0f4ff;
|
|
@@ -1096,7 +1109,8 @@ var BASE_STYLES_CSS = `/**
|
|
|
1096
1109
|
padding: 12px;
|
|
1097
1110
|
display: flex;
|
|
1098
1111
|
flex-direction: column;
|
|
1099
|
-
row-gap:
|
|
1112
|
+
row-gap: 12px;
|
|
1113
|
+
column-gap: 12px;
|
|
1100
1114
|
align-items: flex-start;
|
|
1101
1115
|
}
|
|
1102
1116
|
.universal-card-body > * { width: 100%; box-sizing: border-box; }
|
|
@@ -1334,9 +1348,12 @@ var BASE_STYLES_CSS = `/**
|
|
|
1334
1348
|
.universal-card-interactive-container {
|
|
1335
1349
|
display: flex; flex-direction: column; box-sizing: border-box;
|
|
1336
1350
|
border-radius: 6px; padding: 0; text-decoration: none; color: inherit;
|
|
1337
|
-
|
|
1351
|
+
row-gap: 4px;
|
|
1352
|
+
transition: background-color .1s;
|
|
1338
1353
|
}
|
|
1339
|
-
|
|
1354
|
+
/* \u771F\u673A\uFF1Acursor:pointer \u4E0E hover \u5E95\u53EA\u5728 __action \u5C42\uFF1B\u7EAF\u5C55\u793A\u5BB9\u5668\uFF08\u65E0 actions/url\uFF09\u4FDD\u6301\u9ED8\u8BA4\u7BAD\u5934 */
|
|
1355
|
+
.universal-card-interactive-container--action { cursor: pointer; }
|
|
1356
|
+
.universal-card-interactive-container--action:not(.universal-card-interactive-container--disabled):hover {
|
|
1340
1357
|
background-color: rgba(31, 35, 41, 0.05);
|
|
1341
1358
|
}
|
|
1342
1359
|
.universal-card-interactive-container--bordered { border: 1px solid #dee0e3; }
|
|
@@ -5418,6 +5435,8 @@ function registerBuiltins() {
|
|
|
5418
5435
|
registerComponent("markdown", (el, ctx) => {
|
|
5419
5436
|
const p = el.property || {};
|
|
5420
5437
|
const style = { ...alignToStyle(p.textAlign), ...textStyleToStyle(p.textStyle) };
|
|
5438
|
+
const mg = marginToStyle(p.margin);
|
|
5439
|
+
if (mg) style.margin = mg;
|
|
5421
5440
|
const sizeKey = resolveTextSizeKey(p);
|
|
5422
5441
|
let fontSize = BASE_FONT_SIZE;
|
|
5423
5442
|
let lineHeight = BASE_FONT_SIZE + 8;
|
|
@@ -5689,17 +5708,24 @@ function registerBuiltins() {
|
|
|
5689
5708
|
const disabled = p.disabled === true;
|
|
5690
5709
|
const act = Array.isArray(p.actions) ? p.actions[0] : void 0;
|
|
5691
5710
|
const url = resolveURL(act?.action?.url);
|
|
5711
|
+
const hasActions = Array.isArray(p.actions) && p.actions.length > 0;
|
|
5712
|
+
const clickable = !disabled && (Boolean(url) || hasActions);
|
|
5692
5713
|
const tip = extractText(p.hoverTips);
|
|
5693
|
-
const
|
|
5694
|
-
const
|
|
5695
|
-
const
|
|
5714
|
+
const borderNamed = p.border_color ?? p.borderColor;
|
|
5715
|
+
const borderCustom = adapter.resolveCustomBorderLight(p);
|
|
5716
|
+
const borderColor = resolveColor(borderNamed) ?? (borderCustom ? resolveColor(borderCustom) : void 0);
|
|
5717
|
+
const hasBorder = borderColor != null || p.hasBorder === true || p.has_border === true;
|
|
5718
|
+
const cls = `${CLS}-interactive-container` + (clickable ? ` ${CLS}-interactive-container--action` : "") + (hasBorder && !borderColor ? ` ${CLS}-interactive-container--bordered` : "") + (disabled ? ` ${CLS}-interactive-container--disabled` : "");
|
|
5696
5719
|
const style = {};
|
|
5697
5720
|
const bg = propertyBackgroundColor(p);
|
|
5698
5721
|
if (bg) style.background = bg;
|
|
5699
5722
|
const pad = boxToStyle(p.padding);
|
|
5700
5723
|
if (pad) style.padding = pad;
|
|
5701
5724
|
if (borderColor) style.border = `1px solid ${borderColor}`;
|
|
5702
|
-
|
|
5725
|
+
const radius = resolveCornerRadius(p);
|
|
5726
|
+
if (radius != null) style.borderRadius = radius;
|
|
5727
|
+
const vGap = p.verticalSpacingValue?.value ?? p.vertical_spacing;
|
|
5728
|
+
if (vGap != null) style.rowGap = spacingToPx(vGap) + "px";
|
|
5703
5729
|
const icWv = p.widthValue;
|
|
5704
5730
|
if ((p.width ?? icWv?.value) === "fill") style.width = "100%";
|
|
5705
5731
|
const props = { className: cls };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { dslToRaw, resolveTextStyleColor, resolveCustomBackgroundLight } from '@open-feishu-card/adapter';
|
|
1
|
+
import { resolveCustomBorderLight, dslToRaw, resolveTextStyleColor, resolveCustomBackgroundLight } from '@open-feishu-card/adapter';
|
|
2
2
|
export { dslToRaw } from '@open-feishu-card/adapter';
|
|
3
3
|
|
|
4
4
|
// src/constants.ts
|
|
@@ -705,13 +705,25 @@ function resolveURL(url) {
|
|
|
705
705
|
function sizeToPx(v) {
|
|
706
706
|
return typeof v === "number" ? v + "px" : String(v);
|
|
707
707
|
}
|
|
708
|
+
function marginToStyle(margin) {
|
|
709
|
+
if (typeof margin === "string" && margin.trim()) return margin.trim();
|
|
710
|
+
return boxToStyle(margin);
|
|
711
|
+
}
|
|
712
|
+
function resolveCornerRadius(property) {
|
|
713
|
+
if (!property) return void 0;
|
|
714
|
+
const direct = property.corner_radius ?? property.cornerRadius;
|
|
715
|
+
if (direct != null) return sizeToPx(direct);
|
|
716
|
+
const echo = property.cornerRadiusValue;
|
|
717
|
+
if (echo && typeof echo.value === "number") return echo.value + "px";
|
|
718
|
+
if (echo && typeof echo.value === "string" && echo.value.trim()) return sizeToPx(echo.value);
|
|
719
|
+
return void 0;
|
|
720
|
+
}
|
|
708
721
|
function boxToStyle(box) {
|
|
709
722
|
if (!box || typeof box !== "object") return null;
|
|
710
723
|
const t = box.top?.value ?? 0;
|
|
711
724
|
const r = box.right?.value ?? 0;
|
|
712
725
|
const b = box.bottom?.value ?? 0;
|
|
713
726
|
const l = box.left?.value ?? 0;
|
|
714
|
-
if (!t && !r && !b && !l) return null;
|
|
715
727
|
return `${t}px ${r}px ${b}px ${l}px`;
|
|
716
728
|
}
|
|
717
729
|
function bgStyleToColor(style) {
|
|
@@ -842,13 +854,14 @@ var BASE_STYLES_CSS = `/**
|
|
|
842
854
|
line-height: 1.6;
|
|
843
855
|
color: #1f2329;
|
|
844
856
|
background-color: #fff;
|
|
857
|
+
position: relative;
|
|
845
858
|
border-radius: 8px;
|
|
846
|
-
border:
|
|
859
|
+
/* \u5BF9\u9F50\u98DE\u4E66\u7F51\u9875\u7248 --line-border-card: var(--N300)\uFF1B\u72EC\u7ACB\u6E32\u67D3\u5668\u65E0\u6D88\u606F\u6C14\u6CE1\u5916\u5305\u5C42\uFF0C\u8FB9\u6846\u5728 root */
|
|
860
|
+
border: 1px solid var(--N300);
|
|
847
861
|
overflow: hidden;
|
|
848
862
|
width: 100%;
|
|
849
863
|
max-width: 605px;
|
|
850
864
|
box-sizing: border-box;
|
|
851
|
-
box-shadow: 0 4px 14px rgba(31, 35, 41, 0.08);
|
|
852
865
|
/* BEGIN PALETTE VARS (auto-generated from constants.ts PALETTE) */
|
|
853
866
|
/* \u6B63\u6587 color:var(--O400) \u7B49\u4F9D\u8D56\u8FD9\u4E9B\u53D8\u91CF\uFF1B\u4E0E\u98DE\u4E66 :root light \u8272\u9636\u5BF9\u9F50 */
|
|
854
867
|
--B50: #f0f4ff;
|
|
@@ -1095,7 +1108,8 @@ var BASE_STYLES_CSS = `/**
|
|
|
1095
1108
|
padding: 12px;
|
|
1096
1109
|
display: flex;
|
|
1097
1110
|
flex-direction: column;
|
|
1098
|
-
row-gap:
|
|
1111
|
+
row-gap: 12px;
|
|
1112
|
+
column-gap: 12px;
|
|
1099
1113
|
align-items: flex-start;
|
|
1100
1114
|
}
|
|
1101
1115
|
.universal-card-body > * { width: 100%; box-sizing: border-box; }
|
|
@@ -1333,9 +1347,12 @@ var BASE_STYLES_CSS = `/**
|
|
|
1333
1347
|
.universal-card-interactive-container {
|
|
1334
1348
|
display: flex; flex-direction: column; box-sizing: border-box;
|
|
1335
1349
|
border-radius: 6px; padding: 0; text-decoration: none; color: inherit;
|
|
1336
|
-
|
|
1350
|
+
row-gap: 4px;
|
|
1351
|
+
transition: background-color .1s;
|
|
1337
1352
|
}
|
|
1338
|
-
|
|
1353
|
+
/* \u771F\u673A\uFF1Acursor:pointer \u4E0E hover \u5E95\u53EA\u5728 __action \u5C42\uFF1B\u7EAF\u5C55\u793A\u5BB9\u5668\uFF08\u65E0 actions/url\uFF09\u4FDD\u6301\u9ED8\u8BA4\u7BAD\u5934 */
|
|
1354
|
+
.universal-card-interactive-container--action { cursor: pointer; }
|
|
1355
|
+
.universal-card-interactive-container--action:not(.universal-card-interactive-container--disabled):hover {
|
|
1339
1356
|
background-color: rgba(31, 35, 41, 0.05);
|
|
1340
1357
|
}
|
|
1341
1358
|
.universal-card-interactive-container--bordered { border: 1px solid #dee0e3; }
|
|
@@ -5417,6 +5434,8 @@ function registerBuiltins() {
|
|
|
5417
5434
|
registerComponent("markdown", (el, ctx) => {
|
|
5418
5435
|
const p = el.property || {};
|
|
5419
5436
|
const style = { ...alignToStyle(p.textAlign), ...textStyleToStyle(p.textStyle) };
|
|
5437
|
+
const mg = marginToStyle(p.margin);
|
|
5438
|
+
if (mg) style.margin = mg;
|
|
5420
5439
|
const sizeKey = resolveTextSizeKey(p);
|
|
5421
5440
|
let fontSize = BASE_FONT_SIZE;
|
|
5422
5441
|
let lineHeight = BASE_FONT_SIZE + 8;
|
|
@@ -5688,17 +5707,24 @@ function registerBuiltins() {
|
|
|
5688
5707
|
const disabled = p.disabled === true;
|
|
5689
5708
|
const act = Array.isArray(p.actions) ? p.actions[0] : void 0;
|
|
5690
5709
|
const url = resolveURL(act?.action?.url);
|
|
5710
|
+
const hasActions = Array.isArray(p.actions) && p.actions.length > 0;
|
|
5711
|
+
const clickable = !disabled && (Boolean(url) || hasActions);
|
|
5691
5712
|
const tip = extractText(p.hoverTips);
|
|
5692
|
-
const
|
|
5693
|
-
const
|
|
5694
|
-
const
|
|
5713
|
+
const borderNamed = p.border_color ?? p.borderColor;
|
|
5714
|
+
const borderCustom = resolveCustomBorderLight(p);
|
|
5715
|
+
const borderColor = resolveColor(borderNamed) ?? (borderCustom ? resolveColor(borderCustom) : void 0);
|
|
5716
|
+
const hasBorder = borderColor != null || p.hasBorder === true || p.has_border === true;
|
|
5717
|
+
const cls = `${CLS}-interactive-container` + (clickable ? ` ${CLS}-interactive-container--action` : "") + (hasBorder && !borderColor ? ` ${CLS}-interactive-container--bordered` : "") + (disabled ? ` ${CLS}-interactive-container--disabled` : "");
|
|
5695
5718
|
const style = {};
|
|
5696
5719
|
const bg = propertyBackgroundColor(p);
|
|
5697
5720
|
if (bg) style.background = bg;
|
|
5698
5721
|
const pad = boxToStyle(p.padding);
|
|
5699
5722
|
if (pad) style.padding = pad;
|
|
5700
5723
|
if (borderColor) style.border = `1px solid ${borderColor}`;
|
|
5701
|
-
|
|
5724
|
+
const radius = resolveCornerRadius(p);
|
|
5725
|
+
if (radius != null) style.borderRadius = radius;
|
|
5726
|
+
const vGap = p.verticalSpacingValue?.value ?? p.vertical_spacing;
|
|
5727
|
+
if (vGap != null) style.rowGap = spacingToPx(vGap) + "px";
|
|
5702
5728
|
const icWv = p.widthValue;
|
|
5703
5729
|
if ((p.width ?? icWv?.value) === "fill") style.width = "100%";
|
|
5704
5730
|
const props = { className: cls };
|
package/dist/styles.css
CHANGED
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
line-height: 1.6;
|
|
19
19
|
color: #1f2329;
|
|
20
20
|
background-color: #fff;
|
|
21
|
+
position: relative;
|
|
21
22
|
border-radius: 8px;
|
|
22
|
-
border:
|
|
23
|
+
/* 对齐飞书网页版 --line-border-card: var(--N300);独立渲染器无消息气泡外包层,边框在 root */
|
|
24
|
+
border: 1px solid var(--N300);
|
|
23
25
|
overflow: hidden;
|
|
24
26
|
width: 100%;
|
|
25
27
|
max-width: 605px;
|
|
26
28
|
box-sizing: border-box;
|
|
27
|
-
box-shadow: 0 4px 14px rgba(31, 35, 41, 0.08);
|
|
28
29
|
/* BEGIN PALETTE VARS (auto-generated from constants.ts PALETTE) */
|
|
29
30
|
/* 正文 color:var(--O400) 等依赖这些变量;与飞书 :root light 色阶对齐 */
|
|
30
31
|
--B50: #f0f4ff;
|
|
@@ -271,7 +272,8 @@
|
|
|
271
272
|
padding: 12px;
|
|
272
273
|
display: flex;
|
|
273
274
|
flex-direction: column;
|
|
274
|
-
row-gap:
|
|
275
|
+
row-gap: 12px;
|
|
276
|
+
column-gap: 12px;
|
|
275
277
|
align-items: flex-start;
|
|
276
278
|
}
|
|
277
279
|
.universal-card-body > * { width: 100%; box-sizing: border-box; }
|
|
@@ -509,9 +511,12 @@
|
|
|
509
511
|
.universal-card-interactive-container {
|
|
510
512
|
display: flex; flex-direction: column; box-sizing: border-box;
|
|
511
513
|
border-radius: 6px; padding: 0; text-decoration: none; color: inherit;
|
|
512
|
-
|
|
514
|
+
row-gap: 4px;
|
|
515
|
+
transition: background-color .1s;
|
|
513
516
|
}
|
|
514
|
-
|
|
517
|
+
/* 真机:cursor:pointer 与 hover 底只在 __action 层;纯展示容器(无 actions/url)保持默认箭头 */
|
|
518
|
+
.universal-card-interactive-container--action { cursor: pointer; }
|
|
519
|
+
.universal-card-interactive-container--action:not(.universal-card-interactive-container--disabled):hover {
|
|
515
520
|
background-color: rgba(31, 35, 41, 0.05);
|
|
516
521
|
}
|
|
517
522
|
.universal-card-interactive-container--bordered { border: 1px solid #dee0e3; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-feishu-card/renderer",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.13",
|
|
4
4
|
"description": "零框架依赖的飞书卡片渲染引擎:Web / DOM / SSR,输入 RAW 或公开 DSL,输出真实 DOM 或 HTML 字符串",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"./dist/*.cjs"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@open-feishu-card/adapter": "0.3.
|
|
31
|
+
"@open-feishu-card/adapter": "0.3.9"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"tsup": "^8.3.5",
|