@visactor/vchart-extension 2.1.0-alpha.24 → 2.1.0-alpha.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/build/index.js +213 -321
  2. package/build/index.min.js +1 -1
  3. package/cjs/charts/axis-3d/linear-axis.js +1 -2
  4. package/cjs/charts/bar-3d/constant.js +2 -1
  5. package/cjs/charts/candlestick/candlestick.js +1 -2
  6. package/cjs/charts/conversion-funnel/interface.js +2 -1
  7. package/cjs/charts/funnel-3d/series.js +2 -1
  8. package/cjs/charts/funnel-3d/theme.js +1 -1
  9. package/cjs/charts/histogram-3d/chart.js +1 -2
  10. package/cjs/charts/histogram-3d/index.js +1 -1
  11. package/cjs/charts/histogram-3d/interface.js +1 -1
  12. package/cjs/charts/pictogram/element-highlight-by-graphic-name.js +1 -1
  13. package/cjs/charts/storyline/interface.d.ts +2 -4
  14. package/cjs/charts/storyline/interface.js.map +1 -1
  15. package/cjs/charts/storyline/layout.d.ts +0 -1
  16. package/cjs/charts/storyline/layout.js +4 -27
  17. package/cjs/charts/storyline/layout.js.map +1 -1
  18. package/cjs/charts/storyline/layouts/arc.js +0 -1
  19. package/cjs/charts/storyline/layouts/arc.js.map +1 -1
  20. package/cjs/charts/storyline/layouts/clock.js +0 -1
  21. package/cjs/charts/storyline/layouts/clock.js.map +1 -1
  22. package/cjs/charts/storyline/layouts/common.d.ts +0 -2
  23. package/cjs/charts/storyline/layouts/common.js +6 -11
  24. package/cjs/charts/storyline/layouts/common.js.map +1 -1
  25. package/cjs/charts/storyline/layouts/default.js +0 -1
  26. package/cjs/charts/storyline/layouts/default.js.map +1 -1
  27. package/cjs/charts/storyline/layouts/landscape.js +4 -5
  28. package/cjs/charts/storyline/layouts/landscape.js.map +1 -1
  29. package/cjs/charts/storyline/layouts/portrait.js +0 -1
  30. package/cjs/charts/storyline/layouts/portrait.js.map +1 -1
  31. package/cjs/charts/storyline/layouts/wing.js +137 -23
  32. package/cjs/charts/storyline/layouts/wing.js.map +1 -1
  33. package/cjs/charts/storyline/storyline-transformer.js +10 -22
  34. package/cjs/charts/storyline/storyline-transformer.js.map +1 -1
  35. package/esm/charts/axis-3d/linear-axis.js +1 -2
  36. package/esm/charts/bar-3d/constant.js +2 -1
  37. package/esm/charts/candlestick/candlestick.js +1 -2
  38. package/esm/charts/conversion-funnel/interface.js +2 -1
  39. package/esm/charts/funnel-3d/series.js +2 -1
  40. package/esm/charts/funnel-3d/theme.js +1 -1
  41. package/esm/charts/histogram-3d/chart.js +1 -2
  42. package/esm/charts/histogram-3d/index.js +1 -1
  43. package/esm/charts/histogram-3d/interface.js +1 -1
  44. package/esm/charts/pictogram/element-highlight-by-graphic-name.js +1 -1
  45. package/esm/charts/storyline/interface.d.ts +2 -4
  46. package/esm/charts/storyline/interface.js.map +1 -1
  47. package/esm/charts/storyline/layout.d.ts +0 -1
  48. package/esm/charts/storyline/layout.js +4 -27
  49. package/esm/charts/storyline/layout.js.map +1 -1
  50. package/esm/charts/storyline/layouts/arc.js +0 -1
  51. package/esm/charts/storyline/layouts/arc.js.map +1 -1
  52. package/esm/charts/storyline/layouts/clock.js +0 -1
  53. package/esm/charts/storyline/layouts/clock.js.map +1 -1
  54. package/esm/charts/storyline/layouts/common.d.ts +0 -2
  55. package/esm/charts/storyline/layouts/common.js +3 -8
  56. package/esm/charts/storyline/layouts/common.js.map +1 -1
  57. package/esm/charts/storyline/layouts/default.js +0 -1
  58. package/esm/charts/storyline/layouts/default.js.map +1 -1
  59. package/esm/charts/storyline/layouts/landscape.js +4 -5
  60. package/esm/charts/storyline/layouts/landscape.js.map +1 -1
  61. package/esm/charts/storyline/layouts/portrait.js +0 -1
  62. package/esm/charts/storyline/layouts/portrait.js.map +1 -1
  63. package/esm/charts/storyline/layouts/wing.js +136 -22
  64. package/esm/charts/storyline/layouts/wing.js.map +1 -1
  65. package/esm/charts/storyline/storyline-transformer.js +8 -21
  66. package/esm/charts/storyline/storyline-transformer.js.map +1 -1
  67. package/package.json +4 -4
  68. package/cjs/charts/storyline/layouts/ladder.d.ts +0 -5
  69. package/cjs/charts/storyline/layouts/ladder.js +0 -230
  70. package/cjs/charts/storyline/layouts/ladder.js.map +0 -1
  71. package/esm/charts/storyline/layouts/ladder.d.ts +0 -5
  72. package/esm/charts/storyline/layouts/ladder.js +0 -217
  73. package/esm/charts/storyline/layouts/ladder.js.map +0 -1
package/build/index.js CHANGED
@@ -5855,12 +5855,11 @@
5855
5855
  return layout;
5856
5856
  };
5857
5857
  const computeStorylineLayout = (data, options) => {
5858
- var _a, _b, _c;
5858
+ var _a, _b;
5859
5859
  const layout = normalizeLayout(options.layout);
5860
5860
  const padding = normalizePadding((_a = layout.padding) !== null && _a !== void 0 ? _a : options.padding);
5861
- const gap = (_b = options.gap) !== null && _b !== void 0 ? _b : 40;
5862
- const lineDistance = (_c = options.lineDistance) !== null && _c !== void 0 ? _c : 8;
5863
- const blocks = computeBlockPositions(data, layout, options.viewBox, options.block, padding, gap);
5861
+ const lineDistance = (_b = options.lineDistance) !== null && _b !== void 0 ? _b : 8;
5862
+ const blocks = computeBlockPositions(data, layout, options.viewBox, options.block, padding);
5864
5863
  const circleGuide = layout.type === 'clock' ? computeClockCircleGuide(options.viewBox, options.block, padding, layout) : undefined;
5865
5864
  return {
5866
5865
  blocks,
@@ -5868,7 +5867,7 @@
5868
5867
  circleGuide
5869
5868
  };
5870
5869
  };
5871
- const computeBlockPositions = (data, layout, viewBox, block, padding, gap) => {
5870
+ const computeBlockPositions = (data, layout, viewBox, block, padding) => {
5872
5871
  const count = data.length;
5873
5872
  if (!count) {
5874
5873
  return [];
@@ -5888,34 +5887,6 @@
5888
5887
  case 'portrait':
5889
5888
  centers = lineCenters(count, center.x, inner.y + block.height / 2, center.x, inner.y + inner.height - block.height / 2);
5890
5889
  break;
5891
- case 'ladder': {
5892
- const isDown = layout.direction === 'down';
5893
- const x0 = inner.x + block.width / 2;
5894
- const x1 = inner.x + inner.width - block.width / 2;
5895
- const yTop = inner.y + block.height / 2;
5896
- const yBot = inner.y + inner.height - block.height / 2;
5897
- const y0 = isDown ? yTop : yBot;
5898
- const y1 = isDown ? yBot : yTop;
5899
- const anchors = lineCenters(count, x0, y0, x1, y1);
5900
- const dx = x1 - x0;
5901
- const dy = y1 - y0;
5902
- const len = Math.hypot(dx, dy) || 1;
5903
- const nx = -dy / len;
5904
- const ny = dx / len;
5905
- const headlineFontSize = Math.max(80, Math.min(240, Math.round(inner.height * 0.42)));
5906
- const offset = headlineFontSize * 1.2;
5907
- centers = anchors.map((p, i) => {
5908
- const sign = i % 2 === 0 ? 1 : -1;
5909
- return {
5910
- x: p.x + nx * offset * sign,
5911
- y: p.y + ny * offset * sign
5912
- };
5913
- });
5914
- break;
5915
- }
5916
- case 'spiral':
5917
- centers = alternatingVerticalCenters(count, inner, block, gap);
5918
- break;
5919
5890
  case 'clock':
5920
5891
  centers = circularCenters(count, viewBox, block, padding, layout);
5921
5892
  break;
@@ -5962,15 +5933,6 @@
5962
5933
  };
5963
5934
  });
5964
5935
  };
