@open-feishu-card/renderer 0.3.0 → 0.3.2
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 +33 -0
- package/dist/index.cjs +108 -2
- package/dist/index.js +108 -2
- package/dist/styles.css +33 -0
- package/package.json +1 -1
package/dist/all.css
CHANGED
|
@@ -288,6 +288,13 @@
|
|
|
288
288
|
word-break: break-word;
|
|
289
289
|
vertical-align: middle;
|
|
290
290
|
}
|
|
291
|
+
/* 前缀图标(markdown.icon):与首行文字垂直居中,右侧留 4px。
|
|
292
|
+
容器是 flex row,图标作为首个 flex 子项参与排布。 */
|
|
293
|
+
.universal-card-markdown__icon {
|
|
294
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
295
|
+
flex-shrink: 0; margin-right: 4px;
|
|
296
|
+
height: 1.6em;
|
|
297
|
+
}
|
|
291
298
|
.universal-card-markdown__children {
|
|
292
299
|
flex: 1;
|
|
293
300
|
min-width: 0;
|
|
@@ -443,6 +450,32 @@
|
|
|
443
450
|
/* 非跳转按钮:保留外观,但不可点(默认光标、无 hover、不响应点击) */
|
|
444
451
|
.universal-card-button--static { cursor: default; pointer-events: none; }
|
|
445
452
|
|
|
453
|
+
/* ---- overflow 折叠按钮组 ---- */
|
|
454
|
+
/* 真机是一个「…」图标按钮,点击弹出选项菜单。静态预览只画触发器(--static 不可点)。 */
|
|
455
|
+
.universal-card-overflow { display: inline-flex; position: relative; vertical-align: middle; }
|
|
456
|
+
.universal-card-overflow--static { display: inline-flex; }
|
|
457
|
+
.universal-card-overflow__summary {
|
|
458
|
+
list-style: none; cursor: pointer; display: inline-flex;
|
|
459
|
+
}
|
|
460
|
+
/* 去掉 <summary> 的浏览器默认三角标记 */
|
|
461
|
+
.universal-card-overflow__summary::-webkit-details-marker { display: none; }
|
|
462
|
+
.universal-card-overflow__summary::marker { content: ''; }
|
|
463
|
+
/* 菜单:默认隐藏,<details open> 时浮在触发器下方 */
|
|
464
|
+
.universal-card-overflow__menu {
|
|
465
|
+
display: none;
|
|
466
|
+
position: absolute; top: calc(100% + 4px); left: 0; z-index: 20;
|
|
467
|
+
min-width: 120px; padding: 4px 0;
|
|
468
|
+
background: #fff; border-radius: 6px;
|
|
469
|
+
box-shadow: 0 4px 12px rgba(31, 35, 41, 0.15), 0 0 1px rgba(31, 35, 41, 0.2);
|
|
470
|
+
}
|
|
471
|
+
.universal-card-overflow[open] > .universal-card-overflow__menu { display: block; }
|
|
472
|
+
.universal-card-overflow__item {
|
|
473
|
+
display: block; padding: 6px 12px;
|
|
474
|
+
font-size: 14px; line-height: 22px; color: #1f2329;
|
|
475
|
+
text-decoration: none; white-space: nowrap; cursor: pointer;
|
|
476
|
+
}
|
|
477
|
+
.universal-card-overflow__item:hover { background: #f5f6f7; }
|
|
478
|
+
|
|
446
479
|
/* ---- 表单(预览:仅透传,无表单语义) ---- */
|
|
447
480
|
.universal-card-form { display: flex; flex-direction: column; row-gap: 8px; }
|
|
448
481
|
.universal-card-form > * { width: 100%; }
|
package/dist/index.cjs
CHANGED
|
@@ -1258,6 +1258,13 @@ var BASE_STYLES_CSS = `/**
|
|
|
1258
1258
|
word-break: break-word;
|
|
1259
1259
|
vertical-align: middle;
|
|
1260
1260
|
}
|
|
1261
|
+
/* \u524D\u7F00\u56FE\u6807\uFF08markdown.icon\uFF09\uFF1A\u4E0E\u9996\u884C\u6587\u5B57\u5782\u76F4\u5C45\u4E2D\uFF0C\u53F3\u4FA7\u7559 4px\u3002
|
|
1262
|
+
\u5BB9\u5668\u662F flex row\uFF0C\u56FE\u6807\u4F5C\u4E3A\u9996\u4E2A flex \u5B50\u9879\u53C2\u4E0E\u6392\u5E03\u3002 */
|
|
1263
|
+
.universal-card-markdown__icon {
|
|
1264
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
1265
|
+
flex-shrink: 0; margin-right: 4px;
|
|
1266
|
+
height: 1.6em;
|
|
1267
|
+
}
|
|
1261
1268
|
.universal-card-markdown__children {
|
|
1262
1269
|
flex: 1;
|
|
1263
1270
|
min-width: 0;
|
|
@@ -1413,6 +1420,32 @@ var BASE_STYLES_CSS = `/**
|
|
|
1413
1420
|
/* \u975E\u8DF3\u8F6C\u6309\u94AE\uFF1A\u4FDD\u7559\u5916\u89C2\uFF0C\u4F46\u4E0D\u53EF\u70B9\uFF08\u9ED8\u8BA4\u5149\u6807\u3001\u65E0 hover\u3001\u4E0D\u54CD\u5E94\u70B9\u51FB\uFF09 */
|
|
1414
1421
|
.universal-card-button--static { cursor: default; pointer-events: none; }
|
|
1415
1422
|
|
|
1423
|
+
/* ---- overflow \u6298\u53E0\u6309\u94AE\u7EC4 ---- */
|
|
1424
|
+
/* \u771F\u673A\u662F\u4E00\u4E2A\u300C\u2026\u300D\u56FE\u6807\u6309\u94AE\uFF0C\u70B9\u51FB\u5F39\u51FA\u9009\u9879\u83DC\u5355\u3002\u9759\u6001\u9884\u89C8\u53EA\u753B\u89E6\u53D1\u5668\uFF08--static \u4E0D\u53EF\u70B9\uFF09\u3002 */
|
|
1425
|
+
.universal-card-overflow { display: inline-flex; position: relative; vertical-align: middle; }
|
|
1426
|
+
.universal-card-overflow--static { display: inline-flex; }
|
|
1427
|
+
.universal-card-overflow__summary {
|
|
1428
|
+
list-style: none; cursor: pointer; display: inline-flex;
|
|
1429
|
+
}
|
|
1430
|
+
/* \u53BB\u6389 <summary> \u7684\u6D4F\u89C8\u5668\u9ED8\u8BA4\u4E09\u89D2\u6807\u8BB0 */
|
|
1431
|
+
.universal-card-overflow__summary::-webkit-details-marker { display: none; }
|
|
1432
|
+
.universal-card-overflow__summary::marker { content: ''; }
|
|
1433
|
+
/* \u83DC\u5355\uFF1A\u9ED8\u8BA4\u9690\u85CF\uFF0C<details open> \u65F6\u6D6E\u5728\u89E6\u53D1\u5668\u4E0B\u65B9 */
|
|
1434
|
+
.universal-card-overflow__menu {
|
|
1435
|
+
display: none;
|
|
1436
|
+
position: absolute; top: calc(100% + 4px); left: 0; z-index: 20;
|
|
1437
|
+
min-width: 120px; padding: 4px 0;
|
|
1438
|
+
background: #fff; border-radius: 6px;
|
|
1439
|
+
box-shadow: 0 4px 12px rgba(31, 35, 41, 0.15), 0 0 1px rgba(31, 35, 41, 0.2);
|
|
1440
|
+
}
|
|
1441
|
+
.universal-card-overflow[open] > .universal-card-overflow__menu { display: block; }
|
|
1442
|
+
.universal-card-overflow__item {
|
|
1443
|
+
display: block; padding: 6px 12px;
|
|
1444
|
+
font-size: 14px; line-height: 22px; color: #1f2329;
|
|
1445
|
+
text-decoration: none; white-space: nowrap; cursor: pointer;
|
|
1446
|
+
}
|
|
1447
|
+
.universal-card-overflow__item:hover { background: #f5f6f7; }
|
|
1448
|
+
|
|
1416
1449
|
/* ---- \u8868\u5355\uFF08\u9884\u89C8\uFF1A\u4EC5\u900F\u4F20\uFF0C\u65E0\u8868\u5355\u8BED\u4E49\uFF09 ---- */
|
|
1417
1450
|
.universal-card-form { display: flex; flex-direction: column; row-gap: 8px; }
|
|
1418
1451
|
.universal-card-form > * { width: 100%; }
|
|
@@ -5699,15 +5732,50 @@ function registerBuiltins() {
|
|
|
5699
5732
|
}
|
|
5700
5733
|
const childCtx = { ...ctx, textMetrics: { fontSize, lineHeight } };
|
|
5701
5734
|
const linesStyle = lineClampStyle(p.lines ?? p.textLines);
|
|
5735
|
+
const iconVNode = renderPrefixIcon(p.icon, ctx, fontSize);
|
|
5702
5736
|
return h(
|
|
5703
5737
|
"div",
|
|
5704
5738
|
{ className: `${CLS}-markdown`, style },
|
|
5739
|
+
iconVNode,
|
|
5705
5740
|
h("div", {
|
|
5706
5741
|
className: `${CLS}-markdown__children`,
|
|
5707
5742
|
style: Object.keys(linesStyle).length ? linesStyle : void 0
|
|
5708
5743
|
}, renderElements(p.elements, childCtx))
|
|
5709
5744
|
);
|
|
5710
5745
|
}
|
|
5746
|
+
function renderPrefixIcon(raw, ctx, fontSize) {
|
|
5747
|
+
if (!isRecord(raw)) return null;
|
|
5748
|
+
const inner = isRecord(raw.property) ? raw.property : raw;
|
|
5749
|
+
const tag = typeof raw.tag === "string" ? raw.tag : "standard_icon";
|
|
5750
|
+
const sizeProp = typeof inner.size === "string" ? inner.size : typeof raw.size === "string" ? raw.size : void 0;
|
|
5751
|
+
if (tag === "custom_icon") {
|
|
5752
|
+
const imgKey = typeof inner.img_key === "string" ? inner.img_key : typeof raw.img_key === "string" ? raw.img_key : void 0;
|
|
5753
|
+
if (!imgKey) return null;
|
|
5754
|
+
const src = resolveImageSrc({ img_key: imgKey }, ctx) ?? imgKey;
|
|
5755
|
+
const sizePx = sizeProp && /^\d/.test(sizeProp) ? Number(/^(\d+(?:\.\d+)?)/.exec(sizeProp)[1]) : fontSize;
|
|
5756
|
+
return h(
|
|
5757
|
+
"span",
|
|
5758
|
+
{ className: `${CLS}-markdown__icon` },
|
|
5759
|
+
h("img", {
|
|
5760
|
+
src,
|
|
5761
|
+
alt: "",
|
|
5762
|
+
style: { width: sizePx + "px", height: sizePx + "px", objectFit: "contain" }
|
|
5763
|
+
})
|
|
5764
|
+
);
|
|
5765
|
+
}
|
|
5766
|
+
const token = typeof inner.token === "string" ? inner.token : "";
|
|
5767
|
+
if (!token) return null;
|
|
5768
|
+
const iconNode = renderIcon({
|
|
5769
|
+
property: {
|
|
5770
|
+
token,
|
|
5771
|
+
color: typeof inner.color === "string" ? inner.color : void 0,
|
|
5772
|
+
// 未显式给 size 时跟随文本字号,避免回落到固定 16px 与文字不搭
|
|
5773
|
+
size: sizeProp ?? fontSize + "px"
|
|
5774
|
+
}
|
|
5775
|
+
}, ctx);
|
|
5776
|
+
if (!iconNode) return null;
|
|
5777
|
+
return h("span", { className: `${CLS}-markdown__icon` }, iconNode);
|
|
5778
|
+
}
|
|
5711
5779
|
registerComponent("markdown", MarkdownComponent);
|
|
5712
5780
|
registerComponent("markdown_v1", MarkdownComponent);
|
|
5713
5781
|
function lineClampStyle(lines) {
|
|
@@ -6035,8 +6103,9 @@ function registerBuiltins() {
|
|
|
6035
6103
|
const tip = extractText(p.hoverTips);
|
|
6036
6104
|
const borderNamed = p.border_color ?? p.borderColor;
|
|
6037
6105
|
const borderCustom = adapter.resolveCustomBorderLight(p);
|
|
6038
|
-
const
|
|
6039
|
-
const hasBorder =
|
|
6106
|
+
const borderColorResolved = (borderCustom ? resolveColor(borderCustom) : void 0) ?? resolveColor(borderNamed);
|
|
6107
|
+
const hasBorder = p.hasBorder === true || p.has_border === true;
|
|
6108
|
+
const borderColor = hasBorder ? borderColorResolved : void 0;
|
|
6040
6109
|
const cls = `${CLS}-interactive-container` + (clickable ? ` ${CLS}-interactive-container--action` : "") + (hasBorder && !borderColor ? ` ${CLS}-interactive-container--bordered` : "") + (disabled ? ` ${CLS}-interactive-container--disabled` : "");
|
|
6041
6110
|
const style = {};
|
|
6042
6111
|
const bg = propertyBackgroundColor(p);
|
|
@@ -6204,6 +6273,43 @@ function registerBuiltins() {
|
|
|
6204
6273
|
};
|
|
6205
6274
|
return fromList(p.actions) ?? fromList(p.behaviors) ?? (isRecord(p.value) ? p.value : null);
|
|
6206
6275
|
}
|
|
6276
|
+
registerComponent("overflow", (el, ctx) => {
|
|
6277
|
+
const p = el.property || {};
|
|
6278
|
+
const disabled = p.disabled === true;
|
|
6279
|
+
const options = Array.isArray(p.options) ? p.options : [];
|
|
6280
|
+
const widthTok = p.width ?? p.widthValue?.value;
|
|
6281
|
+
const block = widthTok === "fill";
|
|
6282
|
+
const triggerIcon = renderIcon(
|
|
6283
|
+
{ property: { token: "more_outlined", size: "14px" } },
|
|
6284
|
+
ctx
|
|
6285
|
+
);
|
|
6286
|
+
const triggerCls = `${CLS}-button ${CLS}-button--default ${CLS}-button--static ${CLS}-overflow__trigger` + (disabled ? ` ${CLS}-button--disabled` : "") + (block ? ` ${CLS}-button--block` : "");
|
|
6287
|
+
const trigger = triggerIcon ? h("span", { className: triggerCls }, h("span", { className: `${CLS}-button__icon` }, triggerIcon)) : h("span", { className: triggerCls }, "\xB7\xB7\xB7");
|
|
6288
|
+
const items = options.map((raw) => {
|
|
6289
|
+
const opt = isRecord(raw) ? raw : {};
|
|
6290
|
+
const textObj = opt.text;
|
|
6291
|
+
const label = (isRecord(textObj) && typeof textObj.content === "string" ? textObj.content : extractPlainText(textObj)) || extractPlainText(opt);
|
|
6292
|
+
const multi = isRecord(opt.multi_url) ? opt.multi_url : void 0;
|
|
6293
|
+
const href = resolveURL(multi?.url ?? opt.url);
|
|
6294
|
+
const itemCls = `${CLS}-overflow__item`;
|
|
6295
|
+
if (href && !disabled) {
|
|
6296
|
+
return h("a", { className: itemCls, href, target: "_blank", rel: "noopener" }, label);
|
|
6297
|
+
}
|
|
6298
|
+
return h("span", { className: itemCls }, label);
|
|
6299
|
+
});
|
|
6300
|
+
const style = {};
|
|
6301
|
+
if (p.margin) applyOuterMargin(style, p.margin);
|
|
6302
|
+
const styleProp = Object.keys(style).length ? { style } : {};
|
|
6303
|
+
if (!ctx.options.interactive) {
|
|
6304
|
+
return h("span", { className: `${CLS}-overflow ${CLS}-overflow--static`, ...styleProp }, trigger);
|
|
6305
|
+
}
|
|
6306
|
+
return h(
|
|
6307
|
+
"details",
|
|
6308
|
+
{ className: `${CLS}-overflow`, ...styleProp },
|
|
6309
|
+
h("summary", { className: `${CLS}-overflow__summary` }, trigger),
|
|
6310
|
+
h("div", { className: `${CLS}-overflow__menu` }, items)
|
|
6311
|
+
);
|
|
6312
|
+
});
|
|
6207
6313
|
registerComponent("form", (el, ctx) => {
|
|
6208
6314
|
const children = renderElements(el.property?.elements, ctx);
|
|
6209
6315
|
const className = `${CLS}-form`;
|
package/dist/index.js
CHANGED
|
@@ -1257,6 +1257,13 @@ var BASE_STYLES_CSS = `/**
|
|
|
1257
1257
|
word-break: break-word;
|
|
1258
1258
|
vertical-align: middle;
|
|
1259
1259
|
}
|
|
1260
|
+
/* \u524D\u7F00\u56FE\u6807\uFF08markdown.icon\uFF09\uFF1A\u4E0E\u9996\u884C\u6587\u5B57\u5782\u76F4\u5C45\u4E2D\uFF0C\u53F3\u4FA7\u7559 4px\u3002
|
|
1261
|
+
\u5BB9\u5668\u662F flex row\uFF0C\u56FE\u6807\u4F5C\u4E3A\u9996\u4E2A flex \u5B50\u9879\u53C2\u4E0E\u6392\u5E03\u3002 */
|
|
1262
|
+
.universal-card-markdown__icon {
|
|
1263
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
1264
|
+
flex-shrink: 0; margin-right: 4px;
|
|
1265
|
+
height: 1.6em;
|
|
1266
|
+
}
|
|
1260
1267
|
.universal-card-markdown__children {
|
|
1261
1268
|
flex: 1;
|
|
1262
1269
|
min-width: 0;
|
|
@@ -1412,6 +1419,32 @@ var BASE_STYLES_CSS = `/**
|
|
|
1412
1419
|
/* \u975E\u8DF3\u8F6C\u6309\u94AE\uFF1A\u4FDD\u7559\u5916\u89C2\uFF0C\u4F46\u4E0D\u53EF\u70B9\uFF08\u9ED8\u8BA4\u5149\u6807\u3001\u65E0 hover\u3001\u4E0D\u54CD\u5E94\u70B9\u51FB\uFF09 */
|
|
1413
1420
|
.universal-card-button--static { cursor: default; pointer-events: none; }
|
|
1414
1421
|
|
|
1422
|
+
/* ---- overflow \u6298\u53E0\u6309\u94AE\u7EC4 ---- */
|
|
1423
|
+
/* \u771F\u673A\u662F\u4E00\u4E2A\u300C\u2026\u300D\u56FE\u6807\u6309\u94AE\uFF0C\u70B9\u51FB\u5F39\u51FA\u9009\u9879\u83DC\u5355\u3002\u9759\u6001\u9884\u89C8\u53EA\u753B\u89E6\u53D1\u5668\uFF08--static \u4E0D\u53EF\u70B9\uFF09\u3002 */
|
|
1424
|
+
.universal-card-overflow { display: inline-flex; position: relative; vertical-align: middle; }
|
|
1425
|
+
.universal-card-overflow--static { display: inline-flex; }
|
|
1426
|
+
.universal-card-overflow__summary {
|
|
1427
|
+
list-style: none; cursor: pointer; display: inline-flex;
|
|
1428
|
+
}
|
|
1429
|
+
/* \u53BB\u6389 <summary> \u7684\u6D4F\u89C8\u5668\u9ED8\u8BA4\u4E09\u89D2\u6807\u8BB0 */
|
|
1430
|
+
.universal-card-overflow__summary::-webkit-details-marker { display: none; }
|
|
1431
|
+
.universal-card-overflow__summary::marker { content: ''; }
|
|
1432
|
+
/* \u83DC\u5355\uFF1A\u9ED8\u8BA4\u9690\u85CF\uFF0C<details open> \u65F6\u6D6E\u5728\u89E6\u53D1\u5668\u4E0B\u65B9 */
|
|
1433
|
+
.universal-card-overflow__menu {
|
|
1434
|
+
display: none;
|
|
1435
|
+
position: absolute; top: calc(100% + 4px); left: 0; z-index: 20;
|
|
1436
|
+
min-width: 120px; padding: 4px 0;
|
|
1437
|
+
background: #fff; border-radius: 6px;
|
|
1438
|
+
box-shadow: 0 4px 12px rgba(31, 35, 41, 0.15), 0 0 1px rgba(31, 35, 41, 0.2);
|
|
1439
|
+
}
|
|
1440
|
+
.universal-card-overflow[open] > .universal-card-overflow__menu { display: block; }
|
|
1441
|
+
.universal-card-overflow__item {
|
|
1442
|
+
display: block; padding: 6px 12px;
|
|
1443
|
+
font-size: 14px; line-height: 22px; color: #1f2329;
|
|
1444
|
+
text-decoration: none; white-space: nowrap; cursor: pointer;
|
|
1445
|
+
}
|
|
1446
|
+
.universal-card-overflow__item:hover { background: #f5f6f7; }
|
|
1447
|
+
|
|
1415
1448
|
/* ---- \u8868\u5355\uFF08\u9884\u89C8\uFF1A\u4EC5\u900F\u4F20\uFF0C\u65E0\u8868\u5355\u8BED\u4E49\uFF09 ---- */
|
|
1416
1449
|
.universal-card-form { display: flex; flex-direction: column; row-gap: 8px; }
|
|
1417
1450
|
.universal-card-form > * { width: 100%; }
|
|
@@ -5698,15 +5731,50 @@ function registerBuiltins() {
|
|
|
5698
5731
|
}
|
|
5699
5732
|
const childCtx = { ...ctx, textMetrics: { fontSize, lineHeight } };
|
|
5700
5733
|
const linesStyle = lineClampStyle(p.lines ?? p.textLines);
|
|
5734
|
+
const iconVNode = renderPrefixIcon(p.icon, ctx, fontSize);
|
|
5701
5735
|
return h(
|
|
5702
5736
|
"div",
|
|
5703
5737
|
{ className: `${CLS}-markdown`, style },
|
|
5738
|
+
iconVNode,
|
|
5704
5739
|
h("div", {
|
|
5705
5740
|
className: `${CLS}-markdown__children`,
|
|
5706
5741
|
style: Object.keys(linesStyle).length ? linesStyle : void 0
|
|
5707
5742
|
}, renderElements(p.elements, childCtx))
|
|
5708
5743
|
);
|
|
5709
5744
|
}
|
|
5745
|
+
function renderPrefixIcon(raw, ctx, fontSize) {
|
|
5746
|
+
if (!isRecord(raw)) return null;
|
|
5747
|
+
const inner = isRecord(raw.property) ? raw.property : raw;
|
|
5748
|
+
const tag = typeof raw.tag === "string" ? raw.tag : "standard_icon";
|
|
5749
|
+
const sizeProp = typeof inner.size === "string" ? inner.size : typeof raw.size === "string" ? raw.size : void 0;
|
|
5750
|
+
if (tag === "custom_icon") {
|
|
5751
|
+
const imgKey = typeof inner.img_key === "string" ? inner.img_key : typeof raw.img_key === "string" ? raw.img_key : void 0;
|
|
5752
|
+
if (!imgKey) return null;
|
|
5753
|
+
const src = resolveImageSrc({ img_key: imgKey }, ctx) ?? imgKey;
|
|
5754
|
+
const sizePx = sizeProp && /^\d/.test(sizeProp) ? Number(/^(\d+(?:\.\d+)?)/.exec(sizeProp)[1]) : fontSize;
|
|
5755
|
+
return h(
|
|
5756
|
+
"span",
|
|
5757
|
+
{ className: `${CLS}-markdown__icon` },
|
|
5758
|
+
h("img", {
|
|
5759
|
+
src,
|
|
5760
|
+
alt: "",
|
|
5761
|
+
style: { width: sizePx + "px", height: sizePx + "px", objectFit: "contain" }
|
|
5762
|
+
})
|
|
5763
|
+
);
|
|
5764
|
+
}
|
|
5765
|
+
const token = typeof inner.token === "string" ? inner.token : "";
|
|
5766
|
+
if (!token) return null;
|
|
5767
|
+
const iconNode = renderIcon({
|
|
5768
|
+
property: {
|
|
5769
|
+
token,
|
|
5770
|
+
color: typeof inner.color === "string" ? inner.color : void 0,
|
|
5771
|
+
// 未显式给 size 时跟随文本字号,避免回落到固定 16px 与文字不搭
|
|
5772
|
+
size: sizeProp ?? fontSize + "px"
|
|
5773
|
+
}
|
|
5774
|
+
}, ctx);
|
|
5775
|
+
if (!iconNode) return null;
|
|
5776
|
+
return h("span", { className: `${CLS}-markdown__icon` }, iconNode);
|
|
5777
|
+
}
|
|
5710
5778
|
registerComponent("markdown", MarkdownComponent);
|
|
5711
5779
|
registerComponent("markdown_v1", MarkdownComponent);
|
|
5712
5780
|
function lineClampStyle(lines) {
|
|
@@ -6034,8 +6102,9 @@ function registerBuiltins() {
|
|
|
6034
6102
|
const tip = extractText(p.hoverTips);
|
|
6035
6103
|
const borderNamed = p.border_color ?? p.borderColor;
|
|
6036
6104
|
const borderCustom = resolveCustomBorderLight(p);
|
|
6037
|
-
const
|
|
6038
|
-
const hasBorder =
|
|
6105
|
+
const borderColorResolved = (borderCustom ? resolveColor(borderCustom) : void 0) ?? resolveColor(borderNamed);
|
|
6106
|
+
const hasBorder = p.hasBorder === true || p.has_border === true;
|
|
6107
|
+
const borderColor = hasBorder ? borderColorResolved : void 0;
|
|
6039
6108
|
const cls = `${CLS}-interactive-container` + (clickable ? ` ${CLS}-interactive-container--action` : "") + (hasBorder && !borderColor ? ` ${CLS}-interactive-container--bordered` : "") + (disabled ? ` ${CLS}-interactive-container--disabled` : "");
|
|
6040
6109
|
const style = {};
|
|
6041
6110
|
const bg = propertyBackgroundColor(p);
|
|
@@ -6203,6 +6272,43 @@ function registerBuiltins() {
|
|
|
6203
6272
|
};
|
|
6204
6273
|
return fromList(p.actions) ?? fromList(p.behaviors) ?? (isRecord(p.value) ? p.value : null);
|
|
6205
6274
|
}
|
|
6275
|
+
registerComponent("overflow", (el, ctx) => {
|
|
6276
|
+
const p = el.property || {};
|
|
6277
|
+
const disabled = p.disabled === true;
|
|
6278
|
+
const options = Array.isArray(p.options) ? p.options : [];
|
|
6279
|
+
const widthTok = p.width ?? p.widthValue?.value;
|
|
6280
|
+
const block = widthTok === "fill";
|
|
6281
|
+
const triggerIcon = renderIcon(
|
|
6282
|
+
{ property: { token: "more_outlined", size: "14px" } },
|
|
6283
|
+
ctx
|
|
6284
|
+
);
|
|
6285
|
+
const triggerCls = `${CLS}-button ${CLS}-button--default ${CLS}-button--static ${CLS}-overflow__trigger` + (disabled ? ` ${CLS}-button--disabled` : "") + (block ? ` ${CLS}-button--block` : "");
|
|
6286
|
+
const trigger = triggerIcon ? h("span", { className: triggerCls }, h("span", { className: `${CLS}-button__icon` }, triggerIcon)) : h("span", { className: triggerCls }, "\xB7\xB7\xB7");
|
|
6287
|
+
const items = options.map((raw) => {
|
|
6288
|
+
const opt = isRecord(raw) ? raw : {};
|
|
6289
|
+
const textObj = opt.text;
|
|
6290
|
+
const label = (isRecord(textObj) && typeof textObj.content === "string" ? textObj.content : extractPlainText(textObj)) || extractPlainText(opt);
|
|
6291
|
+
const multi = isRecord(opt.multi_url) ? opt.multi_url : void 0;
|
|
6292
|
+
const href = resolveURL(multi?.url ?? opt.url);
|
|
6293
|
+
const itemCls = `${CLS}-overflow__item`;
|
|
6294
|
+
if (href && !disabled) {
|
|
6295
|
+
return h("a", { className: itemCls, href, target: "_blank", rel: "noopener" }, label);
|
|
6296
|
+
}
|
|
6297
|
+
return h("span", { className: itemCls }, label);
|
|
6298
|
+
});
|
|
6299
|
+
const style = {};
|
|
6300
|
+
if (p.margin) applyOuterMargin(style, p.margin);
|
|
6301
|
+
const styleProp = Object.keys(style).length ? { style } : {};
|
|
6302
|
+
if (!ctx.options.interactive) {
|
|
6303
|
+
return h("span", { className: `${CLS}-overflow ${CLS}-overflow--static`, ...styleProp }, trigger);
|
|
6304
|
+
}
|
|
6305
|
+
return h(
|
|
6306
|
+
"details",
|
|
6307
|
+
{ className: `${CLS}-overflow`, ...styleProp },
|
|
6308
|
+
h("summary", { className: `${CLS}-overflow__summary` }, trigger),
|
|
6309
|
+
h("div", { className: `${CLS}-overflow__menu` }, items)
|
|
6310
|
+
);
|
|
6311
|
+
});
|
|
6206
6312
|
registerComponent("form", (el, ctx) => {
|
|
6207
6313
|
const children = renderElements(el.property?.elements, ctx);
|
|
6208
6314
|
const className = `${CLS}-form`;
|
package/dist/styles.css
CHANGED
|
@@ -288,6 +288,13 @@
|
|
|
288
288
|
word-break: break-word;
|
|
289
289
|
vertical-align: middle;
|
|
290
290
|
}
|
|
291
|
+
/* 前缀图标(markdown.icon):与首行文字垂直居中,右侧留 4px。
|
|
292
|
+
容器是 flex row,图标作为首个 flex 子项参与排布。 */
|
|
293
|
+
.universal-card-markdown__icon {
|
|
294
|
+
display: inline-flex; align-items: center; justify-content: center;
|
|
295
|
+
flex-shrink: 0; margin-right: 4px;
|
|
296
|
+
height: 1.6em;
|
|
297
|
+
}
|
|
291
298
|
.universal-card-markdown__children {
|
|
292
299
|
flex: 1;
|
|
293
300
|
min-width: 0;
|
|
@@ -443,6 +450,32 @@
|
|
|
443
450
|
/* 非跳转按钮:保留外观,但不可点(默认光标、无 hover、不响应点击) */
|
|
444
451
|
.universal-card-button--static { cursor: default; pointer-events: none; }
|
|
445
452
|
|
|
453
|
+
/* ---- overflow 折叠按钮组 ---- */
|
|
454
|
+
/* 真机是一个「…」图标按钮,点击弹出选项菜单。静态预览只画触发器(--static 不可点)。 */
|
|
455
|
+
.universal-card-overflow { display: inline-flex; position: relative; vertical-align: middle; }
|
|
456
|
+
.universal-card-overflow--static { display: inline-flex; }
|
|
457
|
+
.universal-card-overflow__summary {
|
|
458
|
+
list-style: none; cursor: pointer; display: inline-flex;
|
|
459
|
+
}
|
|
460
|
+
/* 去掉 <summary> 的浏览器默认三角标记 */
|
|
461
|
+
.universal-card-overflow__summary::-webkit-details-marker { display: none; }
|
|
462
|
+
.universal-card-overflow__summary::marker { content: ''; }
|
|
463
|
+
/* 菜单:默认隐藏,<details open> 时浮在触发器下方 */
|
|
464
|
+
.universal-card-overflow__menu {
|
|
465
|
+
display: none;
|
|
466
|
+
position: absolute; top: calc(100% + 4px); left: 0; z-index: 20;
|
|
467
|
+
min-width: 120px; padding: 4px 0;
|
|
468
|
+
background: #fff; border-radius: 6px;
|
|
469
|
+
box-shadow: 0 4px 12px rgba(31, 35, 41, 0.15), 0 0 1px rgba(31, 35, 41, 0.2);
|
|
470
|
+
}
|
|
471
|
+
.universal-card-overflow[open] > .universal-card-overflow__menu { display: block; }
|
|
472
|
+
.universal-card-overflow__item {
|
|
473
|
+
display: block; padding: 6px 12px;
|
|
474
|
+
font-size: 14px; line-height: 22px; color: #1f2329;
|
|
475
|
+
text-decoration: none; white-space: nowrap; cursor: pointer;
|
|
476
|
+
}
|
|
477
|
+
.universal-card-overflow__item:hover { background: #f5f6f7; }
|
|
478
|
+
|
|
446
479
|
/* ---- 表单(预览:仅透传,无表单语义) ---- */
|
|
447
480
|
.universal-card-form { display: flex; flex-direction: column; row-gap: 8px; }
|
|
448
481
|
.universal-card-form > * { width: 100%; }
|