@yaoxiu/marketing-dsl 2.7.0 → 2.9.0

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.
@@ -1,4 +1,4 @@
1
- import { TRACK_EVENT_PATTERN, ALLOWED_EASINGS, DEFAULT_USER_FIELDS, USER_FIELD_LABELS, DSL_VERSION, ACTION_TYPES, NODE_TYPES, ALLOWED_STYLE_KEYS, CLOSE_POSITIONS } from '../chunk-DT3ZINDI.js';
1
+ import { TRACK_EVENT_PATTERN, ALLOWED_EASINGS, DEFAULT_USER_FIELDS, USER_FIELD_LABELS, AUTOPLAY_MIN_INTERVAL, DSL_VERSION, ACTION_TYPES, DERIVED_FIELDS, AUTOPLAY_FIELDS, NODE_TYPES, ALLOWED_STYLE_KEYS, CLOSE_POSITIONS } from '../chunk-B6BKOMWL.js';
2
2
 
3
3
  // src/docs/reconcile.ts
4
4
  function pickTokens(rows, columnIndex) {
@@ -316,9 +316,14 @@ countdown_end // \u5012\u8BA1\u65F6\u5F52\u96F6`
316
316
  "`close` \u7684 `extra.name`\uFF08`reason` \u4ECD\u662F\u5173\u95ED\u539F\u56E0\uFF09"
317
317
  ],
318
318
  [
319
- "\u5173\u95ED\u6309\u94AE\u7684 `action` \u91CC\uFF08\u548C `close` \u5199\u5728\u540C\u4E00\u4E2A `sequence`\uFF09",
319
+ "\u5173\u95ED\u6309\u94AE\u7684 `action` \u91CC\uFF08\u548C `close` \u5199\u5728\u540C\u4E00\u4E2A `sequence`\uFF0C\u4E14**\u4E0D\u8DF3\u8F6C**\uFF09",
320
320
  "**\u4E0D\u7B97\u70B9\u51FB**\uFF0C\u5E76\u8FDB\u90A3\u6761\u5173\u95ED",
321
321
  "`close` \u7684 `extra.name`"
322
+ ],
323
+ [
324
+ "\u4E3B\u6309\u94AE\u7684 `action` \u91CC\uFF08`sequence` \u91CC\u65E2\u6709 `close` / `closeAll`\uFF0C\u53C8\u6709 `navigate`\uFF09",
325
+ "**\u7B97\u4E00\u6761 `click`**\uFF08\u8DF3\u8D70\u4E86\u5C31\u662F\u8F6C\u5316\uFF09",
326
+ "`extra.name`\uFF1B\u8DF3\u8F6C\u5730\u5740\u5E76\u8FDB `extra.url`"
322
327
  ]
323
328
  ]
324
329
  },
@@ -330,7 +335,12 @@ countdown_end // \u5012\u8BA1\u65F6\u5F52\u96F6`
330
335
  {
331
336
  t: "note",
332
337
  tone: "warn",
333
- text: '**\u5173\u95ED\u52A8\u4F5C\u4E0D\u4EA7\u751F\u70B9\u51FB\u3002**\u53EA\u8981\u8FD9\u4E00\u4E0B\u6267\u884C\u4E86 `close` / `closeAll`\uFF0C\u5B83\u7684\u672C\u8D28\u5C31\u662F\u300C\u5173\u6389\u5B83\u300D\u800C\u4E0D\u662F\u300C\u70B9\u4E86\u5B83\u300D\u2014\u2014\u540E\u7AEF\u7B97\u70B9\u51FB\u7387\u65F6\u5206\u6BCD\u662F\u66DD\u5149\u3001\u5206\u5B50\u662F\u70B9\u51FB\uFF0C\u628A\u5173\u95ED\u7B97\u8FDB\u70B9\u51FB\u4F1A\u8BA9\u70B9\u51FB\u7387\u865A\u9AD8\u3002\u4F60\u914D\u5728\u5173\u95ED\u6309\u94AE\u4E0A\u7684\u57CB\u70B9\u540D\u4E0D\u4F1A\u4E22\uFF0C\u5B83\u8FDB\u4E86 `close` \u7684 `extra`\u3002\u60F3\u533A\u5206\u300C\u4ECE\u54EA\u4E2A\u5165\u53E3\u5173\u7684\u300D\uFF0C\u66F4\u63A8\u8350\u7528 `close` \u52A8\u4F5C\u7684 `reason`\uFF08\u5982 `reason: "user-dismiss"`\uFF09\u3002'
338
+ text: '**\u7EAF\u5173\u95ED\u52A8\u4F5C\u4E0D\u4EA7\u751F\u70B9\u51FB\u3002**\u8FD9\u4E00\u4E0B\u6267\u884C\u4E86 `close` / `closeAll`\u3001\u53C8\u6CA1\u6709\u8DF3\u8F6C\uFF0C\u5B83\u7684\u672C\u8D28\u5C31\u662F\u300C\u5173\u6389\u5B83\u300D\u800C\u4E0D\u662F\u300C\u70B9\u4E86\u5B83\u300D\u2014\u2014\u540E\u7AEF\u7B97\u70B9\u51FB\u7387\u65F6\u5206\u6BCD\u662F\u66DD\u5149\u3001\u5206\u5B50\u662F\u70B9\u51FB\uFF0C\u628A\u5173\u95ED\u7B97\u8FDB\u70B9\u51FB\u4F1A\u8BA9\u70B9\u51FB\u7387\u865A\u9AD8\u3002\u4F60\u914D\u5728\u5173\u95ED\u6309\u94AE\u4E0A\u7684\u57CB\u70B9\u540D\u4E0D\u4F1A\u4E22\uFF0C\u5B83\u8FDB\u4E86 `close` \u7684 `extra`\u3002\u60F3\u533A\u5206\u300C\u4ECE\u54EA\u4E2A\u5165\u53E3\u5173\u7684\u300D\uFF0C\u66F4\u63A8\u8350\u7528 `close` \u52A8\u4F5C\u7684 `reason`\uFF08\u5982 `reason: "user-dismiss"`\uFF09\u3002'
339
+ },
340
+ {
341
+ t: "note",
342
+ tone: "info",
343
+ text: "**\u4F46\u300C\u70B9\u4E86\u5C31\u8DF3\u8D70\u300D\u7684\u6309\u94AE\u5373\u4F7F\u5E26\u5173\u95ED\u4E5F\u7B97\u4E00\u6B21\u70B9\u51FB\u3002**\u4E3B CTA \u5E38\u5199\u6210 `sequence: [track, closeAll, navigate]`\uFF08\u8DF3\u8D70\u524D\u987A\u624B\u628A\u5F39\u7A97\u6536\u6389\uFF09\uFF0C\u540C\u4E00\u6B21\u624B\u52BF\u91CC\u53EA\u8981\u6709 `navigate`\uFF0C\u5C31\u7167\u5E38\u4E0A\u62A5\u4E00\u6761 `click`\u2014\u2014\u7528\u6237\u771F\u7684\u8DF3\u8FC7\u53BB\u4E86\uFF0C\u8FD9\u662F\u8F6C\u5316\u884C\u4E3A\uFF0C\u5173\u95ED\u53EA\u662F\u5B83\u7684\u526F\u4F5C\u7528\u3002\u8FD9\u6761 `click` \u7684 `extra` \u91CC\u65E2\u6709\u4F60\u914D\u7684\u57CB\u70B9\u540D\uFF0C\u4E5F\u6709\u8DF3\u8F6C\u5730\u5740\uFF1B\u8FD9\u4E00\u4E0B\u4E0D\u4F1A\u518D\u628A\u57CB\u70B9\u540D\u5E76\u8FDB `close`\uFF0C\u540C\u4E00\u4E2A\u540D\u5B57\u4E0D\u4F1A\u88AB\u62A5\u4E24\u904D\u3002"
334
344
  },