5965
- const alternatingVerticalCenters = (count, inner, block, gap) => {
5966
- const baseX = inner.x + inner.width / 2;
5967
- const offset = Math.min(Math.max(block.width * 0.65 + gap / 2, 0), Math.max((inner.width - block.width) / 2, 0));
5968
- const points = lineCenters(count, baseX, inner.y + block.height / 2, baseX, inner.y + inner.height - block.height / 2);
5969
- return points.map((point, index) => ({
5970
- x: point.x + (index % 2 === 0 ? -offset : offset),
5971
- y: point.y
5972
- }));
5973
- };
5974
5936
  const circularCenters = (count, viewBox, block, padding, layout) => {
5975
5937
  var _a;
5976
5938
  const guide = computeClockCircleGuide(viewBox, block, padding, layout);
@@ -6073,7 +6035,6 @@
6073
6035
  const DEFAULT_BLOCK_WIDTH = 180;
6074
6036
  const DEFAULT_BLOCK_HEIGHT = 400;
6075
6037
  const DEFAULT_BLOCK_WIDTH_RATIO = 0.24;
6076
- const DEFAULT_BLOCK_GAP = 36;
6077
6038
  const DEFAULT_IMAGE_WIDTH = 48;
6078
6039
  const DEFAULT_IMAGE_HEIGHT = 48;
6079
6040
  const DEFAULT_IMAGE_GAP = 10;
@@ -6089,12 +6050,11 @@
6089
6050
  const isClock = (spec) => normalizeLayout(spec.layout).type === 'clock';
6090
6051
  const isArc = (spec) => normalizeLayout(spec.layout).type === 'arc';
6091
6052
  const isWing = (spec) => normalizeLayout(spec.layout).type === 'wing';
6092
- const isLadder = (spec) => normalizeLayout(spec.layout).type === 'ladder';
6093
6053
  const getThemeColor = (spec) => { var _a; return (_a = spec.themeColor) !== null && _a !== void 0 ? _a : DEFAULT_THEME_COLOR; };
6094
6054
  const shouldShowImageBackground = (spec) => { var _a, _b; return (_b = (_a = spec.image) === null || _a === void 0 ? void 0 : _a.showBackground) !== null && _b !== void 0 ? _b : !(isPortrait(spec) || isLandscape(spec)); };
6095
6055
  const TITLE_FONT_SCALE_ID = 'storylineTitleFontSize';
6096
6056
  const MARKER_FONT_SCALE_ID = 'storylineMarkerFontSize';
6097
- const clamp$1 = (value, min, max) => Math.max(min, Math.min(max, value));
6057
+ const clamp$2 = (value, min, max) => Math.max(min, Math.min(max, value));
6098
6058
  const getTextWeight = (text) => {
6099
6059
  if (!text) {
6100
6060
  return 4;
@@ -6143,7 +6103,7 @@
6143
6103
  ? ((options.boxWidth * BLOCK_TITLE_MAX_LINES) / textWeight) * 0.96
6144
6104
  : Number.POSITIVE_INFINITY;
6145
6105
  const boxHeightLimit = options.boxHeight && options.boxHeight > 0 ? options.boxHeight / Math.max(textWeight, 1) : Number.POSITIVE_INFINITY;
6146
- return Math.floor(clamp$1(Math.min(adaptiveSize, boxWidthLimit, boxHeightLimit), minFontSize, maxFontSize));
6106
+ return Math.floor(clamp$2(Math.min(adaptiveSize, boxWidthLimit, boxHeightLimit), minFontSize, maxFontSize));
6147
6107
  };
6148
6108
  const resolveAdaptiveLineHeight = (fontSize, style, fallback, ratio = 1.35) => { var _a; return Number((_a = style === null || style === void 0 ? void 0 : style.lineHeight) !== null && _a !== void 0 ? _a : Math.round((Number.isFinite(fontSize) ? fontSize : fallback) * ratio)); };
6149
6109
  const resolveTitleFontSize = (spec, ctx, title, boxWidth, fallback, range = [16, 34]) => {
@@ -6285,7 +6245,7 @@
6285
6245
  };
6286
6246
  };
6287
6247
  const getLayout = (spec, ctx) => {
6288
- var _a, _b, _c, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
6248
+ var _a, _b, _c, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
6289
6249
  const { width, height, startX, startY } = getRegionGeometry(ctx, spec);
6290
6250
  let blockWidth = resolveBlockWidth(spec, width);
6291
6251
  let blockHeight = (_b = (_a = spec.block) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : (isLandscape(spec) ? 320 : DEFAULT_BLOCK_HEIGHT);
@@ -6317,9 +6277,8 @@
6317
6277
  width: blockWidth,
6318
6278
  height: blockHeight
6319
6279
  },
6320
- gap: (_p = (_o = spec.block) === null || _o === void 0 ? void 0 : _o.gap) !== null && _p !== void 0 ? _p : DEFAULT_BLOCK_GAP,
6321
- padding: (_q = spec.block) === null || _q === void 0 ? void 0 : _q.padding,
6322
- lineDistance: (_r = spec.line) === null || _r === void 0 ? void 0 : _r.distance
6280
+ padding: (_o = spec.block) === null || _o === void 0 ? void 0 : _o.padding,
6281
+ lineDistance: (_p = spec.line) === null || _p === void 0 ? void 0 : _p.distance
6323
6282
  });
6324
6283
  if (!startX && !startY) {
6325
6284
  return result;
@@ -6584,7 +6543,7 @@
6584
6543
  }
6585
6544
  },
6586
6545
  block.title
6587
- ? Object.assign(Object.assign({ type: 'text', name: `storyline-clock-title-${index}`, interactive: false }, spec.title), { style: Object.assign({ x: (_d, ctx) => getClockTextRect(spec, ctx, index).x, y: (_d, ctx) => getClockTextRect(spec, ctx, index).anchorY - getTitleHeight(ctx), text: block.title, maxLineWidth: (_d, ctx) => getClockTextRect(spec, ctx, index).width, height: (_d, ctx) => getTitleHeight(ctx), heightLimit: (_d, ctx) => getTitleLineHeight(ctx) * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_d, ctx) => getTitleFontSize(ctx), lineHeight: (_d, ctx) => getTitleLineHeight(ctx), fontWeight: 'bold', fill: themeColor, stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: (_d, ctx) => getClockTextRect(spec, ctx, index).onLeft ? 'right' : 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...' }, (_b = spec.title) === null || _b === void 0 ? void 0 : _b.style) })
6546
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-clock-title-${index}`, interactive: false }, spec.title), { style: Object.assign({ x: (_d, ctx) => getClockTextRect(spec, ctx, index).x, y: (_d, ctx) => getClockTextRect(spec, ctx, index).anchorY - getTitleHeight(ctx), text: block.title, height: (_d, ctx) => getTitleHeight(ctx), heightLimit: (_d, ctx) => getTitleLineHeight(ctx) * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_d, ctx) => getTitleFontSize(ctx), lineHeight: (_d, ctx) => getTitleLineHeight(ctx), fontWeight: 'bold', fill: themeColor, stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: (_d, ctx) => getClockTextRect(spec, ctx, index).onLeft ? 'right' : 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...' }, (_b = spec.title) === null || _b === void 0 ? void 0 : _b.style) })
6588
6547
  : null,
6589
6548
  contentText.length
6590
6549
  ? Object.assign(Object.assign({ type: 'text', name: `storyline-clock-content-${index}`, interactive: false }, spec.content), { style: Object.assign({ x: (_d, ctx) => getClockTextRect(spec, ctx, index).x, y: (_d, ctx) => getClockTextRect(spec, ctx, index).anchorY + 4, width: (_d, ctx) => getClockTextRect(spec, ctx, index).width, height: CLOCK_CONTENT_LINE_HEIGHT * CLOCK_CONTENT_LINES, maxLineWidth: (_d, ctx) => getClockTextRect(spec, ctx, index).width, heightLimit: CLOCK_CONTENT_LINE_HEIGHT * CLOCK_CONTENT_LINES, text: buildPlainContent(contentText), fontSize: CLOCK_CONTENT_FONT_SIZE, lineHeight: CLOCK_CONTENT_LINE_HEIGHT, fill: '#3a3f4d', textAlign: (_d, ctx) => getClockTextRect(spec, ctx, index).onLeft ? 'right' : 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word' }, (_c = spec.content) === null || _c === void 0 ? void 0 : _c.style) })
@@ -6690,7 +6649,7 @@
6690
6649
  ? Object.assign(Object.assign({ type: 'image', name: `storyline-block-image-${index}`, interactive: false }, omitImageLayoutSpec(spec.image)), { style: Object.assign({ x: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).imageBox.x, y: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).imageBox.y, width: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).imageBox.width, height: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).imageBox.height, image: block.image }, (_e = spec.image) === null || _e === void 0 ? void 0 : _e.style) })
6691
6650
  : null,
6692
6651
  block.title
6693
- ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-title-${index}`, interactive: false }, spec.title), { style: Object.assign({ x: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).textBox.x, y: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).textBox.y, text: block.title, maxLineWidth: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).textBox.width, height: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).titleHeight, heightLimit: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).titleLineHeight * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).titleFontSize, lineHeight: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).titleLineHeight, fontWeight: 'bold', fill: '#1f2430', stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...' }, (_f = spec.title) === null || _f === void 0 ? void 0 : _f.style) })
6652
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-title-${index}`, interactive: false }, spec.title), { style: Object.assign({ x: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).textBox.x, y: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).textBox.y, text: block.title, height: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).titleHeight, heightLimit: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).titleLineHeight * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).titleFontSize, lineHeight: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).titleLineHeight, fontWeight: 'bold', fill: '#1f2430', stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...' }, (_f = spec.title) === null || _f === void 0 ? void 0 : _f.style) })
6694
6653
  : null,
6695
6654
  contentText.length
6696
6655
  ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-content-${index}`, interactive: false }, spec.content), { style: Object.assign({ x: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).textBox.x, y: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).contentBox.y, width: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).textBox.width, height: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).contentBox.height, text: buildPlainContent(contentText), maxLineWidth: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).textBox.width, heightLimit: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).contentBox.height, fontSize: 16, lineHeight: 23, textAlign: 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...', fill: '#596173' }, (_g = spec.content) === null || _g === void 0 ? void 0 : _g.style) })
@@ -6740,7 +6699,6 @@
6740
6699
 
6741
6700
  const LANDSCAPE_IMAGE_HEIGHT_RATIO = 0.42;
6742
6701
  const LANDSCAPE_CONNECTOR_GAP = 8;
6743
- const LANDSCAPE_CONNECTOR_ARROW_SIZE = 9;
6744
6702
  const LANDSCAPE_CONNECTOR_X_RATIO = 0.2;
6745
6703
  const LANDSCAPE_TEXT_GAP_FROM_CONNECTOR = 12;
6746
6704
  const LANDSCAPE_TITLE_LINE_HEIGHT = 34;
