@open-feishu-card/renderer 0.3.3 → 0.3.5

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/index.cjs CHANGED
@@ -256,7 +256,7 @@ var HEADER_TEMPLATE = (() => {
256
256
  text: PALETTE[textException[n] || letter + "600"]
257
257
  };
258
258
  }
259
- out.default = { bg: "#f5f6f7", text: "#1f2329" };
259
+ out.default = { bg: "#ffffff", text: "#1f2329" };
260
260
  return out;
261
261
  })();
262
262
  var TEXT_FONT_COLOR_TOKEN = {
@@ -772,11 +772,12 @@ function applyOuterMargin(style, margin) {
772
772
  style.margin = mg;
773
773
  const { left, right } = horizontalMarginPx(margin);
774
774
  const inset = left + right;
775
- if (inset <= 0) return;
775
+ if (inset === 0) return;
776
776
  const w = style.width;
777
777
  if (w && /px$/i.test(w) && !w.includes("%")) return;
778
778
  if (!w || w === "100%" || w === "fill") {
779
- style.width = `calc(100% - ${inset}px)`;
779
+ style.width = inset > 0 ? `calc(100% - ${inset}px)` : `calc(100% + ${-inset}px)`;
780
+ if (inset < 0) style.maxWidth = "none";
780
781
  }
781
782
  }
782
783
  function resolveDimensionPx(direct, valueObj) {
@@ -996,6 +997,9 @@ var BASE_STYLES_CSS = `/**
996
997
  width: 100%;
997
998
  max-width: 605px;
998
999
  box-sizing: border-box;
1000
+ /* \u771F\u673A\u6309\u300C\u5361\u7247\u5BB9\u5668\u5BBD\u5EA6 > 320px\u300D\u533A\u5206\u5BBD/\u7A84\u5C4F\u6309\u94AE\u6863\u4F4D\uFF0C\u8FD9\u91CC\u7528\u5BB9\u5668\u67E5\u8BE2\u590D\u523B */
1001
+ container-type: inline-size;
1002
+ container-name: universal-card;
999
1003
  /* BEGIN PALETTE VARS (auto-generated from constants.ts PALETTE) */
1000
1004
  /* \u6B63\u6587 color:var(--O400) \u7B49\u4F9D\u8D56\u8FD9\u4E9B\u53D8\u91CF\uFF1B\u4E0E\u98DE\u4E66 :root light \u8272\u9636\u5BF9\u9F50 */
1001
1005
  --B50: #f0f4ff;
@@ -1178,6 +1182,8 @@ var BASE_STYLES_CSS = `/**
1178
1182
  /* \u5BF9\u9F50\u98DE\u4E66\uFF1Amax(100%, 605px) 140px\uFF0C\u7A84\u5361\u4E0D\u628A\u9AD8\u5149\u62C9\u7A00 */
1179
1183
  background-size: max(100%, 605px) 140px;
1180
1184
  }
1185
+ /* default/disabled \u6A21\u677F\u771F\u673A\u4E0D\u8BBE\u80CC\u666F\u8272\uFF08bg_color \u4E3A\u7A7A\u4E32\uFF09\uFF0C\u6B64\u65F6 header \u4E0D\u7559\u5E95\u90E8\u5185\u8FB9\u8DDD */
1186
+ .universal-card-header__bg--no-template { padding-bottom: 0; }
1181
1187
  /* \u5185\u5BB9\u884C\uFF1A\u5DE6\u4FA7\u56FE\u6807 + \u53F3\u4FA7\u6807\u9898\u533A\uFF08\u5BF9\u9F50\u7F51\u9875\u7248 header__content = row\uFF09 */
1182
1188
  .universal-card-header__content {
1183
1189
  width: 100%;
@@ -1244,7 +1250,9 @@ var BASE_STYLES_CSS = `/**
1244
1250
  column-gap: 12px;
1245
1251
  align-items: flex-start;
1246
1252
  }
1247
- .universal-card-body > * { width: 100%; box-sizing: border-box; }
1253
+ /* \u4EA4\u4E92\u63A7\u4EF6\u4E0D\u53C2\u4E0E\u300C\u5B50\u5143\u7D20\u6491\u6EE1\u300D\uFF1A\u6309\u94AE\u7684\u5BBD\u5EA6\u7531\u771F\u673A\u89C4\u5219\u51B3\u5B9A\uFF08\u89C1 .universal-card-button--auto\uFF09\uFF0C
1254
+ \u82E5\u88AB\u8FD9\u6761 blanket \u89C4\u5219\u62C9\u5230 100%\uFF0C\u7A84\u5C4F/\u5BBD\u5C4F\u5206\u6863\u5C31\u5931\u6548\u4E86\u3002 */
1255
+ .universal-card-body > *:not(.universal-card-button) { width: 100%; box-sizing: border-box; }
1248
1256
 
1249
1257
  /* ---- markdown \u6BB5\u843D ---- */
1250
1258
  /* \u5BF9\u9F50\u7F51\u9875\u7248\uFF1Aline-height \u9ED8\u8BA4 1.6\uFF1B\u5177\u4F53\u5B57\u53F7/\u884C\u9AD8\u7531\u7EC4\u4EF6\u5185\u8054 style \u6309 text_size \u7ED9\u51FA */
@@ -1331,8 +1339,11 @@ var BASE_STYLES_CSS = `/**
1331
1339
  \u8FD9\u91CC\u4E0D\u518D\u7ED9\u76F8\u90BB\u5B50\u5143\u7D20\u8BBE margin-top\u2014\u2014\u5426\u5219\u4E0E row-gap \u53E0\u52A0\uFF0C\u95F4\u8DDD\u7FFB\u500D\u3002 */
1332
1340
 
1333
1341
  /* ---- \u56FE\u7247 ---- */
1342
+ /* \u771F\u673A\u7F51\u9875\u7248 .universal-card-image__host{border-radius:0}\uFF1A\u56FE\u7247\u9ED8\u8BA4\u76F4\u89D2\uFF0C
1343
+ \u5706\u89D2\u53EA\u7531 DSL/RAW \u7684 corner_radius \u5185\u8054\u7ED9\u51FA\uFF08\u89C1 img \u7EC4\u4EF6\uFF09\u3002
1344
+ \u4E4B\u524D\u8FD9\u91CC\u5199\u6B7B 4px\uFF0C\u5BFC\u81F4\u6CA1\u5199 corner_radius \u7684\u56FE\u5728\u6E32\u67D3\u5668\u91CC\u56DB\u89D2\u88AB\u5706\u6389\uFF0C\u4E0E\u771F\u673A\u4E0D\u7B26\u3002 */
1334
1345
  .universal-card-image__wrapper { display: flex; max-width: 100%; }
1335
- .universal-card-image__host { max-width: 100%; height: auto; object-fit: cover; border-radius: 4px; }
1346
+ .universal-card-image__host { max-width: 100%; height: auto; object-fit: cover; border-radius: 0; }
1336
1347
  .universal-card-image__placeholder {
1337
1348
  display: inline-flex; align-items: center; justify-content: center;
1338
1349
  min-width: 80px; min-height: 48px; padding: 8px 12px;
@@ -1361,10 +1372,14 @@ var BASE_STYLES_CSS = `/**
1361
1372
  flex-shrink: 0; height: 1.2em; color: inherit;
1362
1373
  }
1363
1374
  .universal-card-button__icon .universal-card-icon { color: inherit; }
1364
- /* \u5BBD\u5EA6\uFF1A\u5BF9\u9F50\u771F\u673A\u2014\u2014body > * { width:100% }\u3001\u5217 flex stretch \u4F1A\u628A\u6309\u94AE\u6491\u6EE1\u6240\u5728\u884C/\u5217\u3002
1365
- \u4E0D\u518D\u5F3A\u5236 width:auto\uFF08\u90A3\u662F\u7F51\u9875\u7248\u89C2\u611F\uFF1B\u771F\u673A\u72EC\u7ACB\u6210\u884C\u7684\u6309\u94AE\u9ED8\u8BA4\u5360\u6EE1\u6574\u884C\uFF09\u3002
1366
- width:"fill" \u663E\u5F0F\u6302 --block\uFF0C\u4E0E\u7F3A\u7701\u6491\u6EE1\u540C\u5BBD\uFF0C\u5E76\u4F9B margin calc \u8BC6\u522B\u3002 */
1367
- .universal-card-button--block { width: 100%; }
1375
+ /* \u5BBD\u5EA6\uFF1A\u5BF9\u9F50\u771F\u673A ud__button \u7684 isWide \u5206\u6863\uFF08\u771F\u673A\u6309\u300C\u5361\u7247\u5BB9\u5668\u5BBD\u5EA6 > 320px\u300D\u5224\u5B9A\uFF09\uFF1A
1376
+ \u5BBD\u5C4F \u2192 \u81EA\u9002\u5E94\u5185\u5BB9\u5BBD\uFF08--auto\uFF09\uFF1B\u7A84\u5C4F\uFF08\u2264320px\uFF09\u2192 \u6491\u6EE1\u6574\u884C\uFF08\u4E0B\u65B9 @container \u89C4\u5219\u8986\u76D6\uFF09\u3002
1377
+ text \u65CF\u4E0E width:"fill" \u6052\u5B9A\u6491\u6EE1\uFF08--block\uFF09\u3002
1378
+ align-self:flex-start \u2014\u2014 \u7236\u7EA7\uFF08body/form/column\uFF09\u9ED8\u8BA4 align-items:stretch\uFF0C
1379
+ \u53EA\u5199 width:auto \u4ECD\u4F1A\u88AB\u62C9\u4F38\uFF0C\u5FC5\u987B\u540C\u65F6\u963B\u6B62\u62C9\u4F38\u3002 */
1380
+ .universal-card-button { min-width: 58px; align-self: flex-start; }
1381
+ .universal-card-button--block { width: 100%; min-width: unset; }
1382
+ .universal-card-button--auto { width: auto; }
1368
1383
 
1369
1384
  /* \u2014\u2014 outlined \u63CF\u8FB9\u65CF \u2014\u2014 */
1370
1385
  /* default\uFF1A\u7070\u63CF\u8FB9 + \u767D\u5E95 + \u6DF1\u5B57\uFF08\u672A\u52A0\u53D8\u4F53\u7C7B\u7684\u88F8 .universal-card-button \u5DF2\u662F\u767D\u5E95\u6DF1\u5B57\uFF0C
@@ -1391,6 +1406,8 @@ var BASE_STYLES_CSS = `/**
1391
1406
  .universal-card-button--danger_text {
1392
1407
  border-color: transparent; background: transparent; padding: 4px 8px;
1393
1408
  justify-content: flex-start;
1409
+ /* \u771F\u673A text \u65CF\u6309\u94AE\u4E0D\u8BBE\u6700\u5C0F\u5BBD\u5EA6 */
1410
+ min-width: unset;
1394
1411
  }
1395
1412
  .universal-card-button--text { color: #1f2329; }
1396
1413
  .universal-card-button--primary_text { color: #1456f0; }
@@ -1426,6 +1443,8 @@ var BASE_STYLES_CSS = `/**
1426
1443
  .universal-card-overflow--static { display: inline-flex; }
1427
1444
  .universal-card-overflow__summary {
1428
1445
  list-style: none; cursor: pointer; display: inline-flex;
1446
+ /* \u771F\u673A\u6298\u53E0\u6309\u94AE\u7684\u6700\u5C0F\u5BBD\u5EA6\u662F 32px\uFF08\u666E\u901A\u6309\u94AE\u662F 58px\uFF09 */
1447
+ min-width: 32px;
1429
1448
  }
1430
1449
  /* \u53BB\u6389 <summary> \u7684\u6D4F\u89C8\u5668\u9ED8\u8BA4\u4E09\u89D2\u6807\u8BB0 */
1431
1450
  .universal-card-overflow__summary::-webkit-details-marker { display: none; }
@@ -1447,8 +1466,9 @@ var BASE_STYLES_CSS = `/**
1447
1466
  .universal-card-overflow__item:hover { background: #f5f6f7; }
1448
1467
 
1449
1468
  /* ---- \u8868\u5355\uFF08\u9884\u89C8\uFF1A\u4EC5\u900F\u4F20\uFF0C\u65E0\u8868\u5355\u8BED\u4E49\uFF09 ---- */
1450
- .universal-card-form { display: flex; flex-direction: column; row-gap: 8px; }
1451
- .universal-card-form > * { width: 100%; }
1469
+ /* row-gap 12px\uFF1A\u5BF9\u9F50\u771F\u673A schema 2.0 \u8868\u5355\u5BB9\u5668 */
1470
+ .universal-card-form { display: flex; flex-direction: column; row-gap: 12px; }
1471
+ .universal-card-form > *:not(.universal-card-button) { width: 100%; }
1452
1472
  /* input / select\uFF1A\u9759\u6001\u9884\u89C8\u662F\u53EA\u8BFB\u6846\uFF1Binteractive \u53BB\u6389 --static\uFF0C\u6210\u4E3A\u53EF\u8F93\u5165\u63A7\u4EF6 */
1453
1473
  .universal-card-input,
1454
1474
  .universal-card-input--static {
@@ -1456,6 +1476,13 @@ var BASE_STYLES_CSS = `/**
1456
1476
  font-family: inherit; font-size: 14px; line-height: 20px;
1457
1477
  background: #fff; border: 1px solid #dee0e3; border-radius: 6px;
1458
1478
  color: #1f2329; width: 100%;
1479
+ /* \u771F\u673A input \u9ED8\u8BA4 max-width:282px\uFF08width:"fill" \u65F6\u7531\u5185\u8054\u6837\u5F0F\u653E\u5F00\uFF09 */
1480
+ max-width: 282px;
1481
+ }
1482
+ /* select type:"text"\uFF1A\u771F\u673A\u662F\u65E0\u8FB9\u6846\u3001\u5185\u5BB9\u81EA\u9002\u5E94\u5BBD\u7684\u4E0B\u62C9 */
1483
+ .universal-card-input--text {
1484
+ border-color: transparent; background: transparent;
1485
+ min-height: 26px; padding: 1px 7px; width: auto;
1459
1486
  }
1460
1487
  .universal-card-input--static {
1461
1488
  color: #8f959e; background: #f5f6f7;
@@ -2123,6 +2150,13 @@ var BASE_STYLES_CSS = `/**
2123
2150
  from { opacity: 1; transform: translateY(0); }
2124
2151
  to { opacity: 0; transform: translateY(-100%); margin-bottom: 0; }
2125
2152
  }
2153
+
2154
+ /* ---- \u7A84\u5C4F\u5206\u6863\uFF08\u771F\u673A isWide\uFF1A\u5361\u7247\u5BB9\u5668\u5BBD\u5EA6 > 320px \u4E3A\u5BBD\u5C4F\uFF09 ----
2155
+ \u771F\u673A\u89C4\u5219\uFF1Adefault/primary/primary_filled/danger/danger_filled/laser \u6309\u94AE\u5728\u7A84\u5C4F\u6491\u6EE1\u6574\u884C\uFF0C
2156
+ \u5BBD\u5C4F\u5219\u81EA\u9002\u5E94\u5185\u5BB9\u5BBD\u3002@container \u4E0D\u589E\u52A0\u9009\u62E9\u5668\u6743\u91CD\uFF0C\u9760\u6E90\u7801\u987A\u5E8F\u5728 --auto \u89C4\u5219\u4E4B\u540E\u8986\u76D6\u3002 */
2157
+ @container universal-card (max-width: 320px) {
2158
+ .universal-card-button--auto { width: 100%; }
2159
+ }
2126
2160
  `;
2127
2161
 
2128
2162
  // src/icon-font.ts
@@ -5690,6 +5724,8 @@ function registerBuiltins() {
5690
5724
  ),
5691
5725
  subtitleVNode
5692
5726
  ];
5727
+ const tplKey2 = p.template || "default";
5728
+ const noTemplate = tplKey2 === "default" || tplKey2 === "disabled";
5693
5729
  return h(
5694
5730
  "div",
5695
5731
  {
@@ -5699,7 +5735,7 @@ function registerBuiltins() {
5699
5735
  h(
5700
5736
  "div",
5701
5737
  {
5702
- className: `${CLS}-header__bg`,
5738
+ className: `${CLS}-header__bg${noTemplate ? ` ${CLS}-header__bg--no-template` : ""}`,
5703
5739
  // 内联 base64 高光纹理;图宽=header 宽使亮带居中;padding 透传 DSL(默认 12px)
5704
5740
  style: (() => {
5705
5741
  const s = { backgroundImage: `url(${HEADER_BG_LIGHT})` };
@@ -6232,12 +6268,26 @@ function registerBuiltins() {
6232
6268
  const url = actionUrl || resolveURL(p.url) || p.behaviors?.[0]?.default_url?.url;
6233
6269
  const wv = p.widthValue;
6234
6270
  const widthTok = p.width ?? wv?.value;
6235
- const block = widthTok === "fill";
6236
- const base = `${CLS}-button ${CLS}-button--${type}${block ? ` ${CLS}-button--block` : ""}`;
6271
+ const isFill = widthTok === "fill";
6272
+ const pxWidth = /^\d+(\.\d+)?px$/i.test(String(widthTok ?? "")) ? String(widthTok) : "";
6273
+ const textFamily = type === "text" || type === "primary_text" || type === "danger_text";
6274
+ const block = isFill || textFamily;
6275
+ const auto = !block && !pxWidth;
6276
+ const base = `${CLS}-button ${CLS}-button--${type}` + (block ? ` ${CLS}-button--block` : "") + (auto ? ` ${CLS}-button--auto` : "");
6237
6277
  const style = {};
6238
- if (p.margin) {
6239
- style.width = "100%";
6240
- applyOuterMargin(style, p.margin);
6278
+ if (pxWidth) {
6279
+ style.width = pxWidth;
6280
+ if (p.margin) applyOuterMargin(style, p.margin);
6281
+ } else if (p.margin) {
6282
+ if (block) {
6283
+ style.width = "100%";
6284
+ applyOuterMargin(style, p.margin);
6285
+ } else {
6286
+ applyOuterMargin(style, p.margin);
6287
+ const { left, right } = horizontalMarginPx(p.margin);
6288
+ const inset = left + right;
6289
+ if (inset > 0) style.maxWidth = `calc(100% - ${inset}px)`;
6290
+ }
6241
6291
  }
6242
6292
  const styleProp = Object.keys(style).length ? { style } : {};
6243
6293
  const extra = p;
@@ -6318,15 +6368,53 @@ function registerBuiltins() {
6318
6368
  const name = typeof el.property?.name === "string" ? el.property.name : "";
6319
6369
  return h("form", { className, "data-feishu-form": name }, children);
6320
6370
  });
6371
+ function fieldWidthStyle(p, kind) {
6372
+ const wv = p.widthValue;
6373
+ const raw = String(p.width ?? wv?.value ?? "");
6374
+ const style = {};
6375
+ if (/^\d+(\.\d+)?px$/i.test(raw)) {
6376
+ style.width = raw;
6377
+ style.maxWidth = "100%";
6378
+ return style;
6379
+ }
6380
+ if (raw === "fill") {
6381
+ style.width = "100%";
6382
+ style.maxWidth = "none";
6383
+ return style;
6384
+ }
6385
+ if (kind === "select") {
6386
+ if (raw === "auto") {
6387
+ style.width = "100%";
6388
+ style.maxWidth = "100%";
6389
+ return style;
6390
+ }
6391
+ if (p.type === "text") {
6392
+ style.width = "auto";
6393
+ style.maxWidth = "100%";
6394
+ return style;
6395
+ }
6396
+ style.width = "282px";
6397
+ style.maxWidth = "100%";
6398
+ return style;
6399
+ }
6400
+ style.width = "100%";
6401
+ style.maxWidth = "282px";
6402
+ return style;
6403
+ }
6321
6404
  function renderStaticField(el) {
6322
6405
  const p = el.property || {};
6323
6406
  const ph = extractPlainText(p.placeholder) || "";
6324
- return h("div", { className: `${CLS}-input ${CLS}-input--static` }, ph);
6407
+ const kind = isSelectTag(el.tag) ? "select" : "input";
6408
+ const cls = `${CLS}-input ${CLS}-input--static` + (kind === "select" && p.type === "text" ? ` ${CLS}-input--text` : "");
6409
+ return h("div", { className: cls, style: fieldWidthStyle(p, kind) }, ph);
6325
6410
  }
6326
6411
  function fieldText(value) {
6327
6412
  if (typeof value === "string") return value;
6328
6413
  return extractPlainText(value);
6329
6414
  }
6415
+ function isSelectTag(tag) {
6416
+ return tag === "select_static" || tag === "multi_select_static" || tag === "select_person" || tag === "multi_select_person";
6417
+ }
6330
6418
  function renderInteractiveField(el) {
6331
6419
  const p = el.property || {};
6332
6420
  const ph = extractPlainText(p.placeholder) || "";
@@ -6334,13 +6422,15 @@ function registerBuiltins() {
6334
6422
  const nameProp = name ? { name } : {};
6335
6423
  const callback = readCallbackValue(p);
6336
6424
  const actionProp = callback ? { "data-feishu-action": JSON.stringify(callback), "data-feishu-tag": el.tag } : {};
6337
- if (el.tag === "select_static" || el.tag === "multi_select_static") {
6425
+ if (isSelectTag(el.tag)) {
6338
6426
  const initial = p.initial_option ?? p.initialOption;
6339
6427
  const options = Array.isArray(p.options) ? p.options : [];
6428
+ const cls = `${CLS}-input` + (p.type === "text" ? ` ${CLS}-input--text` : "");
6340
6429
  return h("select", {
6341
- className: `${CLS}-input`,
6430
+ className: cls,
6431
+ style: fieldWidthStyle(p, "select"),
6342
6432
  ...nameProp,
6343
- ...el.tag === "multi_select_static" ? { multiple: true } : {},
6433
+ ...el.tag === "multi_select_static" || el.tag === "multi_select_person" ? { multiple: true } : {},
6344
6434
  ...actionProp
6345
6435
  }, [
6346
6436
  h("option", { value: "" }, ph),
@@ -6359,6 +6449,7 @@ function registerBuiltins() {
6359
6449
  const inputType = el.tag === "date_picker" ? "date" : el.tag === "picker_time" ? "time" : "text";
6360
6450
  return h("input", {
6361
6451
  className: `${CLS}-input`,
6452
+ style: fieldWidthStyle(p, "input"),
6362
6453
  type: inputType,
6363
6454
  placeholder: ph,
6364
6455
  value: typeof def === "string" ? def : "",
package/dist/index.js CHANGED
@@ -255,7 +255,7 @@ var HEADER_TEMPLATE = (() => {
255
255
  text: PALETTE[textException[n] || letter + "600"]
256
256
  };
257
257
  }
258
- out.default = { bg: "#f5f6f7", text: "#1f2329" };
258
+ out.default = { bg: "#ffffff", text: "#1f2329" };
259
259
  return out;
260
260
  })();
261
261
  var TEXT_FONT_COLOR_TOKEN = {
@@ -771,11 +771,12 @@ function applyOuterMargin(style, margin) {
771
771
  style.margin = mg;
772
772
  const { left, right } = horizontalMarginPx(margin);
773
773
  const inset = left + right;
774
- if (inset <= 0) return;
774
+ if (inset === 0) return;
775
775
  const w = style.width;
776
776
  if (w && /px$/i.test(w) && !w.includes("%")) return;
777
777
  if (!w || w === "100%" || w === "fill") {
778
- style.width = `calc(100% - ${inset}px)`;
778
+ style.width = inset > 0 ? `calc(100% - ${inset}px)` : `calc(100% + ${-inset}px)`;
779
+ if (inset < 0) style.maxWidth = "none";
779
780
  }
780
781
  }
781
782
  function resolveDimensionPx(direct, valueObj) {
@@ -995,6 +996,9 @@ var BASE_STYLES_CSS = `/**
995
996
  width: 100%;
996
997
  max-width: 605px;
997
998
  box-sizing: border-box;
999
+ /* \u771F\u673A\u6309\u300C\u5361\u7247\u5BB9\u5668\u5BBD\u5EA6 > 320px\u300D\u533A\u5206\u5BBD/\u7A84\u5C4F\u6309\u94AE\u6863\u4F4D\uFF0C\u8FD9\u91CC\u7528\u5BB9\u5668\u67E5\u8BE2\u590D\u523B */
1000
+ container-type: inline-size;
1001
+ container-name: universal-card;
998
1002
  /* BEGIN PALETTE VARS (auto-generated from constants.ts PALETTE) */
999
1003
  /* \u6B63\u6587 color:var(--O400) \u7B49\u4F9D\u8D56\u8FD9\u4E9B\u53D8\u91CF\uFF1B\u4E0E\u98DE\u4E66 :root light \u8272\u9636\u5BF9\u9F50 */
1000
1004
  --B50: #f0f4ff;
@@ -1177,6 +1181,8 @@ var BASE_STYLES_CSS = `/**
1177
1181
  /* \u5BF9\u9F50\u98DE\u4E66\uFF1Amax(100%, 605px) 140px\uFF0C\u7A84\u5361\u4E0D\u628A\u9AD8\u5149\u62C9\u7A00 */
1178
1182
  background-size: max(100%, 605px) 140px;
1179
1183
  }
1184
+ /* default/disabled \u6A21\u677F\u771F\u673A\u4E0D\u8BBE\u80CC\u666F\u8272\uFF08bg_color \u4E3A\u7A7A\u4E32\uFF09\uFF0C\u6B64\u65F6 header \u4E0D\u7559\u5E95\u90E8\u5185\u8FB9\u8DDD */
1185
+ .universal-card-header__bg--no-template { padding-bottom: 0; }
1180
1186
  /* \u5185\u5BB9\u884C\uFF1A\u5DE6\u4FA7\u56FE\u6807 + \u53F3\u4FA7\u6807\u9898\u533A\uFF08\u5BF9\u9F50\u7F51\u9875\u7248 header__content = row\uFF09 */
1181
1187
  .universal-card-header__content {
1182
1188
  width: 100%;
@@ -1243,7 +1249,9 @@ var BASE_STYLES_CSS = `/**
1243
1249
  column-gap: 12px;
1244
1250
  align-items: flex-start;
1245
1251
  }
1246
- .universal-card-body > * { width: 100%; box-sizing: border-box; }
1252
+ /* \u4EA4\u4E92\u63A7\u4EF6\u4E0D\u53C2\u4E0E\u300C\u5B50\u5143\u7D20\u6491\u6EE1\u300D\uFF1A\u6309\u94AE\u7684\u5BBD\u5EA6\u7531\u771F\u673A\u89C4\u5219\u51B3\u5B9A\uFF08\u89C1 .universal-card-button--auto\uFF09\uFF0C
1253
+ \u82E5\u88AB\u8FD9\u6761 blanket \u89C4\u5219\u62C9\u5230 100%\uFF0C\u7A84\u5C4F/\u5BBD\u5C4F\u5206\u6863\u5C31\u5931\u6548\u4E86\u3002 */
1254
+ .universal-card-body > *:not(.universal-card-button) { width: 100%; box-sizing: border-box; }
1247
1255
 
1248
1256
  /* ---- markdown \u6BB5\u843D ---- */
1249
1257
  /* \u5BF9\u9F50\u7F51\u9875\u7248\uFF1Aline-height \u9ED8\u8BA4 1.6\uFF1B\u5177\u4F53\u5B57\u53F7/\u884C\u9AD8\u7531\u7EC4\u4EF6\u5185\u8054 style \u6309 text_size \u7ED9\u51FA */
@@ -1330,8 +1338,11 @@ var BASE_STYLES_CSS = `/**
1330
1338
  \u8FD9\u91CC\u4E0D\u518D\u7ED9\u76F8\u90BB\u5B50\u5143\u7D20\u8BBE margin-top\u2014\u2014\u5426\u5219\u4E0E row-gap \u53E0\u52A0\uFF0C\u95F4\u8DDD\u7FFB\u500D\u3002 */
1331
1339
 
1332
1340
  /* ---- \u56FE\u7247 ---- */
1341
+ /* \u771F\u673A\u7F51\u9875\u7248 .universal-card-image__host{border-radius:0}\uFF1A\u56FE\u7247\u9ED8\u8BA4\u76F4\u89D2\uFF0C
1342
+ \u5706\u89D2\u53EA\u7531 DSL/RAW \u7684 corner_radius \u5185\u8054\u7ED9\u51FA\uFF08\u89C1 img \u7EC4\u4EF6\uFF09\u3002
1343
+ \u4E4B\u524D\u8FD9\u91CC\u5199\u6B7B 4px\uFF0C\u5BFC\u81F4\u6CA1\u5199 corner_radius \u7684\u56FE\u5728\u6E32\u67D3\u5668\u91CC\u56DB\u89D2\u88AB\u5706\u6389\uFF0C\u4E0E\u771F\u673A\u4E0D\u7B26\u3002 */
1333
1344
  .universal-card-image__wrapper { display: flex; max-width: 100%; }
1334
- .universal-card-image__host { max-width: 100%; height: auto; object-fit: cover; border-radius: 4px; }
1345
+ .universal-card-image__host { max-width: 100%; height: auto; object-fit: cover; border-radius: 0; }
1335
1346
  .universal-card-image__placeholder {
1336
1347
  display: inline-flex; align-items: center; justify-content: center;
1337
1348
  min-width: 80px; min-height: 48px; padding: 8px 12px;
@@ -1360,10 +1371,14 @@ var BASE_STYLES_CSS = `/**
1360
1371
  flex-shrink: 0; height: 1.2em; color: inherit;
1361
1372
  }
1362
1373
  .universal-card-button__icon .universal-card-icon { color: inherit; }
1363
- /* \u5BBD\u5EA6\uFF1A\u5BF9\u9F50\u771F\u673A\u2014\u2014body > * { width:100% }\u3001\u5217 flex stretch \u4F1A\u628A\u6309\u94AE\u6491\u6EE1\u6240\u5728\u884C/\u5217\u3002
1364
- \u4E0D\u518D\u5F3A\u5236 width:auto\uFF08\u90A3\u662F\u7F51\u9875\u7248\u89C2\u611F\uFF1B\u771F\u673A\u72EC\u7ACB\u6210\u884C\u7684\u6309\u94AE\u9ED8\u8BA4\u5360\u6EE1\u6574\u884C\uFF09\u3002
1365
- width:"fill" \u663E\u5F0F\u6302 --block\uFF0C\u4E0E\u7F3A\u7701\u6491\u6EE1\u540C\u5BBD\uFF0C\u5E76\u4F9B margin calc \u8BC6\u522B\u3002 */
1366
- .universal-card-button--block { width: 100%; }
1374
+ /* \u5BBD\u5EA6\uFF1A\u5BF9\u9F50\u771F\u673A ud__button \u7684 isWide \u5206\u6863\uFF08\u771F\u673A\u6309\u300C\u5361\u7247\u5BB9\u5668\u5BBD\u5EA6 > 320px\u300D\u5224\u5B9A\uFF09\uFF1A
1375
+ \u5BBD\u5C4F \u2192 \u81EA\u9002\u5E94\u5185\u5BB9\u5BBD\uFF08--auto\uFF09\uFF1B\u7A84\u5C4F\uFF08\u2264320px\uFF09\u2192 \u6491\u6EE1\u6574\u884C\uFF08\u4E0B\u65B9 @container \u89C4\u5219\u8986\u76D6\uFF09\u3002
1376
+ text \u65CF\u4E0E width:"fill" \u6052\u5B9A\u6491\u6EE1\uFF08--block\uFF09\u3002
1377
+ align-self:flex-start \u2014\u2014 \u7236\u7EA7\uFF08body/form/column\uFF09\u9ED8\u8BA4 align-items:stretch\uFF0C
1378
+ \u53EA\u5199 width:auto \u4ECD\u4F1A\u88AB\u62C9\u4F38\uFF0C\u5FC5\u987B\u540C\u65F6\u963B\u6B62\u62C9\u4F38\u3002 */
1379
+ .universal-card-button { min-width: 58px; align-self: flex-start; }
1380
+ .universal-card-button--block { width: 100%; min-width: unset; }
1381
+ .universal-card-button--auto { width: auto; }
1367
1382
 
1368
1383
  /* \u2014\u2014 outlined \u63CF\u8FB9\u65CF \u2014\u2014 */
1369
1384
  /* default\uFF1A\u7070\u63CF\u8FB9 + \u767D\u5E95 + \u6DF1\u5B57\uFF08\u672A\u52A0\u53D8\u4F53\u7C7B\u7684\u88F8 .universal-card-button \u5DF2\u662F\u767D\u5E95\u6DF1\u5B57\uFF0C
@@ -1390,6 +1405,8 @@ var BASE_STYLES_CSS = `/**
1390
1405
  .universal-card-button--danger_text {
1391
1406
  border-color: transparent; background: transparent; padding: 4px 8px;
1392
1407
  justify-content: flex-start;
1408
+ /* \u771F\u673A text \u65CF\u6309\u94AE\u4E0D\u8BBE\u6700\u5C0F\u5BBD\u5EA6 */
1409
+ min-width: unset;
1393
1410
  }
1394
1411
  .universal-card-button--text { color: #1f2329; }
1395
1412
  .universal-card-button--primary_text { color: #1456f0; }
@@ -1425,6 +1442,8 @@ var BASE_STYLES_CSS = `/**
1425
1442
  .universal-card-overflow--static { display: inline-flex; }
1426
1443
  .universal-card-overflow__summary {
1427
1444
  list-style: none; cursor: pointer; display: inline-flex;
1445
+ /* \u771F\u673A\u6298\u53E0\u6309\u94AE\u7684\u6700\u5C0F\u5BBD\u5EA6\u662F 32px\uFF08\u666E\u901A\u6309\u94AE\u662F 58px\uFF09 */
1446
+ min-width: 32px;
1428
1447
  }
1429
1448
  /* \u53BB\u6389 <summary> \u7684\u6D4F\u89C8\u5668\u9ED8\u8BA4\u4E09\u89D2\u6807\u8BB0 */
1430
1449
  .universal-card-overflow__summary::-webkit-details-marker { display: none; }
@@ -1446,8 +1465,9 @@ var BASE_STYLES_CSS = `/**
1446
1465
  .universal-card-overflow__item:hover { background: #f5f6f7; }
1447
1466
 
1448
1467
  /* ---- \u8868\u5355\uFF08\u9884\u89C8\uFF1A\u4EC5\u900F\u4F20\uFF0C\u65E0\u8868\u5355\u8BED\u4E49\uFF09 ---- */
1449
- .universal-card-form { display: flex; flex-direction: column; row-gap: 8px; }
1450
- .universal-card-form > * { width: 100%; }
1468
+ /* row-gap 12px\uFF1A\u5BF9\u9F50\u771F\u673A schema 2.0 \u8868\u5355\u5BB9\u5668 */
1469
+ .universal-card-form { display: flex; flex-direction: column; row-gap: 12px; }
1470
+ .universal-card-form > *:not(.universal-card-button) { width: 100%; }
1451
1471
  /* input / select\uFF1A\u9759\u6001\u9884\u89C8\u662F\u53EA\u8BFB\u6846\uFF1Binteractive \u53BB\u6389 --static\uFF0C\u6210\u4E3A\u53EF\u8F93\u5165\u63A7\u4EF6 */
1452
1472
  .universal-card-input,
1453
1473
  .universal-card-input--static {
@@ -1455,6 +1475,13 @@ var BASE_STYLES_CSS = `/**
1455
1475
  font-family: inherit; font-size: 14px; line-height: 20px;
1456
1476
  background: #fff; border: 1px solid #dee0e3; border-radius: 6px;
1457
1477
  color: #1f2329; width: 100%;
1478
+ /* \u771F\u673A input \u9ED8\u8BA4 max-width:282px\uFF08width:"fill" \u65F6\u7531\u5185\u8054\u6837\u5F0F\u653E\u5F00\uFF09 */
1479
+ max-width: 282px;
1480
+ }
1481
+ /* select type:"text"\uFF1A\u771F\u673A\u662F\u65E0\u8FB9\u6846\u3001\u5185\u5BB9\u81EA\u9002\u5E94\u5BBD\u7684\u4E0B\u62C9 */
1482
+ .universal-card-input--text {
1483
+ border-color: transparent; background: transparent;
1484
+ min-height: 26px; padding: 1px 7px; width: auto;
1458
1485
  }
1459
1486
  .universal-card-input--static {
1460
1487
  color: #8f959e; background: #f5f6f7;
@@ -2122,6 +2149,13 @@ var BASE_STYLES_CSS = `/**
2122
2149
  from { opacity: 1; transform: translateY(0); }
2123
2150
  to { opacity: 0; transform: translateY(-100%); margin-bottom: 0; }
2124
2151
  }
2152
+
2153
+ /* ---- \u7A84\u5C4F\u5206\u6863\uFF08\u771F\u673A isWide\uFF1A\u5361\u7247\u5BB9\u5668\u5BBD\u5EA6 > 320px \u4E3A\u5BBD\u5C4F\uFF09 ----
2154
+ \u771F\u673A\u89C4\u5219\uFF1Adefault/primary/primary_filled/danger/danger_filled/laser \u6309\u94AE\u5728\u7A84\u5C4F\u6491\u6EE1\u6574\u884C\uFF0C
2155
+ \u5BBD\u5C4F\u5219\u81EA\u9002\u5E94\u5185\u5BB9\u5BBD\u3002@container \u4E0D\u589E\u52A0\u9009\u62E9\u5668\u6743\u91CD\uFF0C\u9760\u6E90\u7801\u987A\u5E8F\u5728 --auto \u89C4\u5219\u4E4B\u540E\u8986\u76D6\u3002 */
2156
+ @container universal-card (max-width: 320px) {
2157
+ .universal-card-button--auto { width: 100%; }
2158
+ }
2125
2159
  `;
2126
2160
 
2127
2161
  // src/icon-font.ts
@@ -5689,6 +5723,8 @@ function registerBuiltins() {
5689
5723
  ),
5690
5724
  subtitleVNode
5691
5725
  ];
5726
+ const tplKey2 = p.template || "default";
5727
+ const noTemplate = tplKey2 === "default" || tplKey2 === "disabled";
5692
5728
  return h(
5693
5729
  "div",
5694
5730
  {
@@ -5698,7 +5734,7 @@ function registerBuiltins() {
5698
5734
  h(
5699
5735
  "div",
5700
5736
  {
5701
- className: `${CLS}-header__bg`,
5737
+ className: `${CLS}-header__bg${noTemplate ? ` ${CLS}-header__bg--no-template` : ""}`,
5702
5738
  // 内联 base64 高光纹理;图宽=header 宽使亮带居中;padding 透传 DSL(默认 12px)
5703
5739
  style: (() => {
5704
5740
  const s = { backgroundImage: `url(${HEADER_BG_LIGHT})` };
@@ -6231,12 +6267,26 @@ function registerBuiltins() {
6231
6267
  const url = actionUrl || resolveURL(p.url) || p.behaviors?.[0]?.default_url?.url;
6232
6268
  const wv = p.widthValue;
6233
6269
  const widthTok = p.width ?? wv?.value;
6234
- const block = widthTok === "fill";
6235
- const base = `${CLS}-button ${CLS}-button--${type}${block ? ` ${CLS}-button--block` : ""}`;
6270
+ const isFill = widthTok === "fill";
6271
+ const pxWidth = /^\d+(\.\d+)?px$/i.test(String(widthTok ?? "")) ? String(widthTok) : "";
6272
+ const textFamily = type === "text" || type === "primary_text" || type === "danger_text";
6273
+ const block = isFill || textFamily;
6274
+ const auto = !block && !pxWidth;
6275
+ const base = `${CLS}-button ${CLS}-button--${type}` + (block ? ` ${CLS}-button--block` : "") + (auto ? ` ${CLS}-button--auto` : "");
6236
6276
  const style = {};
6237
- if (p.margin) {
6238
- style.width = "100%";
6239
- applyOuterMargin(style, p.margin);
6277
+ if (pxWidth) {
6278
+ style.width = pxWidth;
6279
+ if (p.margin) applyOuterMargin(style, p.margin);
6280
+ } else if (p.margin) {
6281
+ if (block) {
6282
+ style.width = "100%";
6283
+ applyOuterMargin(style, p.margin);
6284
+ } else {
6285
+ applyOuterMargin(style, p.margin);
6286
+ const { left, right } = horizontalMarginPx(p.margin);
6287
+ const inset = left + right;
6288
+ if (inset > 0) style.maxWidth = `calc(100% - ${inset}px)`;
6289
+ }
6240
6290
  }
6241
6291
  const styleProp = Object.keys(style).length ? { style } : {};
6242
6292
  const extra = p;
@@ -6317,15 +6367,53 @@ function registerBuiltins() {
6317
6367
  const name = typeof el.property?.name === "string" ? el.property.name : "";
6318
6368
  return h("form", { className, "data-feishu-form": name }, children);
6319
6369
  });
6370
+ function fieldWidthStyle(p, kind) {
6371
+ const wv = p.widthValue;
6372
+ const raw = String(p.width ?? wv?.value ?? "");
6373
+ const style = {};
6374
+ if (/^\d+(\.\d+)?px$/i.test(raw)) {
6375
+ style.width = raw;
6376
+ style.maxWidth = "100%";
6377
+ return style;
6378
+ }
6379
+ if (raw === "fill") {
6380
+ style.width = "100%";
6381
+ style.maxWidth = "none";
6382
+ return style;
6383
+ }
6384
+ if (kind === "select") {
6385
+ if (raw === "auto") {
6386
+ style.width = "100%";
6387
+ style.maxWidth = "100%";
6388
+ return style;
6389
+ }
6390
+ if (p.type === "text") {
6391
+ style.width = "auto";
6392
+ style.maxWidth = "100%";
6393
+ return style;
6394
+ }
6395
+ style.width = "282px";
6396
+ style.maxWidth = "100%";
6397
+ return style;
6398
+ }
6399
+ style.width = "100%";
6400
+ style.maxWidth = "282px";
6401
+ return style;
6402
+ }
6320
6403
  function renderStaticField(el) {
6321
6404
  const p = el.property || {};
6322
6405
  const ph = extractPlainText(p.placeholder) || "";
6323
- return h("div", { className: `${CLS}-input ${CLS}-input--static` }, ph);
6406
+ const kind = isSelectTag(el.tag) ? "select" : "input";
6407
+ const cls = `${CLS}-input ${CLS}-input--static` + (kind === "select" && p.type === "text" ? ` ${CLS}-input--text` : "");
6408
+ return h("div", { className: cls, style: fieldWidthStyle(p, kind) }, ph);
6324
6409
  }
6325
6410
  function fieldText(value) {
6326
6411
  if (typeof value === "string") return value;
6327
6412
  return extractPlainText(value);
6328
6413
  }
6414
+ function isSelectTag(tag) {
6415
+ return tag === "select_static" || tag === "multi_select_static" || tag === "select_person" || tag === "multi_select_person";
6416
+ }
6329
6417
  function renderInteractiveField(el) {
6330
6418
  const p = el.property || {};
6331
6419
  const ph = extractPlainText(p.placeholder) || "";
@@ -6333,13 +6421,15 @@ function registerBuiltins() {
6333
6421
  const nameProp = name ? { name } : {};
6334
6422
  const callback = readCallbackValue(p);
6335
6423
  const actionProp = callback ? { "data-feishu-action": JSON.stringify(callback), "data-feishu-tag": el.tag } : {};
6336
- if (el.tag === "select_static" || el.tag === "multi_select_static") {
6424
+ if (isSelectTag(el.tag)) {
6337
6425
  const initial = p.initial_option ?? p.initialOption;
6338
6426
  const options = Array.isArray(p.options) ? p.options : [];
6427
+ const cls = `${CLS}-input` + (p.type === "text" ? ` ${CLS}-input--text` : "");
6339
6428
  return h("select", {
6340
- className: `${CLS}-input`,
6429
+ className: cls,
6430
+ style: fieldWidthStyle(p, "select"),
6341
6431
  ...nameProp,
6342
- ...el.tag === "multi_select_static" ? { multiple: true } : {},
6432
+ ...el.tag === "multi_select_static" || el.tag === "multi_select_person" ? { multiple: true } : {},
6343
6433
  ...actionProp
6344
6434
  }, [
6345
6435
  h("option", { value: "" }, ph),
@@ -6358,6 +6448,7 @@ function registerBuiltins() {
6358
6448
  const inputType = el.tag === "date_picker" ? "date" : el.tag === "picker_time" ? "time" : "text";
6359
6449
  return h("input", {
6360
6450
  className: `${CLS}-input`,
6451
+ style: fieldWidthStyle(p, "input"),
6361
6452
  type: inputType,
6362
6453
  placeholder: ph,
6363
6454
  value: typeof def === "string" ? def : "",
package/dist/styles.css CHANGED
@@ -26,6 +26,9 @@
26
26
  width: 100%;
27
27
  max-width: 605px;
28
28
  box-sizing: border-box;
29
+ /* 真机按「卡片容器宽度 > 320px」区分宽/窄屏按钮档位,这里用容器查询复刻 */
30
+ container-type: inline-size;
31
+ container-name: universal-card;
29
32
  /* BEGIN PALETTE VARS (auto-generated from constants.ts PALETTE) */
30
33
  /* 正文 color:var(--O400) 等依赖这些变量;与飞书 :root light 色阶对齐 */
31
34
  --B50: #f0f4ff;
@@ -208,6 +211,8 @@
208
211
  /* 对齐飞书:max(100%, 605px) 140px,窄卡不把高光拉稀 */
209
212
  background-size: max(100%, 605px) 140px;
210
213
  }
214
+ /* default/disabled 模板真机不设背景色(bg_color 为空串),此时 header 不留底部内边距 */
215
+ .universal-card-header__bg--no-template { padding-bottom: 0; }
211
216
  /* 内容行:左侧图标 + 右侧标题区(对齐网页版 header__content = row) */
212
217
  .universal-card-header__content {
213
218
  width: 100%;
@@ -274,7 +279,9 @@
274
279
  column-gap: 12px;
275
280
  align-items: flex-start;
276
281
  }
277
- .universal-card-body > * { width: 100%; box-sizing: border-box; }
282
+ /* 交互控件不参与「子元素撑满」:按钮的宽度由真机规则决定(见 .universal-card-button--auto),
283
+ 若被这条 blanket 规则拉到 100%,窄屏/宽屏分档就失效了。 */
284
+ .universal-card-body > *:not(.universal-card-button) { width: 100%; box-sizing: border-box; }
278
285
 
279
286
  /* ---- markdown 段落 ---- */
280
287
  /* 对齐网页版:line-height 默认 1.6;具体字号/行高由组件内联 style 按 text_size 给出 */
@@ -361,8 +368,11 @@
361
368
  这里不再给相邻子元素设 margin-top——否则与 row-gap 叠加,间距翻倍。 */
362
369
 
363
370
  /* ---- 图片 ---- */
371
+ /* 真机网页版 .universal-card-image__host{border-radius:0}:图片默认直角,
372
+ 圆角只由 DSL/RAW 的 corner_radius 内联给出(见 img 组件)。
373
+ 之前这里写死 4px,导致没写 corner_radius 的图在渲染器里四角被圆掉,与真机不符。 */
364
374
  .universal-card-image__wrapper { display: flex; max-width: 100%; }
365
- .universal-card-image__host { max-width: 100%; height: auto; object-fit: cover; border-radius: 4px; }
375
+ .universal-card-image__host { max-width: 100%; height: auto; object-fit: cover; border-radius: 0; }
366
376
  .universal-card-image__placeholder {
367
377
  display: inline-flex; align-items: center; justify-content: center;
368
378
  min-width: 80px; min-height: 48px; padding: 8px 12px;
@@ -391,10 +401,14 @@
391
401
  flex-shrink: 0; height: 1.2em; color: inherit;
392
402
  }
393
403
  .universal-card-button__icon .universal-card-icon { color: inherit; }
394
- /* 宽度:对齐真机——body > * { width:100% }、列 flex stretch 会把按钮撑满所在行/列。
395
- 不再强制 width:auto(那是网页版观感;真机独立成行的按钮默认占满整行)。
396
- width:"fill" 显式挂 --block,与缺省撑满同宽,并供 margin calc 识别。 */
397
- .universal-card-button--block { width: 100%; }
404
+ /* 宽度:对齐真机 ud__button 的 isWide 分档(真机按「卡片容器宽度 > 320px」判定):
405
+ 宽屏 → 自适应内容宽(--auto);窄屏(≤320px)→ 撑满整行(下方 @container 规则覆盖)。
406
+ text 族与 width:"fill" 恒定撑满(--block)。
407
+ align-self:flex-start —— 父级(body/form/column)默认 align-items:stretch,
408
+ 只写 width:auto 仍会被拉伸,必须同时阻止拉伸。 */
409
+ .universal-card-button { min-width: 58px; align-self: flex-start; }
410
+ .universal-card-button--block { width: 100%; min-width: unset; }
411
+ .universal-card-button--auto { width: auto; }
398
412
 
399
413
  /* —— outlined 描边族 —— */
400
414
  /* default:灰描边 + 白底 + 深字(未加变体类的裸 .universal-card-button 已是白底深字,
@@ -421,6 +435,8 @@
421
435
  .universal-card-button--danger_text {
422
436
  border-color: transparent; background: transparent; padding: 4px 8px;
423
437
  justify-content: flex-start;
438
+ /* 真机 text 族按钮不设最小宽度 */
439
+ min-width: unset;
424
440
  }
425
441
  .universal-card-button--text { color: #1f2329; }
426
442
  .universal-card-button--primary_text { color: #1456f0; }
@@ -456,6 +472,8 @@
456
472
  .universal-card-overflow--static { display: inline-flex; }
457
473
  .universal-card-overflow__summary {
458
474
  list-style: none; cursor: pointer; display: inline-flex;
475
+ /* 真机折叠按钮的最小宽度是 32px(普通按钮是 58px) */
476
+ min-width: 32px;
459
477
  }
460
478
  /* 去掉 <summary> 的浏览器默认三角标记 */
461
479
  .universal-card-overflow__summary::-webkit-details-marker { display: none; }
@@ -477,8 +495,9 @@
477
495
  .universal-card-overflow__item:hover { background: #f5f6f7; }
478
496
 
479
497
  /* ---- 表单(预览:仅透传,无表单语义) ---- */
480
- .universal-card-form { display: flex; flex-direction: column; row-gap: 8px; }
481
- .universal-card-form > * { width: 100%; }
498
+ /* row-gap 12px:对齐真机 schema 2.0 表单容器 */
499
+ .universal-card-form { display: flex; flex-direction: column; row-gap: 12px; }
500
+ .universal-card-form > *:not(.universal-card-button) { width: 100%; }
482
501
  /* input / select:静态预览是只读框;interactive 去掉 --static,成为可输入控件 */
483
502
  .universal-card-input,
484
503
  .universal-card-input--static {
@@ -486,6 +505,13 @@
486
505
  font-family: inherit; font-size: 14px; line-height: 20px;
487
506
  background: #fff; border: 1px solid #dee0e3; border-radius: 6px;
488
507
  color: #1f2329; width: 100%;
508
+ /* 真机 input 默认 max-width:282px(width:"fill" 时由内联样式放开) */
509
+ max-width: 282px;
510
+ }
511
+ /* select type:"text":真机是无边框、内容自适应宽的下拉 */
512
+ .universal-card-input--text {
513
+ border-color: transparent; background: transparent;
514
+ min-height: 26px; padding: 1px 7px; width: auto;
489
515
  }
490
516
  .universal-card-input--static {
491
517
  color: #8f959e; background: #f5f6f7;
@@ -1153,3 +1179,10 @@
1153
1179
  from { opacity: 1; transform: translateY(0); }
1154
1180
  to { opacity: 0; transform: translateY(-100%); margin-bottom: 0; }
1155
1181
  }
1182
+
1183
+ /* ---- 窄屏分档(真机 isWide:卡片容器宽度 > 320px 为宽屏) ----
1184
+ 真机规则:default/primary/primary_filled/danger/danger_filled/laser 按钮在窄屏撑满整行,
1185
+ 宽屏则自适应内容宽。@container 不增加选择器权重,靠源码顺序在 --auto 规则之后覆盖。 */
1186
+ @container universal-card (max-width: 320px) {
1187
+ .universal-card-button--auto { width: 100%; }
1188
+ }