335
345
  {
336
346
  t: "note",
@@ -691,6 +701,18 @@ var userFieldRows = DEFAULT_USER_FIELDS.map((field) => [
691
701
  `\`user.${field}\``,
692
702
  USER_FIELD_LABELS[field] || ""
693
703
  ]);
704
+ var derivedRows = [
705
+ ["list", "`data` \u91CC\u7684\u6570\u7EC4\u5B57\u6BB5\u540D"],
706
+ ["indexBy", "`state` \u91CC\u7684\u4E0B\u6807\u5B57\u6BB5\u540D"],
707
+ ["autoplay", "\u53EF\u9009\u3002\u81EA\u52A8\u8F6E\u64AD\uFF0C\u89C1\u4E0B"]
708
+ ];
709
+ var autoplayRows = [
710
+ [
711
+ "interval",
712
+ `\u5FC5\u586B\u3002\u5207\u6362\u95F4\u9694\uFF0C**\u5355\u4F4D\u6BEB\u79D2**\uFF0C\u4E0D\u5C0F\u4E8E ${AUTOPLAY_MIN_INTERVAL}\uFF08\u5982 \`4000\` = 4 \u79D2\uFF09`
713
+ ],
714
+ ["pauseOnHover", "\u53EF\u9009\uFF0C\u9ED8\u8BA4 `false`\u3002\u9F20\u6807\u60AC\u505C\u5728\u6574\u4E2A\u7269\u6599\u4E0A\u65F6\u6682\u505C\uFF0C\u79FB\u5F00\u540E\u91CD\u65B0\u8BA1\u65F6"]
715
+ ];
694
716
  var sections4 = [
695
717
  {
696
718
  id: "data",
@@ -760,9 +782,42 @@ var sections4 = [
760
782
  {
761
783
  t: "table",
762
784
  head: ["\u5B57\u6BB5", "\u8BF4\u660E"],
763
- rows: [
764
- ["list", "`data` \u91CC\u7684\u6570\u7EC4\u5B57\u6BB5\u540D"],
765
- ["indexBy", "`state` \u91CC\u7684\u4E0B\u6807\u5B57\u6BB5\u540D"]
785
+ rows: derivedRows.concat(
786
+ reconcileRows({ rows: derivedRows, actual: DERIVED_FIELDS, label: "\u65B0\u589E\u5B57\u6BB5" })
787
+ )
788
+ },
789
+ { t: "h3", text: "derived.autoplay\uFF1A\u81EA\u52A8\u8F6E\u64AD" },
790
+ {
791
+ t: "p",
792
+ text: "\u516C\u544A\u6761\u8F6E\u64AD\u6587\u6848\u3001\u8F6E\u64AD\u56FE\u8FD9\u7C7B\u300C\u9694\u51E0\u79D2\u81EA\u52A8\u6362\u4E0B\u4E00\u6761\u300D\u7684\u9700\u6C42\uFF0C\u5728 derived \u4E0A\u52A0 `autoplay` \u5373\u53EF\u3002\u914D\u4E86\u5C31\u5F00\u542F\u3001\u59CB\u7EC8\u5FAA\u73AF\uFF1A\u6BCF\u9694 `interval` \u6BEB\u79D2\u628A `state[indexBy]` \u52A0 1\uFF0C\u5230\u672B\u5C3E\u56DE\u5230 0\u3002\u5B83\u6539\u72B6\u6001\u8D70\u7684\u5C31\u662F\u70B9 tab \u90A3\u4E00\u6761\u8DEF\uFF0C\u6240\u4EE5\u6587\u6848\u3001\u56FE\u7247\u3001tabs \u5706\u70B9\u6307\u793A\u5668\u3001\u8DF3\u8F6C\u94FE\u63A5\u4F1A\u4E00\u8D77\u5207\uFF0C\u6548\u679C\u548C\u7528\u6237\u624B\u52A8\u70B9\u5B8C\u5168\u4E00\u6837\u2014\u2014\u4E0D\u4F1A\u51ED\u7A7A\u591A\u51FA\u5207\u6362\u52A8\u753B\uFF0C\u60F3\u8981\u8FC7\u6E21\u6548\u679C\u81EA\u5DF1\u5728 `style` \u91CC\u914D `transition`\u3002"
793
+ },
794
+ {
795
+ t: "code",
796
+ code: `"data": { "slides": [ { "text": "\u2026", "url": "\u2026" }, { \u2026 }, { \u2026 } ] },
797
+ "state": { "slide": 0 },
798
+ "derived": { "cur": { "list": "slides", "indexBy": "slide",
799
+ "autoplay": { "interval": 4000, "pauseOnHover": true } } }
800
+
801
+ // \u6587\u6848 {{ cur.text }}\u3001\u94FE\u63A5 {{ cur.url }} \u81EA\u52A8\u8DDF\u7740\u5F53\u524D\u9879\u8D70\uFF1B
802
+ // \u5706\u70B9\u6307\u793A\u5668\u5C31\u662F\u4E00\u4E2A tabs\uFF1A{ "type": "tabs", "bind": "slides", "stateKey": "slide" }`
803
+ },
804
+ {
805
+ t: "table",
806
+ head: ["\u5B57\u6BB5", "\u8BF4\u660E"],
807
+ rows: autoplayRows.concat(
808
+ reconcileRows({
809
+ rows: autoplayRows,
810
+ actual: AUTOPLAY_FIELDS,
811
+ label: "\u65B0\u589E\u5B57\u6BB5"
812
+ })
813
+ )
814
+ },
815
+ {
816
+ t: "list",
817
+ items: [
818
+ "\u7528\u6237\u70B9\u4E86 tab\uFF08\u6216\u4EFB\u4F55 `setState` \u6539\u4E86\u540C\u4E00\u4E2A key\uFF09\u4F1A**\u91CD\u65B0\u8BA1\u65F6**\uFF0C\u4E0D\u4F1A\u521A\u70B9\u5B8C\u5C31\u88AB\u5207\u8D70",
819
+ "\u5217\u8868\u53EA\u6709 0~1 \u6761\u3001\u6216\u6570\u636E\u6E90\u8FD8\u6CA1\u56DE\u6765\u65F6\u4E0D\u64AD\uFF1B\u6570\u636E\u56DE\u6765\u540E\u81EA\u52A8\u5F00\u59CB",
820
+ "\u6CA1\u6709 `enabled` / `loop` \u5F00\u5173\uFF1A\u4E0D\u60F3\u8F6E\u64AD\u5C31\u522B\u5199 `autoplay`\uFF0C\u5199\u4E86\u5C31\u4E00\u76F4\u5FAA\u73AF"
766
821
  ]
767
822
  }
768
823
  ]
@@ -1690,6 +1745,15 @@ var sections_default = sections10;
1690
1745
 
1691
1746
  // src/docs/meta.ts
1692
1747
  var changelog = [
1748
+ {
1749
+ date: "2026-09-22",
1750
+ items: [
1751
+ '\u65B0\u589E derived.autoplay \u81EA\u52A8\u8F6E\u64AD\uFF08\u7B2C 8 \u8282\uFF09\uFF1A`{ "interval": 4000, "pauseOnHover": true }` \u6302\u5728 derived \u4E0A\u5373\u53EF\u8BA9\u516C\u544A\u6761\u6587\u6848 / \u8F6E\u64AD\u56FE\u6BCF\u9694\u51E0\u79D2\u81EA\u52A8\u6362\u4E0B\u4E00\u6761\u3001\u5230\u672B\u5C3E\u56DE\u5230\u7B2C\u4E00\u6761\u3002\u5207\u6362\u8D70\u7684\u662F\u548C\u70B9 tab \u540C\u4E00\u6761\u8DEF\uFF0C\u6587\u6848\u3001\u56FE\u7247\u3001\u5706\u70B9\u6307\u793A\u5668\u3001\u8DF3\u8F6C\u94FE\u63A5\u4E00\u8D77\u5207\uFF1B\u7528\u6237\u624B\u52A8\u70B9\u8FC7\u4F1A\u91CD\u65B0\u8BA1\u65F6\uFF0C\u5217\u8868\u4E0D\u8DB3 2 \u6761\u6216\u6570\u636E\u6CA1\u56DE\u6765\u65F6\u4E0D\u64AD',
1752
+ "autoplay \u4FDD\u5B58\u65F6\u4F1A\u6821\u9A8C\uFF1Ainterval \u5FC5\u987B\u662F\u4E0D\u5C0F\u4E8E 300 \u7684\u6BEB\u79D2\u6570\uFF08\u5199\u6210 4 \u8868\u793A 4 \u6BEB\u79D2\uFF0C\u4F1A\u88AB\u62E6\u4E0B\uFF09\uFF0CpauseOnHover \u5FC5\u987B\u662F\u5E03\u5C14\uFF1B\u6CA1\u6709 enabled / loop \u5B57\u6BB5\uFF0C\u5199\u4E86\u53EA\u544A\u8B66\u5E76\u88AB\u5FFD\u7565",
1753
+ "\u65B0\u589E\u793A\u4F8B \u246D \u516C\u544A\u6761\u8F6E\u64AD\u6218\u62A5\uFF1A3 \u6761\u6587\u6848 + tabs \u5706\u70B9\u6307\u793A\u5668 + \u8DF3\u8F6C\u94FE\u63A5\u8DDF\u968F\u5F53\u524D\u9879\uFF0C\u8981\u505A\u8F6E\u64AD\u6284\u8FD9\u4EFD",
1754
+ "\u6846\u67B6\u58F3\u65B0\u589E\u4E00\u6761\u4E49\u52A1\uFF1A\u6E32\u67D3\u6811\u5E26 onRootEnter / onRootLeave \u65F6\u5728\u6839\u5BB9\u5668\u4E0A\u7ED1 mouseenter / mouseleave\uFF08Vue 2 \u58F3\u5DF2\u8DDF\u4E0A\uFF09"
1755
+ ]
1756
+ },
1693
1757
  {
1694
1758
  date: "2026-09-01",
1695
1759
  items: [
@@ -5165,6 +5229,142 @@ var quotaLow = {
5165
5229
  };
5166
5230
  var quota_low_default = quotaLow;
5167
5231
 
5232
+ // src/docs/examples/notice-carousel.ts
5233
+ var slides = [
5234
+ {
5235
+ key: "move",
5236
+ text: "\u{1F389} \u4ECA\u65E5\u5DF2\u6709 12,806 \u5BB6\u5E97\u94FA\u7528\u9EA6\u7206\u4E86\u5B8C\u6210\u5546\u54C1\u642C\u5BB6",
5237
+ url: "https://maibaole.example.com/move",
5238
+ // tabs 的标签字段,圆点不显示文字,留空串
5239
+ dot: ""
5240
+ },
5241
+ {
5242
+ key: "ai",
5243
+ text: "\u{1F525} AI \u667A\u80FD\u4F18\u5316\u672C\u5468\u7D2F\u8BA1\u6539\u5199\u6807\u9898 38 \u4E07\u6761\uFF0C\u70B9\u51FB\u7387\u5E73\u5747\u63D0\u5347 17%",
5244
+ url: "https://maibaole.example.com/ai-optimize",
5245
+ dot: ""
5246
+ },
5247
+ {
5248
+ key: "renew",
5249
+ text: "\u{1F4B0} \u4E13\u4E1A\u7248\u9650\u65F6 8 \u6298\uFF0C\u7EED\u8D39\u7ACB\u7701 180 \u5143",
5250
+ url: "https://maibaole.example.com/renew",
5251
+ dot: ""
5252
+ }
5253
+ ];
5254
+ var noticeCarousel = {
5255
+ version: 1,
5256
+ type: "notice",
5257
+ meta: { name: "\u516C\u544A\u6761\u8F6E\u64AD\u6218\u62A5\uFF08\u81EA\u52A8\u8F6E\u64AD\uFF09" },
5258
+ data: { slides },
5259
+ state: { slide: 0 },
5260
+ derived: {
5261
+ cur: {
5262
+ list: "slides",
5263
+ indexBy: "slide",
5264
+ // 4 秒一条,悬停暂停;单位是毫秒
5265
+ autoplay: { interval: 4e3, pauseOnHover: true }
5266
+ }
5267
+ },
5268
+ stage: {
5269
+ width: "100%",
5270
+ height: "auto",
5271
+ layout: "flow",
5272
+ // 通栏类型不写 maxWidth,宽度交给宿主坑位
5273
+ style: { radius: 6, background: "#fff8e6" },
5274
+ onShow: { type: "track", event: "notice_show", params: { notice: "carousel" } },
5275
+ onClose: {
5276
+ type: "track",
5277
+ event: "notice_dismiss",
5278
+ params: { notice: "carousel", reason: "{{ closeReason }}" }
5279
+ }
5280
+ },
5281
+ nodes: [
5282
+ {
5283
+ type: "flex",
5284
+ style: { align: "center", gap: 10, padding: "10px 14px" },
5285
+ children: [
5286
+ {
5287
+ // 文案跟着当前项走;定高单行,换条时公告条高度不跳
5288
+ type: "text",
5289
+ content: "{{ cur.text }}",
5290
+ style: {
5291
+ flex: "1",
5292
+ fontSize: 14,
5293
+ color: "#8a6212",
5294
+ lineHeight: 22,
5295
+ height: 22,
5296
+ overflow: "hidden",
5297
+ whiteSpace: "nowrap"
5298
+ }
5299
+ },
5300
+ {
5301
+ // 圆点指示器:当前项拉长成胶囊,宽度变化用 transition 过渡
5302
+ type: "tabs",
5303
+ bind: "slides",
5304
+ stateKey: "slide",
5305
+ labelField: "dot",
5306
+ style: { direction: "row", align: "center", gap: 6 },
5307
+ itemStyle: {
5308
+ width: 6,
5309
+ height: 6,
5310
+ radius: 3,
5311
+ background: "rgba(176,138,62,0.35)",
5312
+ cursor: "pointer",
5313
+ transition: "width 0.3s ease"
5314
+ },
5315
+ activeItemStyle: { width: 16, background: "#f5a623" },
5316
+ action: {
5317
+ type: "track",
5318
+ event: "notice_dot_click",
5319
+ params: { notice: "carousel" }
5320
+ }
5321
+ },
5322
+ {
5323
+ // 链接跟着当前项走:看到哪条、点的就是哪条
5324
+ type: "button",
5325
+ text: "\u53BB\u770B\u770B",
5326
+ style: {
5327
+ width: 64,
5328
+ height: 26,
5329
+ radius: 13,
5330
+ background: "#f5a623",
5331
+ color: "#fff",
5332
+ fontSize: 12,
5333
+ cursor: "pointer"
5334
+ },
5335
+ action: {
5336
+ type: "sequence",
5337
+ actions: [
5338
+ {
5339
+ type: "track",
5340
+ event: "notice_click",
5341
+ params: { notice: "carousel", slide: "{{ cur.key }}" }
5342
+ },
5343
+ { type: "navigate", url: "{{ cur.url }}", target: "_blank" }
5344
+ ]
5345
+ }
5346
+ },
5347
+ {
5348
+ type: "text",
5349
+ content: "\u2715",
5350
+ style: {
5351
+ alignSelf: "center",
5352
+ width: 22,
5353
+ height: 22,
5354
+ textAlign: "center",
5355
+ lineHeight: 22,
5356
+ color: "#b08a3e",
5357
+ fontSize: 13,
5358
+ cursor: "pointer"
5359
+ },
5360
+ action: { type: "close", reason: "user-close" }
5361
+ }
5362
+ ]
5363
+ }
5364
+ ]
5365
+ };
5366
+ var notice_carousel_default = noticeCarousel;
5367
+
5168
5368
  // src/docs/examples/index.ts
5169
5369
  var HOTSPOT_BG = "rgba(255,68,51,0.16)";
5170
5370
  var imageHotspot = {
@@ -5430,6 +5630,11 @@ var examples = [
5430
5630
  label: "\u246C \u590D\u523B\u8FD0\u8425 demo \xB7 \u642C\u5BB6\u6B21\u6570\u5C06\u5C3D\uFF08\u989D\u5EA6\u8FDB\u5EA6\u6761\uFF09",
5431
5631
  value: "quotaLow",
5432
5632
  dsl: quota_low_default
5633
+ },
5634
+ {
5635
+ label: "\u246D \u516C\u544A\u6761\u8F6E\u64AD\u6218\u62A5\uFF08\u81EA\u52A8\u8F6E\u64AD + \u5706\u70B9\u6307\u793A\u5668\uFF09",
5636
+ value: "noticeCarousel",
5637
+ dsl: notice_carousel_default
5433
5638
  }
5434
5639
  ];
5435
5640
  var examples_default = examples;
@@ -5608,6 +5813,7 @@ function checklistSection() {
5608
5813
  - [ ] \u6240\u6709 \`style\` \u7684\u5C5E\u6027\u540D\u90FD\u5728\u767D\u540D\u5355\u91CC
5609
5814
  - [ ] \u6CA1\u6709\u4EFB\u4F55 JS \u4EE3\u7801\u3001\`javascript:\` \u94FE\u63A5\u3001\u51FD\u6570\u8C03\u7528
5610
5815
  - [ ] \`derived.list\` \u6307\u5411\u7684\u5B57\u6BB5\u5728 \`data\` \u91CC\u771F\u5B9E\u5B58\u5728\uFF0C\`derived.indexBy\` \u5728 \`state\` \u91CC\u5B58\u5728
5816
+ - [ ] \u7528\u4E86 \`derived.autoplay\` \u7684\u8BDD\uFF1A\`interval\` \u662F \u2265${AUTOPLAY_MIN_INTERVAL} \u7684\u6BEB\u79D2\u6570\u5B57\uFF08\u4E0D\u662F\u79D2\uFF09\uFF0C\u6CA1\u6709\u5199 \`enabled\` / \`loop\` \u8FD9\u7C7B\u4E0D\u5B58\u5728\u7684\u5B57\u6BB5
5611
5817
  - [ ] \u7528\u4E86 \`views\` \u7684\u8BDD\uFF1A\`entry\` \u5B58\u5728\u4E8E \`views\`\uFF0C\u9876\u5C42\u6CA1\u6709\u6B8B\u7559 \`stage\`/\`nodes\`\uFF0C\u6240\u6709 \`open\` \u7684 \`view\` \u90FD\u80FD\u5BF9\u4E0A
5612
5818
  - [ ] \`repeat.bind\` \u6307\u5411\u7684\u662F\u6570\u7EC4
5613
5819
  - [ ] \u6BCF\u4E2A\u53EF\u70B9\u51FB\u5143\u7D20\u90FD\u6709 \`action\`\uFF0C\u4E14\u5E26 \`track\` \u57CB\u70B9
@@ -5857,6 +6063,18 @@ function dataSection() {
5857
6063
  \u4E4B\u540E\u4EFB\u610F\u8282\u70B9\u91CC\u7528 \`{{ current.price }}\` \`{{ current.url }}\`\uFF0C
5858
6064
  \u5207\u6362\u65F6\u4EF7\u683C\u3001\u94FE\u63A5\u3001\u57CB\u70B9\u53C2\u6570\u5168\u90E8\u81EA\u52A8\u8054\u52A8\uFF0C\u7248\u5F0F\u53EA\u9700\u8981\u6392\u4E00\u904D\u3002
5859
6065
 
6066
+ **\u81EA\u52A8\u8F6E\u64AD**\uFF08\u516C\u544A\u6761\u8F6E\u64AD\u6587\u6848 / \u6218\u62A5\u6EDA\u52A8\u3001\u8F6E\u64AD\u56FE\uFF09\u7528 \`derived.xxx.autoplay\`\uFF0C\u4E0D\u8981\u81EA\u5DF1\u62FC\u5B9A\u65F6\u903B\u8F91\uFF1A
6067
+
6068
+ \`\`\`jsonc
6069
+ "state": { "slide": 0 },
6070
+ "derived": { "cur": { "list": "slides", "indexBy": "slide",
6071
+ "autoplay": { "interval": 4000, "pauseOnHover": true } } }
6072
+ \`\`\`
6073
+
6074
+ - \`interval\` \u5FC5\u586B\uFF0C**\u5355\u4F4D\u6BEB\u79D2**\uFF0C\u4E0D\u5C0F\u4E8E ${AUTOPLAY_MIN_INTERVAL}\uFF1B\`pauseOnHover\` \u53EF\u9009\u5E03\u5C14\uFF08\u60AC\u505C\u6682\u505C\uFF09
6075
+ - \u53EA\u6709\u8FD9\u4E24\u4E2A\u5B57\u6BB5\uFF0C**\u6CA1\u6709** \`enabled\` / \`loop\`\uFF1A\u914D\u4E86\u5C31\u5F00\u542F\u3001\u59CB\u7EC8\u5FAA\u73AF
6076
+ - \u5207\u6362\u6548\u679C\u4E0E\u70B9 tab \u5B8C\u5168\u4E00\u6837\uFF0C\u6587\u6848 / \u56FE\u7247 / \u94FE\u63A5\u90FD\u4ECE \`{{ cur.xxx }}\` \u53D6\uFF1B\u8981\u5706\u70B9\u6307\u793A\u5668\u5C31\u653E\u4E00\u4E2A \`tabs\`\uFF08\`bind\` \u540C\u4E00\u4E2A\u5217\u8868\u3001\`stateKey\` \u540C\u4E00\u4E2A state\uFF09
6077
+
5860
6078
  \u6570\u636E\u8981\u4ECE\u540E\u7AEF\u53D6\u65F6\u5199 \`"tiers": { "$source": "\u6570\u636E\u6E90\u540D", "params": {} }\`\uFF0C
5861
6079
  \u6570\u636E\u6E90\u540D\u5FC5\u987B\u662F\u540E\u7AEF\u5DF2\u6CE8\u518C\u7684\uFF0C**\u4E0D\u80FD\u5199\u63A5\u53E3\u5730\u5740**\u3002\u7528\u6237\u6CA1\u8BF4\u5C31\u7528\u5199\u6B7B\u7684\u6570\u636E\u3002
5862
6080
 
package/dist/index.cjs CHANGED
@@ -500,6 +500,109 @@ function createTicker(options) {
500
500
  return { sync, stop };
501
501
  }
502
502
 
503
+ // src/autoplay.ts
504
+ var DERIVED_FIELDS = ["list", "indexBy", "autoplay"];
505
+ var AUTOPLAY_FIELDS = ["interval", "pauseOnHover"];
506
+ var AUTOPLAY_MIN_INTERVAL = 300;
507
+ function collectEntries(derived) {
508
+ const entries = [];
509
+ Object.keys(derived || {}).forEach((name) => {
510
+ const config = (derived || {})[name];
511
+ const autoplay = config && config.autoplay;
512
+ if (!autoplay || typeof autoplay !== "object") return;
513
+ const interval = Number(autoplay.interval);
514
+ if (!isFinite(interval) || interval < AUTOPLAY_MIN_INTERVAL) return;
515
+ entries.push({
516
+ list: config.list,
517
+ indexBy: config.indexBy,
518
+ interval,
519
+ pauseOnHover: autoplay.pauseOnHover === true,
520
+ timer: null
521
+ });
522
+ });
523
+ return entries;
524
+ }
525
+ function createAutoplay(options) {
526
+ const entries = collectEntries(options.derived);
527
+ let started = false;
528
+ let hovering = false;
529
+ let stopped = false;
530
+ function clear(entry) {
531
+ if (entry.timer) {
532
+ clearTimeout(entry.timer);
533
+ entry.timer = null;
534
+ }
535
+ }
536
+ function advance(entry) {
537
+ entry.timer = null;
538
+ const length = options.getLength(entry.list);
539
+ if (length <= 1) return;
540
+ const index = options.getIndex(entry.indexBy);
541
+ options.setState(entry.indexBy, (index + 1) % length);
542
+ }
543
+ function schedule(entry) {
544
+ clear(entry);
545
+ if (stopped || !started) return;
546
+ if (hovering && entry.pauseOnHover) return;
547
+ if (options.getLength(entry.list) <= 1) return;
548
+ entry.timer = setTimeout(() => advance(entry), entry.interval);
549
+ }
550
+ return {
551
+ pausable: entries.some((entry) => entry.pauseOnHover),
552
+ start() {
553
+ started = true;
554
+ entries.forEach(schedule);
555
+ },
556
+ reset(key) {
557
+ entries.forEach((entry) => {
558
+ if (entry.indexBy === key) schedule(entry);
559
+ });
560
+ },
561
+ pause() {
562
+ hovering = true;
563
+ entries.forEach((entry) => {
564
+ if (entry.pauseOnHover) clear(entry);
565
+ });
566
+ },
567
+ resume() {
568
+ hovering = false;
569
+ entries.forEach((entry) => {
570
+ if (entry.pauseOnHover) schedule(entry);
571
+ });
572
+ },
573
+ stop() {
574
+ stopped = true;
575
+ entries.forEach(clear);
576
+ }
577
+ };
578
+ }
579
+ function validateAutoplay(autoplay, path, add, warn) {
580
+ if (autoplay === void 0) return;
581
+ if (!autoplay || typeof autoplay !== "object" || Array.isArray(autoplay)) {
582
+ add(path, 'autoplay \u5FC5\u987B\u662F\u5BF9\u8C61\uFF0C\u5F62\u5982 { "interval": 4000, "pauseOnHover": true }');
583
+ return;
584
+ }
585
+ const config = autoplay;
586
+ const interval = config.interval;
587
+ if (typeof interval !== "number" || !isFinite(interval) || interval < AUTOPLAY_MIN_INTERVAL) {
588
+ add(
589
+ `${path}.interval`,
590
+ `interval \u5FC5\u987B\u662F\u4E0D\u5C0F\u4E8E ${AUTOPLAY_MIN_INTERVAL} \u7684\u6570\u5B57\uFF0C\u5355\u4F4D\u6BEB\u79D2\uFF08\u5982 4000 \u8868\u793A 4 \u79D2\uFF09\uFF0C\u5F53\u524D\u4E3A ${JSON.stringify(interval)}`
591
+ );
592
+ }
593
+ if (config.pauseOnHover !== void 0 && typeof config.pauseOnHover !== "boolean") {
594
+ add(`${path}.pauseOnHover`, "pauseOnHover \u5FC5\u987B\u662F true \u6216 false");
595
+ }
596
+ Object.keys(config).forEach((key) => {
597
+ if (AUTOPLAY_FIELDS.indexOf(key) === -1) {
598
+ warn(
599
+ `${path}.${key}`,
600
+ `autoplay \u4E0D\u8BA4\u8BC6 "${key}"\uFF0C\u4F1A\u88AB\u5FFD\u7565\u3002\u53EF\u7528\uFF1A${AUTOPLAY_FIELDS.join(" / ")}\uFF08\u914D\u4E86 autoplay \u5C31\u5F00\u542F\u4E14\u59CB\u7EC8\u5FAA\u73AF\uFF0C\u4E0D\u9700\u8981 enabled / loop\uFF09`
601
+ );
602
+ }
603
+ });
604
+ }
605
+
503
606
  // src/views.ts
504
607
  var SINGLE_VIEW_NAME = "main";
505
608
  function normalizeViews(dsl) {
@@ -1381,7 +1484,19 @@ function createRuntime(dsl, options = {}) {
1381
1484
  state = Object.assign({}, state, { [key]: value });
1382
1485
  emit("state-change", Object.assign({}, state));
1383
1486
  notify();
1487
+ autoplay.reset(key);
1384
1488
  }
1489
+ const autoplay = createAutoplay({
1490
+ derived: dsl.derived,
1491
+ getLength: (name) => {
1492
+ const list = resolvedData[name];
1493
+ return Array.isArray(list) ? list.length : 0;
1494
+ },
1495
+ getIndex: (key) => Number(state[key]) || 0,
1496
+ setState: (key, value) => {
1497
+ if (!destroyed) setState(key, value);
1498
+ }
1499
+ });
1385
1500
  function openView(name, mode) {
1386
1501
  if (!normalized.views[name]) {
1387
1502
  emit("error", { type: "unknown-view", name });
@@ -1482,6 +1597,7 @@ function createRuntime(dsl, options = {}) {
1482
1597
  notify();
1483
1598
  fireLifecycle(normalized.entry, "onShow");
1484
1599
  emit("ready", { keys: Object.keys(resolved) });
1600
+ autoplay.start();
1485
1601
  }).catch((error) => {
1486
1602
  if (destroyed) return;
1487
1603
  loading = false;
@@ -1510,6 +1626,10 @@ function createRuntime(dsl, options = {}) {
1510
1626
  hover
1511
1627
  });
1512
1628
  ticker.sync(tree.countdownEndTimes, tree.countdownPrecision);
1629
+ if (autoplay.pausable) {
1630
+ tree.onRootEnter = autoplay.pause;
1631
+ tree.onRootLeave = autoplay.resume;
1632
+ }
1513
1633
  return tree;
1514
1634
  }
1515
1635
  return {
@@ -1529,6 +1649,7 @@ function createRuntime(dsl, options = {}) {
1529
1649
  destroy() {
1530
1650
  destroyed = true;
1531
1651
  ticker.stop();
1652
+ autoplay.stop();
1532
1653
  listeners.clear();
1533
1654
  }
1534
1655
  };
@@ -1832,7 +1953,7 @@ function validate(dsl, options) {
1832
1953
  }
1833
1954
  const dataKeys = validateData(doc.data, add);
1834
1955
  const stateKeys = validateState(doc.state, add);
1835
- validateDerived(doc.derived, dataKeys, stateKeys, add);
1956
+ validateDerived(doc.derived, dataKeys, stateKeys, add, warn);
1836
1957
  const keyframeNames = validateKeyframes(doc.keyframes, add, warn);
1837
1958
  const isMulti = doc.views !== void 0;
1838
1959
  if (isMulti) validateMultiView(doc, add);
@@ -2081,7 +2202,7 @@ function validateState(state, add) {
2081
2202
  }
2082
2203
  return Object.keys(state);
2083
2204
  }
2084
- function validateDerived(derived, dataKeys, stateKeys, add) {
2205
+ function validateDerived(derived, dataKeys, stateKeys, add, warn) {
2085
2206
  if (derived === void 0) return;
2086
2207
  if (typeof derived !== "object" || derived === null || Array.isArray(derived)) {
2087
2208
  add("derived", "derived \u5FC5\u987B\u662F\u5BF9\u8C61");
@@ -2099,6 +2220,7 @@ function validateDerived(derived, dataKeys, stateKeys, add) {
2099
2220
  } else if (stateKeys.indexOf(item.indexBy) === -1) {
2100
2221
  add(`derived.${key}.indexBy`, `state \u4E2D\u4E0D\u5B58\u5728 "${item.indexBy}"`);
2101
2222
  }
2223
+ validateAutoplay(item.autoplay, `derived.${key}.autoplay`, add, warn);
2102
2224
  });
2103
2225
  }
2104
2226
  function validateNodeStyle(style, path, ctx) {
@@ -2334,10 +2456,13 @@ function isRegisteredHostHandler(name) {
2334
2456
  exports.ACTION_TYPES = ACTION_TYPES;
2335
2457
  exports.ALLOWED_EASINGS = ALLOWED_EASINGS;
2336
2458
  exports.ALLOWED_STYLE_KEYS = ALLOWED_STYLE_KEYS;
2459
+ exports.AUTOPLAY_FIELDS = AUTOPLAY_FIELDS;
2460
+ exports.AUTOPLAY_MIN_INTERVAL = AUTOPLAY_MIN_INTERVAL;
2337
2461
  exports.BANNER_MIN_ASPECT_RATIO = BANNER_MIN_ASPECT_RATIO;
2338
2462
  exports.CLOSE_POSITIONS = CLOSE_POSITIONS;
2339
2463
  exports.CSS_NAME_PATTERN = CSS_NAME_PATTERN;
2340
2464
  exports.DEFAULT_USER_FIELDS = DEFAULT_USER_FIELDS;
2465
+ exports.DERIVED_FIELDS = DERIVED_FIELDS;
2341
2466
  exports.DSL_VERSION = DSL_VERSION;
2342
2467
  exports.HOST_HANDLER_LABELS = HOST_HANDLER_LABELS;
2343
2468
  exports.HOST_HANDLER_NAMES = HOST_HANDLER_NAMES;
@@ -2369,4 +2494,5 @@ exports.sanitizeCssValue = sanitizeCssValue;
2369
2494
  exports.toCssStyle = toCssStyle;
2370
2495
  exports.toLength = toLength;
2371
2496
  exports.validate = validate;
2497
+ exports.validateAutoplay = validateAutoplay;
2372
2498
  exports.validateUserFields = validateUserFields;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { D as Dsl, R as RuntimeOptions, a as RenderTree, b as DslView, c as DslStyle, C as CssStyle } from './types-8FNxDXp0.cjs';
2
- export { s as DslAction, j as DslActionBase, h as DslAnimate, q as DslCallAction, l as DslCloseAction, m as DslCloseAllAction, v as DslCloseButton, u as DslClosePosition, y as DslDerived, E as DslHandler, G as DslInteractionEvent, F as DslInteractionTrigger, i as DslKeyframe, f as DslLength, k as DslNavigateAction, t as DslNode, e as DslNodeType, n as DslOpenAction, g as DslRect, r as DslSequenceAction, o as DslSetStateAction, B as DslSource, x as DslSourceRef, w as DslStage, p as DslTrackAction, d as DslViewType, z as RenderElement, A as RenderLayer, J as RuntimeEmit, I as RuntimeEventName, H as RuntimeEvents } from './types-8FNxDXp0.cjs';
1
+ import { D as Dsl, R as RuntimeOptions, a as RenderTree, b as DslView, c as DslStyle, C as CssStyle } from './types-BapBTTio.cjs';
2
+ export { s as DslAction, j as DslActionBase, h as DslAnimate, y as DslAutoplay, q as DslCallAction, l as DslCloseAction, m as DslCloseAllAction, v as DslCloseButton, u as DslClosePosition, z as DslDerived, F as DslHandler, H as DslInteractionEvent, G as DslInteractionTrigger, i as DslKeyframe, f as DslLength, k as DslNavigateAction, t as DslNode, e as DslNodeType, n as DslOpenAction, g as DslRect, r as DslSequenceAction, o as DslSetStateAction, E as DslSource, x as DslSourceRef, w as DslStage, p as DslTrackAction, d as DslViewType, A as RenderElement, B as RenderLayer, K as RuntimeEmit, J as RuntimeEventName, I as RuntimeEvents } from './types-BapBTTio.cjs';
3
3
 
4
4
  /**
5
5
  * 运行时。
@@ -28,7 +28,7 @@ interface DslRuntime {
28
28
  /** 供调试台等外部读取,正常渲染不需要 */
29
29
  getState: () => Record<string, unknown>;
30
30
  getViewStack: () => string[];
31
- /** 卸载时必须调用,否则倒计时定时器不会停 */
31
+ /** 卸载时必须调用,否则倒计时与自动轮播的定时器不会停 */
32
32
  destroy: () => void;
33
33
  }
34
34
  declare function createRuntime(dsl: Dsl, options?: RuntimeOptions): DslRuntime;
@@ -372,4 +372,41 @@ declare function computeParts(endTime: number, now?: number): CountdownParts;
372
372
  /** 不给 children 时退化成一行文本,占位符 {d} {h} {hAll} {m} {s} {cs} */
373
373
  declare function formatParts(parts: CountdownParts, format?: string): string;
374
374
 
375
- export { ACTION_TYPES, ALLOWED_EASINGS, ALLOWED_STYLE_KEYS, BANNER_MIN_ASPECT_RATIO, CLOSE_POSITIONS, CSS_NAME_PATTERN, type CountdownParts, type CountdownPrecision, CssStyle, DEFAULT_USER_FIELDS, DSL_VERSION, Dsl, type DslRuntime, DslStyle, DslView, HOST_HANDLER_LABELS, HOST_HANDLER_NAMES, HOST_SOURCE_LABELS, HOST_SOURCE_NAMES, type HostHandlerName, type HostSourceName, type Issue, NODE_TYPES, type NormalizedViews, RenderTree, RuntimeOptions, SINGLE_VIEW_NAME, TRACK_EVENT_PATTERN, USER_FIELD_LABELS, type ValidateOptions, type ValidateResult, check, computeParts, createRuntime, evaluate, formatIssues, formatParts, interpolate, interpolateDeep, isKeyframeOffset, isLength, isRegisteredHostHandler, isRegisteredHostSource, isValidEasing, isValidEndTime, normalizeViews, parseEndTime, safeImageUrl, safeUrl, sanitizeCssValue, toCssStyle, toLength, validate, validateUserFields };
375
+ /**
376
+ * derived 自动轮播(`derived.xxx.autoplay`)。
377
+ *
378
+ * 只管「什么时候该往下切一格」,**不管切了之后长什么样**:
379
+ * 到点后调的是运行时的同一个 `setState`,和用户点 tab 完全同一条路径——
380
+ * 文案 / 图片 / tabs 指示器 / 跳转链接 / 运营自己配的 transition 全部自然联动,
381
+ * 这里不引入任何额外的切换动画,也不另写一套状态改动。
382
+ *
383
+ * 时机规则:
384
+ * - 数据就绪(`start`)之后才开始计时;列表长度 ≤1 不播
385
+ * - 用户手动改了同一个 state key(`reset`)→ 重新计时,避免刚点完就被切走
386
+ * - 悬停(`pause`)清掉定时器,离开(`resume`)重新计一整个 interval
387
+ * - `stop` 之后永久失效,任何入口都不会再起定时器
388
+ *
389
+ * 不依赖 DOM,定时器用 setTimeout,Node 里也能跑。
390
+ */
391
+
392
+ /** `derived.xxx` 允许出现的字段,校验与文档对账共用这一份 */
393
+ declare const DERIVED_FIELDS: string[];
394
+ /** `derived.xxx.autoplay` 允许出现的字段,校验与文档对账共用这一份 */
395
+ declare const AUTOPLAY_FIELDS: string[];
396
+ /** 轮播间隔下限(毫秒)。主要防单位写错(把 4 秒写成 4),300 仍允许快速闪动类效果 */
397
+ declare const AUTOPLAY_MIN_INTERVAL = 300;
398
+ type Add = (path: string, message: string) => void;
399
+ /**
400
+ * 校验一处 `derived.xxx.autoplay`。
401
+ *
402
+ * 和运行时共用同一套常量(字段表、间隔下限),规则不会两边漂移。
403
+ * interval 写错的表现是「不轮播」,运营只会以为没生效、反复重配,所以要在保存时拦下。
404
+ *
405
+ * @param autoplay 待校验的值
406
+ * @param path 报错路径,如 `derived.cur.autoplay`
407
+ * @param add 报 error
408
+ * @param warn 报 warning(未知字段只告警:运行时会忽略,但多半是写错了,如 loop / enabled)
409
+ */
410
+ declare function validateAutoplay(autoplay: unknown, path: string, add: Add, warn: Add): void;
411
+
412
+ export { ACTION_TYPES, ALLOWED_EASINGS, ALLOWED_STYLE_KEYS, AUTOPLAY_FIELDS, AUTOPLAY_MIN_INTERVAL, BANNER_MIN_ASPECT_RATIO, CLOSE_POSITIONS, CSS_NAME_PATTERN, type CountdownParts, type CountdownPrecision, CssStyle, DEFAULT_USER_FIELDS, DERIVED_FIELDS, DSL_VERSION, Dsl, type DslRuntime, DslStyle, DslView, HOST_HANDLER_LABELS, HOST_HANDLER_NAMES, HOST_SOURCE_LABELS, HOST_SOURCE_NAMES, type HostHandlerName, type HostSourceName, type Issue, NODE_TYPES, type NormalizedViews, RenderTree, RuntimeOptions, SINGLE_VIEW_NAME, TRACK_EVENT_PATTERN, USER_FIELD_LABELS, type ValidateOptions, type ValidateResult, check, computeParts, createRuntime, evaluate, formatIssues, formatParts, interpolate, interpolateDeep, isKeyframeOffset, isLength, isRegisteredHostHandler, isRegisteredHostSource, isValidEasing, isValidEndTime, normalizeViews, parseEndTime, safeImageUrl, safeUrl, sanitizeCssValue, toCssStyle, toLength, validate, validateAutoplay, validateUserFields };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { D as Dsl, R as RuntimeOptions, a as RenderTree, b as DslView, c as DslStyle, C as CssStyle } from './types-8FNxDXp0.js';
2
- export { s as DslAction, j as DslActionBase, h as DslAnimate, q as DslCallAction, l as DslCloseAction, m as DslCloseAllAction, v as DslCloseButton, u as DslClosePosition, y as DslDerived, E as DslHandler, G as DslInteractionEvent, F as DslInteractionTrigger, i as DslKeyframe, f as DslLength, k as DslNavigateAction, t as DslNode, e as DslNodeType, n as DslOpenAction, g as DslRect, r as DslSequenceAction, o as DslSetStateAction, B as DslSource, x as DslSourceRef, w as DslStage, p as DslTrackAction, d as DslViewType, z as RenderElement, A as RenderLayer, J as RuntimeEmit, I as RuntimeEventName, H as RuntimeEvents } from './types-8FNxDXp0.js';
1
+ import { D as Dsl, R as RuntimeOptions, a as RenderTree, b as DslView, c as DslStyle, C as CssStyle } from './types-BapBTTio.js';
2
+ export { s as DslAction, j as DslActionBase, h as DslAnimate, y as DslAutoplay, q as DslCallAction, l as DslCloseAction, m as DslCloseAllAction, v as DslCloseButton, u as DslClosePosition, z as DslDerived, F as DslHandler, H as DslInteractionEvent, G as DslInteractionTrigger, i as DslKeyframe, f as DslLength, k as DslNavigateAction, t as DslNode, e as DslNodeType, n as DslOpenAction, g as DslRect, r as DslSequenceAction, o as DslSetStateAction, E as DslSource, x as DslSourceRef, w as DslStage, p as DslTrackAction, d as DslViewType, A as RenderElement, B as RenderLayer, K as RuntimeEmit, J as RuntimeEventName, I as RuntimeEvents } from './types-BapBTTio.js';
3
3
 
4
4
  /**
5
5
  * 运行时。
@@ -28,7 +28,7 @@ interface DslRuntime {
28
28
  /** 供调试台等外部读取,正常渲染不需要 */
29
29
  getState: () => Record<string, unknown>;
30
30
  getViewStack: () => string[];
31
- /** 卸载时必须调用,否则倒计时定时器不会停 */
31
+ /** 卸载时必须调用,否则倒计时与自动轮播的定时器不会停 */
32
32
  destroy: () => void;
33
33
  }
34
34
  declare function createRuntime(dsl: Dsl, options?: RuntimeOptions): DslRuntime;
@@ -372,4 +372,41 @@ declare function computeParts(endTime: number, now?: number): CountdownParts;
372
372
  /** 不给 children 时退化成一行文本,占位符 {d} {h} {hAll} {m} {s} {cs} */
373
373
  declare function formatParts(parts: CountdownParts, format?: string): string;
374
374
 
375
- export { ACTION_TYPES, ALLOWED_EASINGS, ALLOWED_STYLE_KEYS, BANNER_MIN_ASPECT_RATIO, CLOSE_POSITIONS, CSS_NAME_PATTERN, type CountdownParts, type CountdownPrecision, CssStyle, DEFAULT_USER_FIELDS, DSL_VERSION, Dsl, type DslRuntime, DslStyle, DslView, HOST_HANDLER_LABELS, HOST_HANDLER_NAMES, HOST_SOURCE_LABELS, HOST_SOURCE_NAMES, type HostHandlerName, type HostSourceName, type Issue, NODE_TYPES, type NormalizedViews, RenderTree, RuntimeOptions, SINGLE_VIEW_NAME, TRACK_EVENT_PATTERN, USER_FIELD_LABELS, type ValidateOptions, type ValidateResult, check, computeParts, createRuntime, evaluate, formatIssues, formatParts, interpolate, interpolateDeep, isKeyframeOffset, isLength, isRegisteredHostHandler, isRegisteredHostSource, isValidEasing, isValidEndTime, normalizeViews, parseEndTime, safeImageUrl, safeUrl, sanitizeCssValue, toCssStyle, toLength, validate, validateUserFields };
375
+ /**
376
+ * derived 自动轮播(`derived.xxx.autoplay`)。
377
+ *
378
+ * 只管「什么时候该往下切一格」,**不管切了之后长什么样**:
379
+ * 到点后调的是运行时的同一个 `setState`,和用户点 tab 完全同一条路径——
380
+ * 文案 / 图片 / tabs 指示器 / 跳转链接 / 运营自己配的 transition 全部自然联动,
381
+ * 这里不引入任何额外的切换动画,也不另写一套状态改动。
382
+ *
383
+ * 时机规则:
384
+ * - 数据就绪(`start`)之后才开始计时;列表长度 ≤1 不播
385
+ * - 用户手动改了同一个 state key(`reset`)→ 重新计时,避免刚点完就被切走
386
+ * - 悬停(`pause`)清掉定时器,离开(`resume`)重新计一整个 interval
387
+ * - `stop` 之后永久失效,任何入口都不会再起定时器
388
+ *
389
+ * 不依赖 DOM,定时器用 setTimeout,Node 里也能跑。
390
+ */
391
+
392
+ /** `derived.xxx` 允许出现的字段,校验与文档对账共用这一份 */
393
+ declare const DERIVED_FIELDS: string[];
394
+ /** `derived.xxx.autoplay` 允许出现的字段,校验与文档对账共用这一份 */
395
+ declare const AUTOPLAY_FIELDS: string[];
396
+ /** 轮播间隔下限(毫秒)。主要防单位写错(把 4 秒写成 4),300 仍允许快速闪动类效果 */
397
+ declare const AUTOPLAY_MIN_INTERVAL = 300;
398
+ type Add = (path: string, message: string) => void;
399
+ /**
400
+ * 校验一处 `derived.xxx.autoplay`。
401
+ *
402
+ * 和运行时共用同一套常量(字段表、间隔下限),规则不会两边漂移。
403
+ * interval 写错的表现是「不轮播」,运营只会以为没生效、反复重配,所以要在保存时拦下。
404
+ *
405
+ * @param autoplay 待校验的值
406
+ * @param path 报错路径,如 `derived.cur.autoplay`
407
+ * @param add 报 error
408
+ * @param warn 报 warning(未知字段只告警:运行时会忽略,但多半是写错了,如 loop / enabled)
409
+ */
410
+ declare function validateAutoplay(autoplay: unknown, path: string, add: Add, warn: Add): void;
411
+
412
+ export { ACTION_TYPES, ALLOWED_EASINGS, ALLOWED_STYLE_KEYS, AUTOPLAY_FIELDS, AUTOPLAY_MIN_INTERVAL, BANNER_MIN_ASPECT_RATIO, CLOSE_POSITIONS, CSS_NAME_PATTERN, type CountdownParts, type CountdownPrecision, CssStyle, DEFAULT_USER_FIELDS, DERIVED_FIELDS, DSL_VERSION, Dsl, type DslRuntime, DslStyle, DslView, HOST_HANDLER_LABELS, HOST_HANDLER_NAMES, HOST_SOURCE_LABELS, HOST_SOURCE_NAMES, type HostHandlerName, type HostSourceName, type Issue, NODE_TYPES, type NormalizedViews, RenderTree, RuntimeOptions, SINGLE_VIEW_NAME, TRACK_EVENT_PATTERN, USER_FIELD_LABELS, type ValidateOptions, type ValidateResult, check, computeParts, createRuntime, evaluate, formatIssues, formatParts, interpolate, interpolateDeep, isKeyframeOffset, isLength, isRegisteredHostHandler, isRegisteredHostSource, isValidEasing, isValidEndTime, normalizeViews, parseEndTime, safeImageUrl, safeUrl, sanitizeCssValue, toCssStyle, toLength, validate, validateAutoplay, validateUserFields };