@@ -6975,23 +6933,18 @@
6975
6933
  stroke: connectorStroke,
6976
6934
  lineWidth: connectorLineWidth,
6977
6935
  lineDash: connectorDash,
6978
- fill: connectorStroke,
6936
+ fill: false,
6979
6937
  path: (_d, ctx) => {
6980
6938
  const m = getMetrics(ctx);
6981
- const tipSize = LANDSCAPE_CONNECTOR_ARROW_SIZE;
6982
6939
  const x = m.connector.x1;
6983
6940
  const y0 = m.connector.y1;
6984
6941
  const y1 = m.connector.y2;
6985
- const tipDir = y1 < y0 ? -1 : 1;
6986
- const baseY = y1 - tipDir * tipSize;
6987
- const dashLine = `M ${x} ${y0} L ${x} ${baseY}`;
6988
- const triangle = `M ${x - tipSize / 2} ${baseY} L ${x + tipSize / 2} ${baseY} L ${x} ${y1} Z`;
6989
- return `${dashLine} ${triangle}`;
6942
+ return `M ${x} ${y0} L ${x} ${y1}`;
6990
6943
  }
6991
6944
  }
6992
6945
  },
6993
6946
  block.title
6994
- ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-title-${index}`, interactive: false }, spec.title), { style: Object.assign({ x: (_d, ctx) => getMetrics(ctx).textBox.x, y: (_d, ctx) => getMetrics(ctx).textBox.y, text: block.title, maxLineWidth: (_d, ctx) => getMetrics(ctx).textBox.width, height: (_d, ctx) => getMetrics(ctx).titleHeight, heightLimit: (_d, ctx) => getMetrics(ctx).titleLineHeight * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_d, ctx) => getMetrics(ctx).titleFontSize, lineHeight: (_d, ctx) => getMetrics(ctx).titleLineHeight, fontWeight: 'bold', fill: '#1f2430', stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...' }, (_l = spec.title) === null || _l === void 0 ? void 0 : _l.style) })
6947
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-title-${index}`, interactive: false }, spec.title), { style: Object.assign({ x: (_d, ctx) => getMetrics(ctx).textBox.x, y: (_d, ctx) => getMetrics(ctx).textBox.y, text: block.title, height: (_d, ctx) => getMetrics(ctx).titleHeight, heightLimit: (_d, ctx) => getMetrics(ctx).titleLineHeight * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_d, ctx) => getMetrics(ctx).titleFontSize, lineHeight: (_d, ctx) => getMetrics(ctx).titleLineHeight, fontWeight: 'bold', fill: '#1f2430', stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...' }, (_l = spec.title) === null || _l === void 0 ? void 0 : _l.style) })
6995
6948
  : null,
6996
6949
  contentText.length
6997
6950
  ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-content-${index}`, interactive: false }, spec.content), { style: Object.assign({ x: (_d, ctx) => getMetrics(ctx).contentBox.x, y: (_d, ctx) => getMetrics(ctx).contentBox.y, width: (_d, ctx) => getMetrics(ctx).contentBox.width, height: (_d, ctx) => getMetrics(ctx).contentBox.height, maxLineWidth: (_d, ctx) => getMetrics(ctx).contentBox.width, heightLimit: (_d, ctx) => getMetrics(ctx).contentBox.height, text: buildPlainContent(contentText), fontSize: (_d, ctx) => getMetrics(ctx).contentFontSize, lineHeight: (_d, ctx) => getMetrics(ctx).contentLineHeight, textAlign: 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...', fill: '#596173' }, (_m = spec.content) === null || _m === void 0 ? void 0 : _m.style) })
@@ -7234,7 +7187,7 @@
7234
7187
  ? Object.assign(Object.assign({ type: 'image', name: `storyline-block-image-${index}`, interactive: false }, omitImageLayoutSpec(spec.image)), { style: Object.assign({ x: (_d, ctx) => getMetrics(ctx).imageBox.x, y: (_d, ctx) => getMetrics(ctx).imageBox.y, width: (_d, ctx) => getMetrics(ctx).imageBox.width, height: (_d, ctx) => getMetrics(ctx).imageBox.height, image: block.image, repeatX: 'no-repeat', repeatY: 'no-repeat', imageMode: 'contain', imagePosition: 'center' }, (_e = spec.image) === null || _e === void 0 ? void 0 : _e.style) })
7235
7188
  : null,
7236
7189
  block.title
7237
- ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-title-${index}`, interactive: false }, spec.title), { style: Object.assign({ x: (_d, ctx) => getMetrics(ctx).textBox.x, y: (_d, ctx) => getMetrics(ctx).textBox.y, text: block.title, maxLineWidth: (_d, ctx) => getMetrics(ctx).textBox.width, height: (_d, ctx) => getMetrics(ctx).titleHeight, heightLimit: (_d, ctx) => getMetrics(ctx).titleLineHeight * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_d, ctx) => getMetrics(ctx).titleFontSize, lineHeight: (_d, ctx) => getMetrics(ctx).titleLineHeight, fontWeight: 'bold', fill: '#1f2430', stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...' }, (_f = spec.title) === null || _f === void 0 ? void 0 : _f.style) })
7190
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-title-${index}`, interactive: false }, spec.title), { style: Object.assign({ x: (_d, ctx) => getMetrics(ctx).textBox.x, y: (_d, ctx) => getMetrics(ctx).textBox.y, text: block.title, height: (_d, ctx) => getMetrics(ctx).titleHeight, heightLimit: (_d, ctx) => getMetrics(ctx).titleLineHeight * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_d, ctx) => getMetrics(ctx).titleFontSize, lineHeight: (_d, ctx) => getMetrics(ctx).titleLineHeight, fontWeight: 'bold', fill: '#1f2430', stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...' }, (_f = spec.title) === null || _f === void 0 ? void 0 : _f.style) })
7238
7191
  : null,
7239
7192
  contentText.length
7240
7193
  ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-content-${index}`, interactive: false }, spec.content), { style: Object.assign({ x: (_d, ctx) => getMetrics(ctx).contentBox.x, y: (_d, ctx) => getMetrics(ctx).contentBox.y, width: (_d, ctx) => getMetrics(ctx).contentBox.width, height: (_d, ctx) => getMetrics(ctx).contentBox.height, maxLineWidth: (_d, ctx) => getMetrics(ctx).contentBox.width, heightLimit: (_d, ctx) => getMetrics(ctx).contentBox.height, text: buildPlainContent(contentText), fontSize: PORTRAIT_CONTENT_FONT_SIZE, lineHeight: PORTRAIT_CONTENT_LINE_HEIGHT, textAlign: 'left', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...', fill: '#596173' }, (_g = spec.content) === null || _g === void 0 ? void 0 : _g.style) })
@@ -7262,7 +7215,7 @@
7262
7215
  const ARC_TITLE_IMAGE_HEIGHT_RATIO = 0.34;
7263
7216
  const ARC_GAP_FROM_TITLE_IMAGE = 200;
7264
7217
  const ARC_FIT_MARGIN = 8;
7265
- const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
7218
+ const clamp$1 = (value, min, max) => Math.max(min, Math.min(max, value));
7266
7219
  const isDownArc = (spec) => normalizeLayout(spec.layout).direction === 'down';
7267
7220
  const getArcTitleImageRect = (spec, ctx) => {
7268
7221
  var _a, _b, _c, _e;
@@ -7473,25 +7426,25 @@
7473
7426
  const regionWidth = Math.max((_c = region === null || region === void 0 ? void 0 : region.width) !== null && _c !== void 0 ? _c : Number((_e = spec.width) !== null && _e !== void 0 ? _e : ARC_BLOCK_IMAGE_SIZE * count), 1);
7474
7427
  const regionHeight = Math.max((_f = region === null || region === void 0 ? void 0 : region.height) !== null && _f !== void 0 ? _f : Number((_g = spec.height) !== null && _g !== void 0 ? _g : ARC_TEXT_BOX_HEIGHT), 1);
7475
7428
  const slotWidth = regionWidth / (count + 1);
7476
- const imageScale = clamp(Math.min(regionWidth / Math.max(count * ARC_BLOCK_IMAGE_SIZE * 0.92, 1), regionHeight / 620), 0.42, 1);
7477
- const textScale = clamp(Math.min(slotWidth / 180, imageScale), 0.48, 1);
7429
+ const imageScale = clamp$1(Math.min(regionWidth / Math.max(count * ARC_BLOCK_IMAGE_SIZE * 0.92, 1), regionHeight / 620), 0.42, 1);
7430
+ const textScale = clamp$1(Math.min(slotWidth / 180, imageScale), 0.48, 1);
7478
7431
  const styleContent = (_h = spec.content) === null || _h === void 0 ? void 0 : _h.style;
7479
7432
  const contentFontSize = Number((_j = styleContent === null || styleContent === void 0 ? void 0 : styleContent.fontSize) !== null && _j !== void 0 ? _j : Math.round(ARC_CONTENT_FONT_SIZE * textScale));
7480
7433
  const contentLineHeight = Number((_k = styleContent === null || styleContent === void 0 ? void 0 : styleContent.lineHeight) !== null && _k !== void 0 ? _k : Math.round(Math.max(contentFontSize * 1.35, ARC_CONTENT_LINE_HEIGHT * textScale)));
7481
7434
  const titleToContentGap = ARC_TITLE_TO_CONTENT_GAP;
7482
7435
  const configuredImageDiameter = Math.max((_m = (_l = spec.image) === null || _l === void 0 ? void 0 : _l.width) !== null && _m !== void 0 ? _m : ARC_BLOCK_IMAGE_SIZE, (_p = (_o = spec.image) === null || _o === void 0 ? void 0 : _o.height) !== null && _p !== void 0 ? _p : ARC_BLOCK_IMAGE_SIZE);
7483
- const imageDiameter = Math.round(clamp(configuredImageDiameter * imageScale, 64, configuredImageDiameter));
7436
+ const imageDiameter = Math.round(clamp$1(configuredImageDiameter * imageScale, 64, configuredImageDiameter));
7484
7437
  const imageWidth = imageDiameter;
7485
7438
  const imageHeight = imageDiameter;
7486
7439
  const isDown = isDownArc(spec);
7487
7440
  const configuredTextWidth = Number((_r = (_q = spec.block) === null || _q === void 0 ? void 0 : _q.width) !== null && _r !== void 0 ? _r : ARC_TEXT_BOX_MAX_WIDTH);
7488
7441
  const defaultTextWidth = Math.round(slotWidth * 0.96);
7489
7442
  const minTextWidth = Math.min(ARC_TEXT_BOX_MIN_WIDTH, Math.max(Math.round(slotWidth * 0.72), ARC_TEXT_BOX_ABSOLUTE_MIN_WIDTH));
7490
- const textBoxWidth = Math.round(clamp(Math.min(configuredTextWidth, defaultTextWidth), minTextWidth, ARC_TEXT_BOX_MAX_WIDTH));
7443
+ const textBoxWidth = Math.round(clamp$1(Math.min(configuredTextWidth, defaultTextWidth), minTextWidth, ARC_TEXT_BOX_MAX_WIDTH));
7491
7444
  const titleFontSize = resolveTitleFontSize(spec, ctx, (_t = (_s = spec.data) === null || _s === void 0 ? void 0 : _s[index]) === null || _t === void 0 ? void 0 : _t.title, textBoxWidth, Math.round(ARC_TITLE_FONT_SIZE * textScale), [10, 40]);
7492
7445
  const titleLineHeight = resolveAdaptiveLineHeight(titleFontSize, (_u = spec.title) === null || _u === void 0 ? void 0 : _u.style, ARC_TITLE_LINE_HEIGHT);
7493
7446
  const titleHeight = getBlockTitleHeight(titleLineHeight, (_w = (_v = spec.data) === null || _v === void 0 ? void 0 : _v[index]) === null || _w === void 0 ? void 0 : _w.title, textBoxWidth, titleFontSize);
7494
- const textHeight = Math.round(clamp(ARC_TEXT_BOX_HEIGHT * textScale, 88, ARC_TEXT_BOX_HEIGHT));
7447
+ const textHeight = Math.round(clamp$1(ARC_TEXT_BOX_HEIGHT * textScale, 88, ARC_TEXT_BOX_HEIGHT));
7495
7448
  const contentHeight = Math.max(textHeight - titleHeight - titleToContentGap, contentLineHeight);
7496
7449
  const isLeftSide = index < count / 2;
7497
7450
  const textAlign = isLeftSide ? 'right' : 'left';
@@ -7598,7 +7551,7 @@
7598
7551
  }
7599
7552
  : null,
7600
7553
  block.title
7601
- ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-title-${index}`, interactive: false, zIndex: vchart.LayoutZIndex.Mark + 5 }, spec.title), { style: Object.assign({ x: (_d, ctx) => getMetrics(ctx).textAnchorX, y: (_d, ctx) => getMetrics(ctx).textBox.y, text: block.title, maxLineWidth: (_d, ctx) => getMetrics(ctx).textBox.width, height: (_d, ctx) => getMetrics(ctx).titleLineHeight * BLOCK_TITLE_MAX_LINES, heightLimit: (_d, ctx) => getMetrics(ctx).titleLineHeight * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_d, ctx) => getMetrics(ctx).titleFontSize, lineHeight: (_d, ctx) => getMetrics(ctx).titleLineHeight, fontWeight: 'bold', fill: '#1f2430', stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: (_d, ctx) => getMetrics(ctx).textAlign, textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...' }, (_c = spec.title) === null || _c === void 0 ? void 0 : _c.style) })
7554
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-title-${index}`, interactive: false, zIndex: vchart.LayoutZIndex.Mark + 5 }, spec.title), { style: Object.assign({ x: (_d, ctx) => getMetrics(ctx).textAnchorX, y: (_d, ctx) => getMetrics(ctx).textBox.y, text: block.title, height: (_d, ctx) => getMetrics(ctx).titleLineHeight * BLOCK_TITLE_MAX_LINES, heightLimit: (_d, ctx) => getMetrics(ctx).titleLineHeight * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_d, ctx) => getMetrics(ctx).titleFontSize, lineHeight: (_d, ctx) => getMetrics(ctx).titleLineHeight, fontWeight: 'bold', fill: '#1f2430', stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: (_d, ctx) => getMetrics(ctx).textAlign, textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...' }, (_c = spec.title) === null || _c === void 0 ? void 0 : _c.style) })
7602
7555
  : null,
7603
7556
  contentText.length
7604
7557
  ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-content-${index}`, interactive: false, zIndex: vchart.LayoutZIndex.Mark + 4 }, spec.content), { style: Object.assign({ x: (_d, ctx) => getMetrics(ctx).textAnchorX, y: (_d, ctx) => getMetrics(ctx).contentBox.y, width: (_d, ctx) => getMetrics(ctx).contentBox.width, height: (_d, ctx) => getMetrics(ctx).contentBox.height, maxLineWidth: (_d, ctx) => getMetrics(ctx).contentBox.width, heightLimit: (_d, ctx) => getMetrics(ctx).contentBox.height, text: buildPlainContent(contentText), fontSize: (_d, ctx) => getMetrics(ctx).contentFontSize, lineHeight: (_d, ctx) => getMetrics(ctx).contentLineHeight, textAlign: (_d, ctx) => getMetrics(ctx).textAlign, textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...', fill: '#596173' }, (_e = spec.content) === null || _e === void 0 ? void 0 : _e.style) })
@@ -7610,16 +7563,107 @@
7610
7563
  const WING_BLOCK_IMAGE_SIZE = 160;
7611
7564
  const WING_TITLE_LINE_HEIGHT = 30;
7612
7565
  const WING_TITLE_FONT_SIZE = 22;
7566
+ const WING_TITLE_MIN_FONT_SIZE = 14;
7567
+ const WING_TITLE_MAX_FONT_SIZE = 30;
7613
7568
  const WING_CONTENT_LINE_HEIGHT = 17;
7614
7569
  const WING_CONTENT_FONT_SIZE = 12;
7615
7570
  const WING_TEXT_BOX_WIDTH = 240;
7571
+ const WING_TEXT_BOX_MIN_WIDTH = 240;
7572
+ const WING_TEXT_BOX_MAX_WIDTH = 360;
7573
+ const WING_TEXT_BOX_WIDTH_RATIO = 0.24;
7616
7574
  const WING_TEXT_BOX_HEIGHT = 110;
7617
7575
  const WING_TITLE_TO_CONTENT_GAP = 4;
7618
7576
  const WING_TITLE_IMAGE_WIDTH_RATIO = 0.6;
7619
7577
  const WING_TITLE_IMAGE_MAX_WIDTH = 820;
7578
+ const WING_DEFAULT_PATH_END_WIDTH = 350;
7579
+ const WING_IMAGE_MIN_SCALE = 0.52;
7580
+ const WING_IMAGE_MAX_SCALE = 1.2;
7581
+ const WING_BOTTOM_TEXT_IMAGE_GAP_RATIO = 1.35;
7582
+ const WING_PATH_EDGE_GAP = 8;
7583
+ const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
7620
7584
  const getWingDirection = (spec) => {
7621
7585
  return normalizeLayout(spec.layout).direction === 'right' ? 'right' : 'left';
7622
7586
  };
7587
+ const getWingPathWidthRange = (spec) => {
7588
+ var _a, _b, _c, _e, _f;
7589
+ const lineStyle = ((_b = (_a = spec.line) === null || _a === void 0 ? void 0 : _a.style) !== null && _b !== void 0 ? _b : {});
7590
+ const startWidth = Math.max(Number((_c = lineStyle.startWidth) !== null && _c !== void 0 ? _c : 50), 0.5);
7591
+ const endWidth = Math.max(Number((_f = (_e = lineStyle.endWidth) !== null && _e !== void 0 ? _e : lineStyle.lineWidth) !== null && _f !== void 0 ? _f : WING_DEFAULT_PATH_END_WIDTH), startWidth);
7592
+ return { startWidth, endWidth };
7593
+ };
7594
+ const getWingBlockPathRatio = (spec, index) => {
7595
+ var _a, _b;
7596
+ const count = (_b = (_a = spec.data) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
7597
+ if (count <= 1) {
7598
+ return 0.5;
7599
+ }
7600
+ return index / (count - 1);
7601
+ };
7602
+ const getWingBlockImageScale = (spec, index) => {
7603
+ const { startWidth, endWidth } = getWingPathWidthRange(spec);
7604
+ const startScale = clamp(startWidth / WING_DEFAULT_PATH_END_WIDTH, WING_IMAGE_MIN_SCALE, WING_IMAGE_MAX_SCALE);
7605
+ const endScale = clamp(endWidth / WING_DEFAULT_PATH_END_WIDTH, WING_IMAGE_MIN_SCALE, WING_IMAGE_MAX_SCALE);
7606
+ return startScale + (endScale - startScale) * getWingBlockPathRatio(spec, index);
7607
+ };
7608
+ const getConfiguredTextBoxWidth = (spec) => {
7609
+ var _a, _b, _c;
7610
+ const style = (_a = spec.title) === null || _a === void 0 ? void 0 : _a.style;
7611
+ const width = Number((_c = (_b = style === null || style === void 0 ? void 0 : style.width) !== null && _b !== void 0 ? _b : style === null || style === void 0 ? void 0 : style.maxLineWidth) !== null && _c !== void 0 ? _c : WING_TEXT_BOX_WIDTH);
7612
+ return Number.isFinite(width) && width > 0 ? width : WING_TEXT_BOX_WIDTH;
7613
+ };
7614
+ const getWingTextBoxWidth = (spec, ctx) => {
7615
+ const { width } = getRegionGeometry(ctx, spec);
7616
+ const configuredWidth = getConfiguredTextBoxWidth(spec);
7617
+ const adaptiveWidth = Math.max(configuredWidth, Math.round(width * WING_TEXT_BOX_WIDTH_RATIO));
7618
+ return clamp(adaptiveWidth, WING_TEXT_BOX_MIN_WIDTH, WING_TEXT_BOX_MAX_WIDTH);
7619
+ };
7620
+ const estimateTextWidth = (text, fontSize) => Array.from(text).reduce((sum, char) => {
7621
+ if (char.trim().length === 0) {
7622
+ return sum + fontSize * 0.32;
7623
+ }
7624
+ return sum + fontSize * (char.charCodeAt(0) > 255 ? 1.05 : 0.62);
7625
+ }, 0);
7626
+ const measureWingTitleWidth = (title, fontSize, style) => {
7627
+ var _a;
7628
+ if (!title) {
7629
+ return 0;
7630
+ }
7631
+ try {
7632
+ const size = vchart.measureText(title, {
7633
+ fontSize,
7634
+ fontFamily: style.fontFamily,
7635
+ fontWeight: (_a = style.fontWeight) !== null && _a !== void 0 ? _a : 'bold'
7636
+ });
7637
+ return Number.isFinite(size.width) && size.width > 0 ? size.width : estimateTextWidth(title, fontSize);
7638
+ }
7639
+ catch (_err) {
7640
+ return estimateTextWidth(title, fontSize);
7641
+ }
7642
+ };
7643
+ const getMeasuredTitleLineCount = (title, fontSize, textWidth, style) => {
7644
+ if (!title) {
7645
+ return 0;
7646
+ }
7647
+ const measuredWidth = measureWingTitleWidth(title, fontSize, style);
7648
+ return Math.max(1, Math.min(BLOCK_TITLE_MAX_LINES, Math.ceil(measuredWidth / Math.max(textWidth * 0.96, 1))));
7649
+ };
7650
+ const resolveWingTitleFontSize = (spec, index, textWidth) => {
7651
+ var _a, _b, _c, _e;
7652
+ const style = ((_b = (_a = spec.title) === null || _a === void 0 ? void 0 : _a.style) !== null && _b !== void 0 ? _b : {});
7653
+ const configuredFontSize = style.fontSize;
7654
+ if (configuredFontSize != null) {
7655
+ return Number(configuredFontSize);
7656
+ }
7657
+ const title = (_e = (_c = spec.data) === null || _c === void 0 ? void 0 : _c[index]) === null || _e === void 0 ? void 0 : _e.title;
7658
+ const measuredWidth = measureWingTitleWidth(title, WING_TITLE_FONT_SIZE, style);
7659
+ if (!measuredWidth) {
7660
+ return WING_TITLE_FONT_SIZE;
7661
+ }
7662
+ const widthLimit = textWidth * BLOCK_TITLE_MAX_LINES * 0.96;
7663
+ const measuredPerFont = measuredWidth / WING_TITLE_FONT_SIZE;
7664
+ const fittedFontSize = Math.floor(widthLimit / Math.max(measuredPerFont, 1));
7665
+ return clamp(fittedFontSize, WING_TITLE_MIN_FONT_SIZE, WING_TITLE_MAX_FONT_SIZE);
7666
+ };
7623
7667
  const getWingArcGeometry = (spec, ctx) => {
7624
7668
  var _a, _b, _c;
7625
7669
  const { width, height, startX, startY } = getRegionGeometry(ctx);
@@ -7632,10 +7676,15 @@
7632
7676
  const startAngle = (_a = layoutOpt.startAngle) !== null && _a !== void 0 ? _a : defaultStart;
7633
7677
  const endAngle = (_b = layoutOpt.endAngle) !== null && _b !== void 0 ? _b : defaultEnd;
7634
7678
  const ratio = (_c = layoutOpt.radiusRatio) !== null && _c !== void 0 ? _c : 0.92;
7635
- const ry = (innerHeight / 2) * ratio;
7679
+ const { startWidth, endWidth } = getWingPathWidthRange(spec);
7680
+ const topPathWidth = direction === 'right' ? endWidth : startWidth;
7681
+ const pathTopInset = Math.min(Math.max(innerHeight / 2 - 1, 0), Math.ceil(topPathWidth / 2 + WING_PATH_EDGE_GAP));
7682
+ const arcHeight = Math.max(innerHeight - pathTopInset, 1);
7683
+ const ry = (arcHeight / 2) * ratio;
7636
7684
  const rx = innerWidth * 0.6 * ratio;
7685
+ const topSin = Math.min(Math.sin((startAngle / 180) * Math.PI), Math.sin((endAngle / 180) * Math.PI), 0);
7637
7686
  const cx = direction === 'right' ? startX + innerWidth - rx * 0.1 : startX + rx * 0.1;
7638
- const cy = startY + innerHeight / 2;
7687
+ const cy = startY + pathTopInset - topSin * ry;
7639
7688
  return { cx, cy, rx, ry, startAngle, endAngle };
7640
7689
  };
7641
7690
  const getWingBlockCenter = (spec, ctx, index) => {
@@ -7652,15 +7701,31 @@
7652
7701
  y: arc.cy + Math.sin(angle) * arc.ry
7653
7702
  };
7654
7703
  };
7704
+ const isWingBottomBlock = (spec, ctx, index) => {
7705
+ var _a, _b;
7706
+ const count = (_b = (_a = spec.data) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
7707
+ if (count <= 0) {
7708
+ return false;
7709
+ }
7710
+ let bottomIndex = 0;
7711
+ let bottomY = Number.NEGATIVE_INFINITY;
7712
+ for (let i = 0; i < count; i++) {
7713
+ const center = getWingBlockCenter(spec, ctx, i);
7714
+ if (center.y > bottomY) {
7715
+ bottomY = center.y;
7716
+ bottomIndex = i;
7717
+ }
7718
+ }
7719
+ return index === bottomIndex;
7720
+ };
7655
7721
  const buildWingArcMark = (spec) => {
7656
- var _a, _b, _c, _e, _f, _g, _h, _j;
7722
+ var _a, _b, _c, _e, _f;
7657
7723
  if (((_a = spec.line) === null || _a === void 0 ? void 0 : _a.visible) === false) {
7658
7724
  return null;
7659
7725
  }
7660
7726
  const themeColor = getThemeColor(spec);
7661
7727
  const lineStyle = ((_c = (_b = spec.line) === null || _b === void 0 ? void 0 : _b.style) !== null && _c !== void 0 ? _c : {});
7662
- const startWidth = Math.max(Number((_e = lineStyle.startWidth) !== null && _e !== void 0 ? _e : 50), 0.5);
7663
- const endWidth = Math.max(Number((_g = (_f = lineStyle.endWidth) !== null && _f !== void 0 ? _f : lineStyle.lineWidth) !== null && _g !== void 0 ? _g : 350), startWidth);
7728
+ const { startWidth, endWidth } = getWingPathWidthRange(spec);
7664
7729
  return {
7665
7730
  type: 'group',
7666
7731
  name: 'storyline-wing-arc',
@@ -7673,7 +7738,7 @@
7673
7738
  style: {
7674
7739
  stroke: false,
7675
7740
  lineWidth: 0,
7676
- fill: (_j = (_h = lineStyle.fill) !== null && _h !== void 0 ? _h : lineStyle.stroke) !== null && _j !== void 0 ? _j : themeColor,
7741
+ fill: (_f = (_e = lineStyle.fill) !== null && _e !== void 0 ? _e : lineStyle.stroke) !== null && _f !== void 0 ? _f : themeColor,
7677
7742
  opacity: 0.95,
7678
7743
  path: (_d, ctx) => {
7679
7744
  const arc = getWingArcGeometry(spec, ctx);
@@ -7727,7 +7792,29 @@
7727
7792
  name: 'storyline-wing-title-image',
7728
7793
  zIndex: vchart.LayoutZIndex.Mark + 8,
7729
7794
  children: [
7730
- Object.assign(Object.assign({ type: 'image', name: 'storyline-wing-title-image-node', interactive: false }, spec.titleImage), { style: Object.assign({ x: (_d, ctx) => {
7795
+ Object.assign(Object.assign({ type: 'rect', name: 'storyline-wing-title-image-node', interactive: false }, spec.titleImage), { _debug_bounds: true, style: Object.assign({ _debug_bounds: true, x: (_d, ctx) => {
7796
+ const { width, height, startX } = getChartGeometry(ctx, spec);
7797
+ const size = getTitleImageSize(spec, width, height, {
7798
+ widthRatio: WING_TITLE_IMAGE_WIDTH_RATIO,
7799
+ maxWidth: WING_TITLE_IMAGE_MAX_WIDTH
7800
+ });
7801
+ return getWingDirection(spec) === 'right' ? startX : startX + width - size.width;
7802
+ }, fill: 'red', y: (_d, ctx) => {
7803
+ return getChartGeometry(ctx, spec).startY + 12;
7804
+ }, width: (_d, ctx) => {
7805
+ const { width, height } = getChartGeometry(ctx, spec);
7806
+ return getTitleImageSize(spec, width, height, {
7807
+ widthRatio: WING_TITLE_IMAGE_WIDTH_RATIO,
7808
+ maxWidth: WING_TITLE_IMAGE_MAX_WIDTH
7809
+ }).width;
7810
+ }, height: (_d, ctx) => {
7811
+ const { width, height } = getChartGeometry(ctx, spec);
7812
+ return getTitleImageSize(spec, width, height, {
7813
+ widthRatio: WING_TITLE_IMAGE_WIDTH_RATIO,
7814
+ maxWidth: WING_TITLE_IMAGE_MAX_WIDTH
7815
+ }).height;
7816
+ }, image: spec.titleImage.image, repeatX: 'no-repeat', repeatY: 'no-repeat', imageMode: 'contain', imagePosition: 'center' }, spec.titleImage.style) }),
7817
+ Object.assign(Object.assign({ type: 'image', name: 'storyline-wing-title-image-node', interactive: false }, spec.titleImage), { _debug_bounds: true, style: Object.assign({ _debug_bounds: true, x: (_d, ctx) => {
7731
7818
  const { width, height, startX } = getChartGeometry(ctx, spec);
7732
7819
  const size = getTitleImageSize(spec, width, height, {
7733
7820
  widthRatio: WING_TITLE_IMAGE_WIDTH_RATIO,
@@ -7754,17 +7841,20 @@
7754
7841
  };
7755
7842
  const WING_TEXT_IMAGE_GAP = 120;
7756
7843
  const getWingBlockMetrics = (spec, ctx, index) => {
7757
- var _a, _b, _c, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
7758
- const titleFontSize = resolveTitleFontSize(spec, ctx, (_b = (_a = spec.data) === null || _a === void 0 ? void 0 : _a[index]) === null || _b === void 0 ? void 0 : _b.title, WING_TEXT_BOX_WIDTH, WING_TITLE_FONT_SIZE, [8, 30]);
7759
- const titleLineHeight = resolveAdaptiveLineHeight(titleFontSize, (_c = spec.title) === null || _c === void 0 ? void 0 : _c.style, WING_TITLE_LINE_HEIGHT, 1.3);
7760
- const titleHeight = getBlockTitleHeight(titleLineHeight, (_f = (_e = spec.data) === null || _e === void 0 ? void 0 : _e[index]) === null || _f === void 0 ? void 0 : _f.title, WING_TEXT_BOX_WIDTH, titleFontSize);
7761
- const contentFontSize = Number((_j = (_h = (_g = spec.content) === null || _g === void 0 ? void 0 : _g.style) === null || _h === void 0 ? void 0 : _h.fontSize) !== null && _j !== void 0 ? _j : WING_CONTENT_FONT_SIZE);
7762
- const contentLineHeight = Number((_m = (_l = (_k = spec.content) === null || _k === void 0 ? void 0 : _k.style) === null || _l === void 0 ? void 0 : _l.lineHeight) !== null && _m !== void 0 ? _m : WING_CONTENT_LINE_HEIGHT);
7844
+ var _a, _b, _c, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
7845
+ const textWidth = getWingTextBoxWidth(spec, ctx);
7846
+ const titleStyle = ((_b = (_a = spec.title) === null || _a === void 0 ? void 0 : _a.style) !== null && _b !== void 0 ? _b : {});
7847
+ const titleFontSize = resolveWingTitleFontSize(spec, index, textWidth);
7848
+ const titleLineHeight = resolveAdaptiveLineHeight(titleFontSize, titleStyle, WING_TITLE_LINE_HEIGHT, 1.3);
7849
+ const titleHeight = titleLineHeight * getMeasuredTitleLineCount((_e = (_c = spec.data) === null || _c === void 0 ? void 0 : _c[index]) === null || _e === void 0 ? void 0 : _e.title, titleFontSize, textWidth, titleStyle);
7850
+ const contentFontSize = Number((_h = (_g = (_f = spec.content) === null || _f === void 0 ? void 0 : _f.style) === null || _g === void 0 ? void 0 : _g.fontSize) !== null && _h !== void 0 ? _h : WING_CONTENT_FONT_SIZE);
7851
+ const contentLineHeight = Number((_l = (_k = (_j = spec.content) === null || _j === void 0 ? void 0 : _j.style) === null || _k === void 0 ? void 0 : _k.lineHeight) !== null && _l !== void 0 ? _l : WING_CONTENT_LINE_HEIGHT);
7763
7852
  const titleToContentGap = WING_TITLE_TO_CONTENT_GAP;
7764
7853
  const textHeight = WING_TEXT_BOX_HEIGHT;
7765
7854
  const contentHeight = 100000;
7766
- const imageWidth = Number((_p = (_o = spec.image) === null || _o === void 0 ? void 0 : _o.width) !== null && _p !== void 0 ? _p : WING_BLOCK_IMAGE_SIZE);
7767
- const imageHeight = Number((_r = (_q = spec.image) === null || _q === void 0 ? void 0 : _q.height) !== null && _r !== void 0 ? _r : WING_BLOCK_IMAGE_SIZE);
7855
+ const imageScale = getWingBlockImageScale(spec, index);
7856
+ const imageWidth = Math.round(Number((_o = (_m = spec.image) === null || _m === void 0 ? void 0 : _m.width) !== null && _o !== void 0 ? _o : WING_BLOCK_IMAGE_SIZE) * imageScale);
7857
+ const imageHeight = Math.round(Number((_q = (_p = spec.image) === null || _p === void 0 ? void 0 : _p.height) !== null && _q !== void 0 ? _q : WING_BLOCK_IMAGE_SIZE) * imageScale);
7768
7858
  const imageBox = {
7769
7859
  x: -imageWidth / 2,
7770
7860
  y: -imageHeight / 2,
@@ -7772,16 +7862,36 @@
7772
7862
  height: imageHeight
7773
7863
  };
7774
7864
  const direction = getWingDirection(spec);
7775
- const count = (_t = (_s = spec.data) === null || _s === void 0 ? void 0 : _s.length) !== null && _t !== void 0 ? _t : 0;
7865
+ const count = (_s = (_r = spec.data) === null || _r === void 0 ? void 0 : _r.length) !== null && _s !== void 0 ? _s : 0;
7776
7866
  const isSpecialBelow = (direction === 'right' && count > 0 && index === count - 1) || (direction === 'left' && index === 0);
7777
- const isVerticalLayout = isSpecialBelow;
7778
- const textWidth = WING_TEXT_BOX_WIDTH;
7867
+ const isBottomAbove = isWingBottomBlock(spec, ctx, index);
7868
+ const isVerticalLayout = isBottomAbove || isSpecialBelow;
7779
7869
  let textBox;
7780
7870
  let contentBox;
7781
7871
  let connectorBox;
7782
7872
  let onLeft;
7783
7873
  let verticalAlign;
7784
- if (isVerticalLayout) {
7874
+ if (isBottomAbove) {
7875
+ const bottomTextImageGap = Math.round(WING_TEXT_IMAGE_GAP * WING_BOTTOM_TEXT_IMAGE_GAP_RATIO);
7876
+ const textX = -textWidth / 2;
7877
+ const textY = -imageHeight / 2 - bottomTextImageGap - textHeight;
7878
+ textBox = { x: textX, y: textY, width: textWidth, height: textHeight };
7879
+ contentBox = {
7880
+ x: textX,
7881
+ y: textY + titleHeight + titleToContentGap,
7882
+ width: textWidth,
7883
+ height: contentHeight
7884
+ };
7885
+ connectorBox = {
7886
+ x: -1,
7887
+ y: textY + textHeight,
7888
+ width: 2,
7889
+ height: bottomTextImageGap
7890
+ };
7891
+ onLeft = false;
7892
+ verticalAlign = 'above';
7893
+ }
7894
+ else if (isVerticalLayout) {
7785
7895
  const textX = -textWidth / 2;
7786
7896
  const textY = imageHeight / 2 + WING_TEXT_IMAGE_GAP;
7787
7897
  textBox = { x: textX, y: textY, width: textWidth, height: textHeight };
@@ -7889,7 +7999,7 @@
7889
7999
  return m.textBox.x + m.textBox.width / 2;
7890
8000
  }
7891
8001
  return m.onLeft ? m.textBox.x + m.textBox.width : m.textBox.x;
7892
- }, y: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).textBox.y, text: block.title, maxLineWidth: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).textBox.width, height: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).titleHeight, heightLimit: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).titleLineHeight * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).titleFontSize, lineHeight: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).titleLineHeight, fontWeight: 'bold', fill: themeColor, stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: (_d, ctx) => {
8002
+ }, y: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).textBox.y, width: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).textBox.width, maxLineWidth: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).textBox.width, text: block.title, height: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).titleHeight, heightLimit: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).titleLineHeight * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).titleFontSize, lineHeight: (_d, ctx) => getWingBlockMetrics(spec, ctx, index).titleLineHeight, fontWeight: 'bold', fill: themeColor, stroke: '#fff', lineWidth: 5, lineJoin: 'round', textAlign: (_d, ctx) => {
7893
8003
  const m = getWingBlockMetrics(spec, ctx, index);
7894
8004
  if (m.verticalAlign) {
7895
8005
  return 'center';
@@ -7916,194 +8026,6 @@
7916
8026
  };
7917
8027
  };
7918
8028
 
7919
- const LADDER_HEADLINE_FONT_RATIO = 0.42;
7920
- const LADDER_HEADLINE_FONT_MIN = 80;
7921
- const LADDER_HEADLINE_FONT_MAX = 240;
7922
- const LADDER_DIAGONAL_LINE_WIDTH = 2;
7923
- const LADDER_DIAGONAL_DASH = [12, 8];
7924
- const LADDER_BLOCK_IMAGE_SIZE = 100;
7925
- const LADDER_TITLE_FONT_SIZE = 28;
7926
- const LADDER_TITLE_LINE_HEIGHT = 26;
7927
- const LADDER_CONTENT_FONT_SIZE = 16;
7928
- const LADDER_CONTENT_LINE_HEIGHT = 23;
7929
- const isDownLadder = (spec) => normalizeLayout(spec.layout).direction === 'down';
7930
- const getLadderDiagonalGeometry = (spec, ctx) => {
7931
- var _a;
7932
- const { width, height, startX, startY } = getRegionGeometry(ctx);
7933
- const padding = normalizePadding((_a = spec.block) === null || _a === void 0 ? void 0 : _a.padding);
7934
- const innerX = startX + padding.left;
7935
- const innerY = startY + padding.top;
7936
- const innerW = Math.max(width - padding.left - padding.right, 1);
7937
- const innerH = Math.max(height - padding.top - padding.bottom, 1);
7938
- const isDown = isDownLadder(spec);
7939
- const x0 = innerX;
7940
- const x1 = innerX + innerW;
7941
- const y0 = isDown ? innerY : innerY + innerH;
7942
- const y1 = isDown ? innerY + innerH : innerY;
7943
- const cx = (x0 + x1) / 2;
7944
- const cy = (y0 + y1) / 2;
7945
- const dx = x1 - x0;
7946
- const dy = y1 - y0;
7947
- const angleRad = (Math.atan2(dy, dx) / Math.PI) * 180;
7948
- const fontSize = Math.max(LADDER_HEADLINE_FONT_MIN, Math.min(LADDER_HEADLINE_FONT_MAX, Math.round(innerH * LADDER_HEADLINE_FONT_RATIO)));
7949
- return { x0, y0, x1, y1, cx, cy, angleRad, fontSize };
7950
- };
7951
- const getLadderHeadlineText = (spec) => {
7952
- var _a, _b;
7953
- const layoutOpt = normalizeLayout(spec.layout);
7954
- if (typeof layoutOpt.headline === 'string' && layoutOpt.headline.length > 0) {
7955
- return layoutOpt.headline;
7956
- }
7957
- const title = (_b = (_a = spec.title) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.text;
7958
- if (typeof title === 'string' && title.length > 0) {
7959
- return title;
7960
- }
7961
- return 'storyline';
7962
- };
7963
- const buildLadderDiagonalMark = (spec) => {
7964
- const themeColor = getThemeColor(spec);
7965
- return {
7966
- type: 'group',
7967
- name: 'storyline-ladder-diagonal',
7968
- zIndex: vchart.LayoutZIndex.Mark - 1,
7969
- children: [
7970
- {
7971
- type: 'path',
7972
- name: 'storyline-ladder-diagonal-line',
7973
- interactive: false,
7974
- style: {
7975
- path: (_d, ctx) => {
7976
- const g = getLadderDiagonalGeometry(spec, ctx);
7977
- return `M ${g.x0} ${g.y0} L ${g.x1} ${g.y1}`;
7978
- },
7979
- stroke: withAlpha(themeColor, 0.85),
7980
- lineWidth: LADDER_DIAGONAL_LINE_WIDTH,
7981
- lineDash: LADDER_DIAGONAL_DASH,
7982
- fill: 'transparent'
7983
- }
7984
- }
7985
- ]
7986
- };
7987
- };
7988
- const buildLadderHeadlineMark = (spec) => {
7989
- const text = getLadderHeadlineText(spec);
7990
- if (!text) {
7991
- return null;
7992
- }
7993
- const themeColor = getThemeColor(spec);
7994
- return {
7995
- type: 'group',
7996
- name: 'storyline-ladder-headline',
7997
- zIndex: vchart.LayoutZIndex.Mark,
7998
- style: {
7999
- x: (_d, ctx) => getLadderDiagonalGeometry(spec, ctx).cx,
8000
- y: (_d, ctx) => getLadderDiagonalGeometry(spec, ctx).cy,
8001
- angle: (_d, ctx) => getLadderDiagonalGeometry(spec, ctx).angleRad
8002
- },
8003
- children: [
8004
- {
8005
- type: 'text',
8006
- name: 'storyline-ladder-headline-text',
8007
- interactive: false,
8008
- style: {
8009
- x: 0,
8010
- y: 0,
8011
- text,
8012
- fontSize: (_d, ctx) => getLadderDiagonalGeometry(spec, ctx).fontSize,
8013
- fontWeight: 900,
8014
- fontFamily: 'Impact, "Arial Black", sans-serif',
8015
- fill: withAlpha(themeColor, 0.92),
8016
- textAlign: 'center',
8017
- textBaseline: 'middle'
8018
- }
8019
- }
8020
- ]
8021
- };
8022
- };
8023
- const isOnLeft = (index) => index % 2 === 1;
8024
- const getLadderBlockMetrics = (spec, ctx, index) => {
8025
- var _a, _b, _c, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
8026
- const block = getLayout(spec, ctx).blocks[index];
8027
- const padding = normalizePadding((_b = (_a = spec.block) === null || _a === void 0 ? void 0 : _a.padding) !== null && _b !== void 0 ? _b : 12);
8028
- const imagePosition = isOnLeft(index) ? 'right' : 'left';
8029
- const imageWidth = (_e = (_c = spec.image) === null || _c === void 0 ? void 0 : _c.width) !== null && _e !== void 0 ? _e : LADDER_BLOCK_IMAGE_SIZE;
8030
- const imageHeight = (_g = (_f = spec.image) === null || _f === void 0 ? void 0 : _f.height) !== null && _g !== void 0 ? _g : LADDER_BLOCK_IMAGE_SIZE;
8031
- const imageGap = (_j = (_h = spec.image) === null || _h === void 0 ? void 0 : _h.gap) !== null && _j !== void 0 ? _j : DEFAULT_IMAGE_GAP;
8032
- const hasImage = !!((_l = (_k = spec.data) === null || _k === void 0 ? void 0 : _k[index]) === null || _l === void 0 ? void 0 : _l.image);
8033
- const blockWidth = (_m = block === null || block === void 0 ? void 0 : block.width) !== null && _m !== void 0 ? _m : resolveBlockWidth(spec, 0);
8034
- const blockHeight = (_q = (_o = block === null || block === void 0 ? void 0 : block.height) !== null && _o !== void 0 ? _o : (_p = spec.block) === null || _p === void 0 ? void 0 : _p.height) !== null && _q !== void 0 ? _q : DEFAULT_BLOCK_HEIGHT;
8035
- const imageBox = getImageBox(imagePosition, blockWidth, blockHeight, padding, imageWidth, imageHeight, imageGap, hasImage);
8036
- const textBox = getTextBox(imagePosition, blockWidth, blockHeight, padding, imageWidth, imageHeight, imageGap, hasImage);
8037
- const titleFontSize = resolveTitleFontSize(spec, ctx, (_s = (_r = spec.data) === null || _r === void 0 ? void 0 : _r[index]) === null || _s === void 0 ? void 0 : _s.title, textBox.width, LADDER_TITLE_FONT_SIZE, [8, 34]);
8038
- const titleLineHeight = resolveAdaptiveLineHeight(titleFontSize, (_t = spec.title) === null || _t === void 0 ? void 0 : _t.style, LADDER_TITLE_LINE_HEIGHT, LADDER_TITLE_LINE_HEIGHT / LADDER_TITLE_FONT_SIZE);
8039
- const titleHeight = getBlockTitleHeight(titleLineHeight, (_v = (_u = spec.data) === null || _u === void 0 ? void 0 : _u[index]) === null || _v === void 0 ? void 0 : _v.title, textBox.width, titleFontSize);
8040
- const contentGap = ((_x = (_w = spec.data) === null || _w === void 0 ? void 0 : _w[index]) === null || _x === void 0 ? void 0 : _x.title) ? 8 : 0;
8041
- return {
8042
- block: { width: blockWidth, height: blockHeight },
8043
- titleFontSize,
8044
- titleLineHeight,
8045
- titleHeight,
8046
- imageBox,
8047
- textBox,
8048
- contentBox: {
8049
- y: textBox.y + titleHeight + contentGap,
8050
- height: Math.max(0, textBox.height - titleHeight - contentGap)
8051
- }
8052
- };
8053
- };
8054
- const buildLadderBlockMark = (spec, block, index) => {
8055
- var _a, _b, _c, _e, _f, _g, _h;
8056
- const hasImage = !!block.image;
8057
- const onLeft = isOnLeft(index);
8058
- const align = onLeft ? 'right' : 'left';
8059
- const contentText = Array.isArray(block.content) ? block.content : block.content ? [block.content] : [];
8060
- const showBackground = ((_a = spec.block) === null || _a === void 0 ? void 0 : _a.showBackground) === true;
8061
- const showImageBackground = shouldShowImageBackground(spec);
8062
- const getTitleX = (ctx) => {
8063
- const m = getLadderBlockMetrics(spec, ctx, index);
8064
- return align === 'right' ? m.textBox.x + m.textBox.width : m.textBox.x;
8065
- };
8066
- return {
8067
- type: 'group',
8068
- id: `storyline-block-${(_b = block.id) !== null && _b !== void 0 ? _b : index}`,
8069
- name: `storyline-block-${index}`,
8070
- zIndex: vchart.LayoutZIndex.Mark + 1,
8071
- style: {
8072
- x: (_d, ctx) => { var _a, _b; return (_b = (_a = getLayout(spec, ctx).blocks[index]) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0; },
8073
- y: (_d, ctx) => { var _a, _b; return (_b = (_a = getLayout(spec, ctx).blocks[index]) === null || _a === void 0 ? void 0 : _a.y) !== null && _b !== void 0 ? _b : 0; },
8074
- width: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).block.width,
8075
- height: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).block.height
8076
- },
8077
- children: [
8078
- showBackground
8079
- ? {
8080
- type: 'rect',
8081
- name: `storyline-block-bg-${index}`,
8082
- interactive: false,
8083
- style: Object.assign({ x: 0, y: 0, width: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).block.width, height: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).block.height, cornerRadius: 8, fill: '#ffffff', stroke: '#d7dce5', lineWidth: 1, shadowBlur: 6, shadowColor: 'rgba(0, 0, 0, 0.08)' }, (_c = spec.block) === null || _c === void 0 ? void 0 : _c.style)
8084
- }
8085
- : null,
8086
- showImageBackground
8087
- ? {
8088
- type: 'rect',
8089
- name: `storyline-block-image-bg-${index}`,
8090
- interactive: false,
8091
- style: Object.assign(Object.assign({ x: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).imageBox.x, y: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).imageBox.y, width: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).imageBox.width, height: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).imageBox.height, cornerRadius: 8 }, getImageBackgroundStyle(spec)), (_e = spec.block) === null || _e === void 0 ? void 0 : _e.style)
8092
- }
8093
- : null,
8094
- hasImage
8095
- ? Object.assign(Object.assign({ type: 'image', name: `storyline-block-image-${index}`, interactive: false }, omitImageLayoutSpec(spec.image)), { style: Object.assign({ x: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).imageBox.x, y: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).imageBox.y, width: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).imageBox.width, height: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).imageBox.height, image: block.image }, (_f = spec.image) === null || _f === void 0 ? void 0 : _f.style) })
8096
- : null,
8097
- block.title
8098
- ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-title-${index}`, interactive: false }, spec.title), { style: Object.assign(Object.assign({ x: (_d, ctx) => getTitleX(ctx), y: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).textBox.y, text: block.title, maxLineWidth: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).textBox.width, height: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).titleHeight, heightLimit: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).titleLineHeight * BLOCK_TITLE_MAX_LINES, lineClamp: BLOCK_TITLE_MAX_LINES, fontSize: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).titleFontSize, lineHeight: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).titleLineHeight, fontWeight: 'bold', fill: '#1f2430', stroke: '#fff', lineWidth: 5, lineJoin: 'round', textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...' }, (_g = spec.title) === null || _g === void 0 ? void 0 : _g.style), { textAlign: align }) })
8099
- : null,
8100
- contentText.length
8101
- ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-content-${index}`, interactive: false }, spec.content), { style: Object.assign(Object.assign({ x: (_d, ctx) => getTitleX(ctx), y: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).contentBox.y, width: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).textBox.width, height: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).contentBox.height, text: buildPlainContent(contentText), maxLineWidth: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).textBox.width, heightLimit: (_d, ctx) => getLadderBlockMetrics(spec, ctx, index).contentBox.height, fontSize: LADDER_CONTENT_FONT_SIZE, lineHeight: LADDER_CONTENT_LINE_HEIGHT, textBaseline: 'top', whiteSpace: 'normal', wordBreak: 'break-word', ellipsis: '...', fill: '#596173' }, (_h = spec.content) === null || _h === void 0 ? void 0 : _h.style), { textAlign: align }) })
8102
- : null
8103
- ].filter(Boolean)
8104
- };
8105
- };
8106
-
8107
8029
  class StorylineChartSpecTransformer extends vchart.CommonChartSpecTransformer {
8108
8030
  transformSpec(spec) {
8109
8031
  var _a;
@@ -8123,23 +8045,27 @@
8123
8045
  var _a, _b, _c, _d;
8124
8046
  const LARGE = 100;
8125
8047
  const SMALL = 20;
8048
+ const WING_BASE_PADDING = 40;
8049
+ const WING_DIRECTION_PADDING = 100;
8050
+ const WING_TITLE_IMAGE_BOTTOM = 4;
8126
8051
  const TEXT_RESERVE = 280;
8127
8052
  const arc = isArc(spec);
8128
8053
  const arcDown = arc && normalizeLayout(spec.layout).direction === 'down';
8129
8054
  const arcUp = arc && !arcDown;
8130
8055
  const portrait = isPortrait(spec);
8131
- const ladder = isLadder(spec);
8132
8056
  const wing = isWing(spec);
8057
+ const wingDirection = wing ? normalizeLayout(spec.layout).direction : undefined;
8058
+ const wingLeft = wing && wingDirection !== 'right';
8059
+ const wingRight = wing && wingDirection === 'right';
8060
+ const wingTopPadding = wingRight ? WING_DIRECTION_PADDING : WING_BASE_PADDING;
8061
+ const wingBottomPadding = wingLeft ? WING_DIRECTION_PADDING : WING_BASE_PADDING;
8133
8062
  const clock = isClock(spec);
8134
8063
  const topTitleImageReserve = (() => {
8135
8064
  var _a, _b, _c, _d;
8136
- if (arc ||
8137
- ladder ||
8138
- !((_a = spec.titleImage) === null || _a === void 0 ? void 0 : _a.image) ||
8139
- ((_b = spec.titleImage) === null || _b === void 0 ? void 0 : _b.visible) === false) {
8065
+ if (arc || !((_a = spec.titleImage) === null || _a === void 0 ? void 0 : _a.image) || ((_b = spec.titleImage) === null || _b === void 0 ? void 0 : _b.visible) === false) {
8140
8066
  return 0;
8141
8067
  }
8142
- return getTitleImageReservedHeight(spec, Number((_c = spec.width) !== null && _c !== void 0 ? _c : 1000), Number((_d = spec.height) !== null && _d !== void 0 ? _d : 600));
8068
+ return getTitleImageReservedHeight(spec, Number((_c = spec.width) !== null && _c !== void 0 ? _c : 1000), Number((_d = spec.height) !== null && _d !== void 0 ? _d : 600), wing ? { bottom: WING_TITLE_IMAGE_BOTTOM } : undefined);
8143
8069
  })();
8144
8070
  const portraitBottomReserve = (() => {
8145
8071
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
@@ -8161,39 +8087,13 @@
8161
8087
  const breath = 16;
8162
8088
  return Math.max(LARGE, Math.round(imageHeight / 2 + textGap + titleLineHeight + titleToContentGap + contentHeight + breath));
8163
8089
  })();
8164
- const ladderHorizontalPadding = (() => {
8165
- var _a, _b, _c, _d, _e, _f;
8166
- if (!ladder) {
8167
- return 0;
8168
- }
8169
- const blockWidth = (_b = (_a = spec.block) === null || _a === void 0 ? void 0 : _a.minWidth) !== null && _b !== void 0 ? _b : resolveBlockWidth(spec, 0);
8170
- const imageWidth = (_d = (_c = spec.image) === null || _c === void 0 ? void 0 : _c.width) !== null && _d !== void 0 ? _d : 96;
8171
- const imageGap = (_f = (_e = spec.image) === null || _e === void 0 ? void 0 : _e.gap) !== null && _f !== void 0 ? _f : DEFAULT_IMAGE_GAP;
8172
- const innerPadding = 12 * 2;
8173
- const contentWidth = Math.max(blockWidth - imageWidth - imageGap - innerPadding, DEFAULT_BLOCK_WIDTH * 0.5);
8174
- const ideal = Math.round(contentWidth * 2);
8175
- const canvasWidth = spec.width;
8176
- const cap = canvasWidth ? Math.floor(canvasWidth * 0.3) : ideal;
8177
- return Math.min(ideal, cap);
8178
- })();
8179
- const ladderVerticalPadding = (() => {
8180
- var _a, _b;
8181
- if (!ladder) {
8182
- return 0;
8183
- }
8184
- const blockHeight = (_b = (_a = spec.block) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : 132;
8185
- const ideal = Math.round(blockHeight * 3);
8186
- const canvasHeight = spec.height;
8187
- const cap = canvasHeight ? Math.floor(canvasHeight * 0.3) : ideal;
8188
- return Math.min(ideal, cap);
8189
- })();
8190
- const defaultTop = Math.max(topTitleImageReserve, clock ? 40 : ladder ? ladderVerticalPadding : arcDown ? 0 : arcUp ? TEXT_RESERVE : SMALL);
8090
+ const defaultTop = Math.max(topTitleImageReserve, clock ? 40 : wing ? wingTopPadding : arcDown ? 0 : arcUp ? TEXT_RESERVE : SMALL);
8191
8091
  const defaultBottom = clock
8192
8092
  ? 60
8193
8093
  : portrait
8194
8094
  ? portraitBottomReserve
8195
8095
  : wing
8196
- ? 300
8096
+ ? wingBottomPadding
8197
8097
  : arcUp
8198
8098
  ? 100
8199
8099
  : arcDown
@@ -8211,8 +8111,8 @@
8211
8111
  }
8212
8112
  return Math.round(canvasWidth / (count + 1));
8213
8113
  })();
8214
- const defaultLeft = clock ? 40 : ladder ? ladderHorizontalPadding : arcHorizontalPadding;
8215
- const defaultRight = clock ? 40 : ladder ? ladderHorizontalPadding : arcHorizontalPadding;
8114
+ const defaultLeft = clock ? 40 : arcHorizontalPadding;
8115
+ const defaultRight = clock ? 40 : arcHorizontalPadding;
8216
8116
  const p = spec.padding;
8217
8117
  if (p == null) {
8218
8118
  spec.padding = [defaultTop, defaultRight, defaultBottom, defaultLeft];
@@ -8261,11 +8161,6 @@
8261
8161
  const wingTitleImageMark = buildWingTitleImageMark(spec);
8262
8162
  return [arcMark, wingTitleImageMark, ...blockMarks].filter(Boolean);
8263
8163
  }
8264
- if (isLadder(spec)) {
8265
- const diagonalMark = buildLadderDiagonalMark(spec);
8266
- const headlineMark = buildLadderHeadlineMark(spec);
8267
- return [diagonalMark, headlineMark, ...blockMarks].filter(Boolean);
8268
- }
8269
8164
  return [titleImageMark, lineMark, ...blockMarks].filter(Boolean);
8270
8165
  };
8271
8166
  const buildLineMark = (spec) => {
@@ -8297,9 +8192,6 @@
8297
8192
  if (isWing(spec)) {
8298
8193
  return buildWingBlockMark(spec, block, index);
8299
8194
  }
8300
- if (isLadder(spec)) {
8301
- return buildLadderBlockMark(spec, block, index);
8302
- }
8303
8195
  return buildDefaultBlockMark(spec, block, index);
8304
8196
  };
8305
8197