@visactor/vchart-extension 2.1.0-alpha.13 → 2.1.0-alpha.15

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 (81) hide show
  1. package/build/index.js +1960 -0
  2. package/build/index.min.js +2 -2
  3. package/cjs/charts/storyline/index.d.ts +4 -0
  4. package/cjs/charts/storyline/index.js +22 -0
  5. package/cjs/charts/storyline/index.js.map +1 -0
  6. package/cjs/charts/storyline/interface.d.ts +59 -0
  7. package/cjs/charts/storyline/interface.js +6 -0
  8. package/cjs/charts/storyline/interface.js.map +1 -0
  9. package/cjs/charts/storyline/layout.d.ts +53 -0
  10. package/cjs/charts/storyline/layout.js +215 -0
  11. package/cjs/charts/storyline/layout.js.map +1 -0
  12. package/cjs/charts/storyline/layouts/bowl.d.ts +5 -0
  13. package/cjs/charts/storyline/layouts/bowl.js +286 -0
  14. package/cjs/charts/storyline/layouts/bowl.js.map +1 -0
  15. package/cjs/charts/storyline/layouts/clock.d.ts +5 -0
  16. package/cjs/charts/storyline/layouts/clock.js +233 -0
  17. package/cjs/charts/storyline/layouts/clock.js.map +1 -0
  18. package/cjs/charts/storyline/layouts/common.d.ts +87 -0
  19. package/cjs/charts/storyline/layouts/common.js +287 -0
  20. package/cjs/charts/storyline/layouts/common.js.map +1 -0
  21. package/cjs/charts/storyline/layouts/default.d.ts +4 -0
  22. package/cjs/charts/storyline/layouts/default.js +179 -0
  23. package/cjs/charts/storyline/layouts/default.js.map +1 -0
  24. package/cjs/charts/storyline/layouts/dome.d.ts +5 -0
  25. package/cjs/charts/storyline/layouts/dome.js +286 -0
  26. package/cjs/charts/storyline/layouts/dome.js.map +1 -0
  27. package/cjs/charts/storyline/layouts/landscape.d.ts +4 -0
  28. package/cjs/charts/storyline/layouts/landscape.js +254 -0
  29. package/cjs/charts/storyline/layouts/landscape.js.map +1 -0
  30. package/cjs/charts/storyline/layouts/portrait.d.ts +4 -0
  31. package/cjs/charts/storyline/layouts/portrait.js +241 -0
  32. package/cjs/charts/storyline/layouts/portrait.js.map +1 -0
  33. package/cjs/charts/storyline/storyline-transformer.d.ts +4 -0
  34. package/cjs/charts/storyline/storyline-transformer.js +62 -0
  35. package/cjs/charts/storyline/storyline-transformer.js.map +1 -0
  36. package/cjs/charts/storyline/storyline.d.ts +16 -0
  37. package/cjs/charts/storyline/storyline.js +36 -0
  38. package/cjs/charts/storyline/storyline.js.map +1 -0
  39. package/cjs/index.d.ts +1 -0
  40. package/cjs/index.js +5 -5
  41. package/cjs/index.js.map +1 -1
  42. package/esm/charts/storyline/index.d.ts +4 -0
  43. package/esm/charts/storyline/index.js +8 -0
  44. package/esm/charts/storyline/index.js.map +1 -0
  45. package/esm/charts/storyline/interface.d.ts +59 -0
  46. package/esm/charts/storyline/interface.js +2 -0
  47. package/esm/charts/storyline/interface.js.map +1 -0
  48. package/esm/charts/storyline/layout.d.ts +53 -0
  49. package/esm/charts/storyline/layout.js +205 -0
  50. package/esm/charts/storyline/layout.js.map +1 -0
  51. package/esm/charts/storyline/layouts/bowl.d.ts +5 -0
  52. package/esm/charts/storyline/layouts/bowl.js +278 -0
  53. package/esm/charts/storyline/layouts/bowl.js.map +1 -0
  54. package/esm/charts/storyline/layouts/clock.d.ts +5 -0
  55. package/esm/charts/storyline/layouts/clock.js +227 -0
  56. package/esm/charts/storyline/layouts/clock.js.map +1 -0
  57. package/esm/charts/storyline/layouts/common.d.ts +87 -0
  58. package/esm/charts/storyline/layouts/common.js +255 -0
  59. package/esm/charts/storyline/layouts/common.js.map +1 -0
  60. package/esm/charts/storyline/layouts/default.d.ts +4 -0
  61. package/esm/charts/storyline/layouts/default.js +172 -0
  62. package/esm/charts/storyline/layouts/default.js.map +1 -0
  63. package/esm/charts/storyline/layouts/dome.d.ts +5 -0
  64. package/esm/charts/storyline/layouts/dome.js +278 -0
  65. package/esm/charts/storyline/layouts/dome.js.map +1 -0
  66. package/esm/charts/storyline/layouts/landscape.d.ts +4 -0
  67. package/esm/charts/storyline/layouts/landscape.js +250 -0
  68. package/esm/charts/storyline/layouts/landscape.js.map +1 -0
  69. package/esm/charts/storyline/layouts/portrait.d.ts +4 -0
  70. package/esm/charts/storyline/layouts/portrait.js +238 -0
  71. package/esm/charts/storyline/layouts/portrait.js.map +1 -0
  72. package/esm/charts/storyline/storyline-transformer.d.ts +4 -0
  73. package/esm/charts/storyline/storyline-transformer.js +61 -0
  74. package/esm/charts/storyline/storyline-transformer.js.map +1 -0
  75. package/esm/charts/storyline/storyline.d.ts +16 -0
  76. package/esm/charts/storyline/storyline.js +29 -0
  77. package/esm/charts/storyline/storyline.js.map +1 -0
  78. package/esm/index.d.ts +1 -0
  79. package/esm/index.js +2 -0
  80. package/esm/index.js.map +1 -1
  81. package/package.json +8 -8
package/build/index.js CHANGED
@@ -5822,6 +5822,1960 @@
5822
5822
  vchart.Factory.registerChart(TimelineChart.type, TimelineChart);
5823
5823
  };
5824
5824
 
5825
+ const DEFAULT_LAYOUT = 'landscape';
5826
+ const DEFAULT_PADDING = 24;
5827
+ const normalizePadding = (padding) => {
5828
+ var _a, _b, _c, _d;
5829
+ if (Array.isArray(padding)) {
5830
+ return {
5831
+ top: (_a = padding[0]) !== null && _a !== void 0 ? _a : 0,
5832
+ right: (_b = padding[1]) !== null && _b !== void 0 ? _b : 0,
5833
+ bottom: (_c = padding[2]) !== null && _c !== void 0 ? _c : 0,
5834
+ left: (_d = padding[3]) !== null && _d !== void 0 ? _d : 0
5835
+ };
5836
+ }
5837
+ const value = padding !== null && padding !== void 0 ? padding : DEFAULT_PADDING;
5838
+ return { top: value, right: value, bottom: value, left: value };
5839
+ };
5840
+ const normalizeLayout = (layout) => {
5841
+ if (!layout) {
5842
+ return { type: DEFAULT_LAYOUT };
5843
+ }
5844
+ if (typeof layout === 'string') {
5845
+ return { type: layout };
5846
+ }
5847
+ return layout;
5848
+ };
5849
+ const computeStorylineLayout = (data, options) => {
5850
+ var _a, _b, _c;
5851
+ const layout = normalizeLayout(options.layout);
5852
+ const padding = normalizePadding((_a = layout.padding) !== null && _a !== void 0 ? _a : options.padding);
5853
+ const gap = (_b = options.gap) !== null && _b !== void 0 ? _b : 40;
5854
+ const lineDistance = (_c = options.lineDistance) !== null && _c !== void 0 ? _c : 8;
5855
+ const blocks = computeBlockPositions(data, layout, options.viewBox, options.block, padding, gap);
5856
+ const circleGuide = layout.type === 'clock' ? computeClockCircleGuide(options.viewBox, options.block, padding, layout) : undefined;
5857
+ return {
5858
+ blocks,
5859
+ links: computeLinks(blocks, lineDistance),
5860
+ circleGuide
5861
+ };
5862
+ };
5863
+ const computeBlockPositions = (data, layout, viewBox, block, padding, gap) => {
5864
+ const count = data.length;
5865
+ if (!count) {
5866
+ return [];
5867
+ }
5868
+ const inner = {
5869
+ x: padding.left,
5870
+ y: padding.top,
5871
+ width: Math.max(viewBox.width - padding.left - padding.right, block.width),
5872
+ height: Math.max(viewBox.height - padding.top - padding.bottom, block.height)
5873
+ };
5874
+ const center = {
5875
+ x: inner.x + inner.width / 2,
5876
+ y: inner.y + inner.height / 2
5877
+ };
5878
+ let centers;
5879
+ switch (layout.type) {
5880
+ case 'portrait':
5881
+ centers = lineCenters(count, center.x, inner.y + block.height / 2, center.x, inner.y + inner.height - block.height / 2);
5882
+ break;
5883
+ case 'up-ladder':
5884
+ centers = lineCenters(count, inner.x + block.width / 2, inner.y + inner.height - block.height / 2, inner.x + inner.width - block.width / 2, inner.y + block.height / 2);
5885
+ break;
5886
+ case 'down-ladder':
5887
+ centers = lineCenters(count, inner.x + block.width / 2, inner.y + block.height / 2, inner.x + inner.width - block.width / 2, inner.y + inner.height - block.height / 2);
5888
+ break;
5889
+ case 'pulse':
5890
+ centers = alternatingHorizontalCenters(count, inner, block, gap);
5891
+ break;
5892
+ case 'spiral':
5893
+ centers = alternatingVerticalCenters(count, inner, block, gap);
5894
+ break;
5895
+ case 'clock':
5896
+ centers = circularCenters(count, viewBox, block, padding, layout);
5897
+ break;
5898
+ case 'bowl':
5899
+ centers = arcCenters(count, inner, block, layout, 200, 340);
5900
+ break;
5901
+ case 'dome':
5902
+ centers = arcCenters(count, inner, block, layout, 160, 20);
5903
+ break;
5904
+ case 'left-wing':
5905
+ centers = arcCenters(count, inner, block, layout, 250, 110);
5906
+ break;
5907
+ case 'right-wing':
5908
+ centers = arcCenters(count, inner, block, layout, -70, 70);
5909
+ break;
5910
+ case 'landscape':
5911
+ default:
5912
+ centers = lineCenters(count, inner.x + block.width / 2, center.y, inner.x + inner.width - block.width / 2, center.y);
5913
+ break;
5914
+ }
5915
+ return centers.map((point, index) => {
5916
+ var _a, _b;
5917
+ return ({
5918
+ id: (_b = (_a = data[index]) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : index,
5919
+ index,
5920
+ datum: data[index],
5921
+ width: block.width,
5922
+ height: block.height,
5923
+ x: point.x - block.width / 2,
5924
+ y: point.y - block.height / 2,
5925
+ center: point
5926
+ });
5927
+ });
5928
+ };
5929
+ const lineCenters = (count, x0, y0, x1, y1) => {
5930
+ if (count === 1) {
5931
+ return [{ x: (x0 + x1) / 2, y: (y0 + y1) / 2 }];
5932
+ }
5933
+ return Array.from({ length: count }, (_, index) => {
5934
+ const t = index / (count - 1);
5935
+ return {
5936
+ x: x0 + (x1 - x0) * t,
5937
+ y: y0 + (y1 - y0) * t
5938
+ };
5939
+ });
5940
+ };
5941
+ const alternatingHorizontalCenters = (count, inner, block, gap) => {
5942
+ const baseY = inner.y + inner.height / 2;
5943
+ const offset = Math.min(Math.max(block.height * 0.65 + gap / 2, 0), Math.max((inner.height - block.height) / 2, 0));
5944
+ const points = lineCenters(count, inner.x + block.width / 2, baseY, inner.x + inner.width - block.width / 2, baseY);
5945
+ return points.map((point, index) => ({
5946
+ x: point.x,
5947
+ y: point.y + (index % 2 === 0 ? -offset : offset)
5948
+ }));
5949
+ };
5950
+ const alternatingVerticalCenters = (count, inner, block, gap) => {
5951
+ const baseX = inner.x + inner.width / 2;
5952
+ const offset = Math.min(Math.max(block.width * 0.65 + gap / 2, 0), Math.max((inner.width - block.width) / 2, 0));
5953
+ const points = lineCenters(count, baseX, inner.y + block.height / 2, baseX, inner.y + inner.height - block.height / 2);
5954
+ return points.map((point, index) => ({
5955
+ x: point.x + (index % 2 === 0 ? -offset : offset),
5956
+ y: point.y
5957
+ }));
5958
+ };
5959
+ const circularCenters = (count, viewBox, block, padding, layout) => {
5960
+ var _a;
5961
+ const guide = computeClockCircleGuide(viewBox, block, padding, layout);
5962
+ const startAngle = (_a = layout.startAngle) !== null && _a !== void 0 ? _a : -90;
5963
+ const delta = 360;
5964
+ if (count === 1) {
5965
+ const angle = degreeToRadian(startAngle);
5966
+ return [
5967
+ {
5968
+ x: guide.center.x + Math.cos(angle) * guide.radius,
5969
+ y: guide.center.y + Math.sin(angle) * guide.radius
5970
+ }
5971
+ ];
5972
+ }
5973
+ return Array.from({ length: count }, (_, index) => {
5974
+ const angle = degreeToRadian(startAngle + (delta * index) / count);
5975
+ return {
5976
+ x: guide.center.x + Math.cos(angle) * guide.radius,
5977
+ y: guide.center.y + Math.sin(angle) * guide.radius
5978
+ };
5979
+ });
5980
+ };
5981
+ const computeClockCircleGuide = (viewBox, block, padding, layout) => {
5982
+ var _a;
5983
+ const innerWidth = Math.max(viewBox.width - padding.left - padding.right, 1);
5984
+ const innerHeight = Math.max(viewBox.height - padding.top - padding.bottom, 1);
5985
+ const center = {
5986
+ x: padding.left + innerWidth / 2,
5987
+ y: padding.top + innerHeight / 2
5988
+ };
5989
+ const ratio = (_a = layout.radiusRatio) !== null && _a !== void 0 ? _a : 0.7;
5990
+ const maxRadius = Math.max(Math.min(innerWidth - block.width, innerHeight - block.height) / 2, 1);
5991
+ return {
5992
+ center,
5993
+ radius: Math.max(1, maxRadius * ratio)
5994
+ };
5995
+ };
5996
+ const arcCenters = (count, inner, block, layout, fallbackStartAngle, fallbackEndAngle, defaultRatio = 0.88) => {
5997
+ var _a, _b, _c, _d, _e;
5998
+ const startAngle = (_b = (_a = layout.startAngle) !== null && _a !== void 0 ? _a : fallbackStartAngle) !== null && _b !== void 0 ? _b : -90;
5999
+ const endAngle = (_d = (_c = layout.endAngle) !== null && _c !== void 0 ? _c : fallbackEndAngle) !== null && _d !== void 0 ? _d : 270;
6000
+ const ratio = (_e = layout.radiusRatio) !== null && _e !== void 0 ? _e : defaultRatio;
6001
+ const rx = Math.max((inner.width - block.width) / 2, 1) * ratio;
6002
+ const ry = Math.max((inner.height - block.height) / 2, 1) * ratio;
6003
+ const center = {
6004
+ x: inner.x + inner.width / 2,
6005
+ y: inner.y + inner.height / 2
6006
+ };
6007
+ if (count === 1) {
6008
+ const angle = degreeToRadian((startAngle + endAngle) / 2);
6009
+ return [{ x: center.x + Math.cos(angle) * rx, y: center.y + Math.sin(angle) * ry }];
6010
+ }
6011
+ return Array.from({ length: count }, (_, index) => {
6012
+ const t = index / (count - 1);
6013
+ const angle = degreeToRadian(startAngle + angleDelta(startAngle, endAngle) * t);
6014
+ return {
6015
+ x: center.x + Math.cos(angle) * rx,
6016
+ y: center.y + Math.sin(angle) * ry
6017
+ };
6018
+ });
6019
+ };
6020
+ const angleDelta = (startAngle, endAngle) => {
6021
+ const delta = endAngle - startAngle;
6022
+ return Math.abs(delta) >= 360 ? 360 : delta;
6023
+ };
6024
+ const degreeToRadian = (degree) => (degree / 180) * Math.PI;
6025
+ const computeLinks = (blocks, distance) => {
6026
+ const links = [];
6027
+ for (let i = 0; i < blocks.length - 1; i++) {
6028
+ const from = blocks[i];
6029
+ const to = blocks[i + 1];
6030
+ const start = pointOnBlockEdge(from, to.center, distance);
6031
+ const end = pointOnBlockEdge(to, from.center, distance);
6032
+ links.push({
6033
+ from,
6034
+ to,
6035
+ start,
6036
+ end,
6037
+ points: [start, end]
6038
+ });
6039
+ }
6040
+ return links;
6041
+ };
6042
+ const pointOnBlockEdge = (block, toward, distance) => {
6043
+ const dx = toward.x - block.center.x;
6044
+ const dy = toward.y - block.center.y;
6045
+ if (dx === 0 && dy === 0) {
6046
+ return { x: block.center.x, y: block.center.y };
6047
+ }
6048
+ const scaleX = dx === 0 ? Number.POSITIVE_INFINITY : block.width / 2 / Math.abs(dx);
6049
+ const scaleY = dy === 0 ? Number.POSITIVE_INFINITY : block.height / 2 / Math.abs(dy);
6050
+ const scale = Math.min(scaleX, scaleY);
6051
+ const length = Math.sqrt(dx * dx + dy * dy) || 1;
6052
+ return {
6053
+ x: block.center.x + dx * scale + (dx / length) * distance,
6054
+ y: block.center.y + dy * scale + (dy / length) * distance
6055
+ };
6056
+ };
6057
+
6058
+ const DEFAULT_BLOCK_WIDTH = 180;
6059
+ const DEFAULT_BLOCK_HEIGHT = 112;
6060
+ const DEFAULT_BLOCK_WIDTH_RATIO = 0.24;
6061
+ const DEFAULT_BLOCK_GAP = 36;
6062
+ const DEFAULT_IMAGE_WIDTH = 48;
6063
+ const DEFAULT_IMAGE_HEIGHT = 48;
6064
+ const DEFAULT_IMAGE_GAP = 10;
6065
+ const DEFAULT_THEME_COLOR = '#e8543d';
6066
+ const isLandscape = (spec) => normalizeLayout(spec.layout).type === 'landscape';
6067
+ const isPortrait = (spec) => normalizeLayout(spec.layout).type === 'portrait';
6068
+ const isClock = (spec) => normalizeLayout(spec.layout).type === 'clock';
6069
+ const isDome = (spec) => normalizeLayout(spec.layout).type === 'dome';
6070
+ const isBowl = (spec) => normalizeLayout(spec.layout).type === 'bowl';
6071
+ const getThemeColor = (spec) => { var _a; return (_a = spec.themeColor) !== null && _a !== void 0 ? _a : DEFAULT_THEME_COLOR; };
6072
+ const withAlpha = (color, alpha) => {
6073
+ const safeAlpha = Math.max(0, Math.min(1, alpha));
6074
+ if (!color) {
6075
+ return `rgba(0, 0, 0, ${safeAlpha})`;
6076
+ }
6077
+ const trimmed = color.trim();
6078
+ if (trimmed.startsWith('#')) {
6079
+ let hex = trimmed.slice(1);
6080
+ if (hex.length === 3 || hex.length === 4) {
6081
+ hex = hex
6082
+ .split('')
6083
+ .map(ch => ch + ch)
6084
+ .join('');
6085
+ }
6086
+ if (hex.length === 6 || hex.length === 8) {
6087
+ const r = parseInt(hex.slice(0, 2), 16);
6088
+ const g = parseInt(hex.slice(2, 4), 16);
6089
+ const b = parseInt(hex.slice(4, 6), 16);
6090
+ return `rgba(${r}, ${g}, ${b}, ${safeAlpha})`;
6091
+ }
6092
+ }
6093
+ const rgbMatch = trimmed.match(/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i);
6094
+ if (rgbMatch) {
6095
+ return `rgba(${rgbMatch[1]}, ${rgbMatch[2]}, ${rgbMatch[3]}, ${safeAlpha})`;
6096
+ }
6097
+ return trimmed;
6098
+ };
6099
+ const resolveBlockWidth = (spec, viewWidth) => {
6100
+ var _a, _b, _c, _d, _e, _f, _g;
6101
+ if ((_a = spec.block) === null || _a === void 0 ? void 0 : _a.width) {
6102
+ return spec.block.width;
6103
+ }
6104
+ const ratio = (_c = (_b = spec.block) === null || _b === void 0 ? void 0 : _b.widthRatio) !== null && _c !== void 0 ? _c : DEFAULT_BLOCK_WIDTH_RATIO;
6105
+ const minWidth = (_e = (_d = spec.block) === null || _d === void 0 ? void 0 : _d.minWidth) !== null && _e !== void 0 ? _e : DEFAULT_BLOCK_WIDTH;
6106
+ const maxWidth = (_g = (_f = spec.block) === null || _f === void 0 ? void 0 : _f.maxWidth) !== null && _g !== void 0 ? _g : Math.max(minWidth, 320);
6107
+ return Math.max(minWidth, Math.min(maxWidth, Math.round(viewWidth * ratio)));
6108
+ };
6109
+ const getRegionGeometry = (ctx) => {
6110
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
6111
+ const region = (_c = (_b = (_a = ctx.chart) === null || _a === void 0 ? void 0 : _a.getAllRegions) === null || _b === void 0 ? void 0 : _b.call(_a)) === null || _c === void 0 ? void 0 : _c[0];
6112
+ const regionRect = (_d = region === null || region === void 0 ? void 0 : region.getLayoutRect) === null || _d === void 0 ? void 0 : _d.call(region);
6113
+ const regionStart = (_e = region === null || region === void 0 ? void 0 : region.getLayoutStartPoint) === null || _e === void 0 ? void 0 : _e.call(region);
6114
+ const chartRect = (_g = (_f = ctx.chart) === null || _f === void 0 ? void 0 : _f.getLayoutRect) === null || _g === void 0 ? void 0 : _g.call(_f);
6115
+ const bounds = (_h = ctx.getLayoutBounds) === null || _h === void 0 ? void 0 : _h.call(ctx);
6116
+ const width = Math.max((_m = (_k = (_j = regionRect === null || regionRect === void 0 ? void 0 : regionRect.width) !== null && _j !== void 0 ? _j : chartRect === null || chartRect === void 0 ? void 0 : chartRect.width) !== null && _k !== void 0 ? _k : (_l = bounds === null || bounds === void 0 ? void 0 : bounds.width) === null || _l === void 0 ? void 0 : _l.call(bounds)) !== null && _m !== void 0 ? _m : 0, 1);
6117
+ const height = Math.max((_r = (_p = (_o = regionRect === null || regionRect === void 0 ? void 0 : regionRect.height) !== null && _o !== void 0 ? _o : chartRect === null || chartRect === void 0 ? void 0 : chartRect.height) !== null && _p !== void 0 ? _p : (_q = bounds === null || bounds === void 0 ? void 0 : bounds.height) === null || _q === void 0 ? void 0 : _q.call(bounds)) !== null && _r !== void 0 ? _r : 0, 1);
6118
+ return {
6119
+ width,
6120
+ height,
6121
+ startX: (_s = regionStart === null || regionStart === void 0 ? void 0 : regionStart.x) !== null && _s !== void 0 ? _s : 0,
6122
+ startY: (_t = regionStart === null || regionStart === void 0 ? void 0 : regionStart.y) !== null && _t !== void 0 ? _t : 0
6123
+ };
6124
+ };
6125
+ const getLayout = (spec, ctx) => {
6126
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
6127
+ const { width, height, startX, startY } = getRegionGeometry(ctx);
6128
+ let blockWidth = resolveBlockWidth(spec, width);
6129
+ let blockHeight = (_b = (_a = spec.block) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : DEFAULT_BLOCK_HEIGHT;
6130
+ if (isLandscape(spec) && !((_c = spec.block) === null || _c === void 0 ? void 0 : _c.width)) {
6131
+ const count = (_e = (_d = spec.data) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 0;
6132
+ if (count > 0) {
6133
+ const padding = normalizePadding((_f = spec.block) === null || _f === void 0 ? void 0 : _f.padding);
6134
+ const innerWidth = Math.max(width - padding.left - padding.right, 1);
6135
+ const LANDSCAPE_IMAGE_GAP = 40;
6136
+ const LANDSCAPE_IMAGE_MIN_WIDTH = 80;
6137
+ const totalGap = LANDSCAPE_IMAGE_GAP * Math.max(count - 1, 0);
6138
+ const adaptive = (innerWidth - totalGap) / count;
6139
+ blockWidth = Math.max(LANDSCAPE_IMAGE_MIN_WIDTH, Math.floor(adaptive));
6140
+ }
6141
+ }
6142
+ if (isPortrait(spec) && !((_g = spec.block) === null || _g === void 0 ? void 0 : _g.height)) {
6143
+ const count = (_j = (_h = spec.data) === null || _h === void 0 ? void 0 : _h.length) !== null && _j !== void 0 ? _j : 0;
6144
+ if (count > 0) {
6145
+ const padding = normalizePadding((_k = spec.block) === null || _k === void 0 ? void 0 : _k.padding);
6146
+ const innerHeight = Math.max(height - padding.top - padding.bottom, 1);
6147
+ blockHeight = Math.max(160, Math.floor(innerHeight / count));
6148
+ }
6149
+ }
6150
+ const result = computeStorylineLayout((_l = spec.data) !== null && _l !== void 0 ? _l : [], {
6151
+ layout: spec.layout,
6152
+ viewBox: { width, height },
6153
+ block: {
6154
+ width: blockWidth,
6155
+ height: blockHeight
6156
+ },
6157
+ gap: (_o = (_m = spec.block) === null || _m === void 0 ? void 0 : _m.gap) !== null && _o !== void 0 ? _o : DEFAULT_BLOCK_GAP,
6158
+ padding: (_p = spec.block) === null || _p === void 0 ? void 0 : _p.padding,
6159
+ lineDistance: (_q = spec.line) === null || _q === void 0 ? void 0 : _q.distance
6160
+ });
6161
+ if (!startX && !startY) {
6162
+ return result;
6163
+ }
6164
+ return Object.assign(Object.assign({}, result), { blocks: result.blocks.map(block => (Object.assign(Object.assign({}, block), { x: block.x + startX, y: block.y + startY, center: {
6165
+ x: block.center.x + startX,
6166
+ y: block.center.y + startY
6167
+ } }))), links: result.links.map(link => (Object.assign(Object.assign({}, link), { start: { x: link.start.x + startX, y: link.start.y + startY }, end: { x: link.end.x + startX, y: link.end.y + startY }, points: link.points.map(point => ({ x: point.x + startX, y: point.y + startY })) }))) });
6168
+ };
6169
+ const buildRichContent = (contentText, spec) => {
6170
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
6171
+ const fontSize = Number((_c = (_b = (_a = spec.content) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.fontSize) !== null && _c !== void 0 ? _c : 12);
6172
+ const lineHeight = Number((_f = (_e = (_d = spec.content) === null || _d === void 0 ? void 0 : _d.style) === null || _e === void 0 ? void 0 : _e.lineHeight) !== null && _f !== void 0 ? _f : 18);
6173
+ const fill = (_j = (_h = (_g = spec.content) === null || _g === void 0 ? void 0 : _g.style) === null || _h === void 0 ? void 0 : _h.fill) !== null && _j !== void 0 ? _j : '#596173';
6174
+ return {
6175
+ type: 'rich',
6176
+ text: contentText.reduce((result, paragraph, index) => {
6177
+ const suffix = index === contentText.length - 1 ? '' : '\n';
6178
+ result.push({
6179
+ text: `${paragraph}${suffix}`,
6180
+ fontSize,
6181
+ lineHeight,
6182
+ fill
6183
+ });
6184
+ return result;
6185
+ }, [])
6186
+ };
6187
+ };
6188
+ const omitImageLayoutSpec = (imageSpec) => {
6189
+ if (!imageSpec) {
6190
+ return {};
6191
+ }
6192
+ const rest = __rest(imageSpec, ["width", "height", "position", "gap"]);
6193
+ return rest;
6194
+ };
6195
+ const getImageBox = (position, blockWidth, blockHeight, padding, width, height, _gap, visible) => {
6196
+ if (!visible) {
6197
+ return { x: padding.left, y: padding.top, width: 0, height: 0 };
6198
+ }
6199
+ switch (position) {
6200
+ case 'left':
6201
+ return { x: padding.left, y: (blockHeight - height) / 2, width, height };
6202
+ case 'right':
6203
+ return { x: blockWidth - padding.right - width, y: (blockHeight - height) / 2, width, height };
6204
+ case 'bottom':
6205
+ return { x: (blockWidth - width) / 2, y: blockHeight - padding.bottom - height, width, height };
6206
+ case 'top':
6207
+ default:
6208
+ return { x: (blockWidth - width) / 2, y: padding.top, width, height };
6209
+ }
6210
+ };
6211
+ const getTextBox = (position, blockWidth, blockHeight, padding, imageWidth, imageHeight, imageGap, hasImage) => {
6212
+ if (!hasImage) {
6213
+ return {
6214
+ x: padding.left,
6215
+ y: padding.top,
6216
+ width: blockWidth - padding.left - padding.right,
6217
+ height: blockHeight - padding.top - padding.bottom
6218
+ };
6219
+ }
6220
+ switch (position) {
6221
+ case 'left':
6222
+ return {
6223
+ x: padding.left + imageWidth + imageGap,
6224
+ y: padding.top,
6225
+ width: blockWidth - padding.left - padding.right - imageWidth - imageGap,
6226
+ height: blockHeight - padding.top - padding.bottom
6227
+ };
6228
+ case 'right':
6229
+ return {
6230
+ x: padding.left,
6231
+ y: padding.top,
6232
+ width: blockWidth - padding.left - padding.right - imageWidth - imageGap,
6233
+ height: blockHeight - padding.top - padding.bottom
6234
+ };
6235
+ case 'bottom':
6236
+ return {
6237
+ x: padding.left,
6238
+ y: padding.top,
6239
+ width: blockWidth - padding.left - padding.right,
6240
+ height: blockHeight - padding.top - padding.bottom - imageHeight - imageGap
6241
+ };
6242
+ case 'top':
6243
+ default:
6244
+ return {
6245
+ x: padding.left,
6246
+ y: padding.top + imageHeight + imageGap,
6247
+ width: blockWidth - padding.left - padding.right,
6248
+ height: blockHeight - padding.top - padding.bottom - imageHeight - imageGap
6249
+ };
6250
+ }
6251
+ };
6252
+ const buildSmoothCurvePath = (points) => {
6253
+ var _a, _b;
6254
+ if (points.length < 2) {
6255
+ return '';
6256
+ }
6257
+ if (points.length === 2) {
6258
+ return `M ${points[0].x} ${points[0].y} L ${points[1].x} ${points[1].y}`;
6259
+ }
6260
+ let d = `M ${points[0].x} ${points[0].y}`;
6261
+ for (let i = 0; i < points.length - 1; i++) {
6262
+ const p0 = (_a = points[i - 1]) !== null && _a !== void 0 ? _a : points[i];
6263
+ const p1 = points[i];
6264
+ const p2 = points[i + 1];
6265
+ const p3 = (_b = points[i + 2]) !== null && _b !== void 0 ? _b : p2;
6266
+ const c1x = p1.x + (p2.x - p0.x) / 6;
6267
+ const c1y = p1.y + (p2.y - p0.y) / 6;
6268
+ const c2x = p2.x - (p3.x - p1.x) / 6;
6269
+ const c2y = p2.y - (p3.y - p1.y) / 6;
6270
+ d += ` C ${c1x} ${c1y}, ${c2x} ${c2y}, ${p2.x} ${p2.y}`;
6271
+ }
6272
+ return d;
6273
+ };
6274
+
6275
+ const CLOCK_CENTER_RADIUS_RATIO = 0.5;
6276
+ const CLOCK_CENTER_IMAGE_INSET_RATIO = 0.86;
6277
+ const CLOCK_ORBIT_RATIO = 0.58;
6278
+ const CLOCK_DOT_RATIO = 0.58;
6279
+ const CLOCK_TEXT_INNER_RATIO = 0.7;
6280
+ const CLOCK_TEXT_MAX_WIDTH = 200;
6281
+ const CLOCK_DOT_DIAMETER_RATIO = 0.24;
6282
+ const CLOCK_LEAD_LINE_GAP = 6;
6283
+ const CLOCK_TEXT_GAP_FROM_LEAD = 8;
6284
+ const CLOCK_ORBIT_DASH = [4, 4];
6285
+ const CLOCK_TITLE_FONT_SIZE = 13;
6286
+ const CLOCK_TITLE_LINE_HEIGHT = 18;
6287
+ const CLOCK_CONTENT_FONT_SIZE = 11;
6288
+ const CLOCK_CONTENT_LINE_HEIGHT = 15;
6289
+ const getClockGeometry = (spec, ctx) => {
6290
+ var _a, _b, _c;
6291
+ const { width, height, startX, startY } = getRegionGeometry(ctx);
6292
+ const padding = normalizePadding((_a = spec.block) === null || _a === void 0 ? void 0 : _a.padding);
6293
+ const innerWidth = Math.max(width - padding.left - padding.right, 1);
6294
+ const innerHeight = Math.max(height - padding.top - padding.bottom, 1);
6295
+ const cx = startX + padding.left + innerWidth / 2;
6296
+ const cy = startY + padding.top + innerHeight / 2;
6297
+ const R = Math.max(Math.min(innerWidth, innerHeight) / 2, 1);
6298
+ const count = (_c = (_b = spec.data) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0;
6299
+ const step = count > 0 ? (Math.PI * 2) / count : 0;
6300
+ return { cx, cy, R, count, step };
6301
+ };
6302
+ const getClockBlockAngle = (geom, index) => -Math.PI / 2 + geom.step * (index + 0.5);
6303
+ const polar = (cx, cy, r, angle) => ({
6304
+ x: cx + Math.cos(angle) * r,
6305
+ y: cy + Math.sin(angle) * r
6306
+ });
6307
+ const isOnLeftHalf = (angle) => Math.cos(angle) < 0;
6308
+ const buildClockCenterImageMark = (spec) => {
6309
+ var _a, _b, _c, _e;
6310
+ if (((_a = spec.centerImage) === null || _a === void 0 ? void 0 : _a.visible) === false) {
6311
+ return null;
6312
+ }
6313
+ const themeColor = getThemeColor(spec);
6314
+ const hasImage = !!((_b = spec.centerImage) === null || _b === void 0 ? void 0 : _b.image);
6315
+ return {
6316
+ type: 'group',
6317
+ name: 'storyline-clock-center',
6318
+ zIndex: vchart.LayoutZIndex.Mark + 2,
6319
+ children: [
6320
+ {
6321
+ type: 'symbol',
6322
+ name: 'storyline-clock-center-halo',
6323
+ interactive: false,
6324
+ style: {
6325
+ x: (_d, ctx) => getClockGeometry(spec, ctx).cx,
6326
+ y: (_d, ctx) => getClockGeometry(spec, ctx).cy,
6327
+ size: (_d, ctx) => {
6328
+ const g = getClockGeometry(spec, ctx);
6329
+ return g.R * CLOCK_CENTER_RADIUS_RATIO * 2.16;
6330
+ },
6331
+ symbolType: 'circle',
6332
+ fill: withAlpha(themeColor, 0.28),
6333
+ stroke: 'transparent'
6334
+ }
6335
+ },
6336
+ hasImage
6337
+ ? {
6338
+ type: 'image',
6339
+ name: 'storyline-clock-center-image',
6340
+ interactive: false,
6341
+ style: Object.assign({ x: (_d, ctx) => {
6342
+ const g = getClockGeometry(spec, ctx);
6343
+ return g.cx - g.R * CLOCK_CENTER_RADIUS_RATIO * CLOCK_CENTER_IMAGE_INSET_RATIO;
6344
+ }, y: (_d, ctx) => {
6345
+ const g = getClockGeometry(spec, ctx);
6346
+ return g.cy - g.R * CLOCK_CENTER_RADIUS_RATIO * CLOCK_CENTER_IMAGE_INSET_RATIO;
6347
+ }, width: (_d, ctx) => getClockGeometry(spec, ctx).R * CLOCK_CENTER_RADIUS_RATIO * CLOCK_CENTER_IMAGE_INSET_RATIO * 2, height: (_d, ctx) => getClockGeometry(spec, ctx).R * CLOCK_CENTER_RADIUS_RATIO * CLOCK_CENTER_IMAGE_INSET_RATIO * 2, image: (_c = spec.centerImage) === null || _c === void 0 ? void 0 : _c.image, cornerRadius: (_d, ctx) => getClockGeometry(spec, ctx).R * CLOCK_CENTER_RADIUS_RATIO * CLOCK_CENTER_IMAGE_INSET_RATIO, repeatX: 'no-repeat', repeatY: 'no-repeat', imageMode: 'cover', imagePosition: 'center' }, (_e = spec.centerImage) === null || _e === void 0 ? void 0 : _e.style)
6348
+ }
6349
+ : {
6350
+ type: 'symbol',
6351
+ name: 'storyline-clock-center-placeholder',
6352
+ interactive: false,
6353
+ style: {
6354
+ x: (_d, ctx) => getClockGeometry(spec, ctx).cx,
6355
+ y: (_d, ctx) => getClockGeometry(spec, ctx).cy,
6356
+ size: (_d, ctx) => getClockGeometry(spec, ctx).R * CLOCK_CENTER_RADIUS_RATIO * 2,
6357
+ symbolType: 'circle',
6358
+ fill: '#ffffff',
6359
+ stroke: themeColor,
6360
+ lineWidth: 2
6361
+ }
6362
+ }
6363
+ ].filter(Boolean)
6364
+ };
6365
+ };
6366
+ const buildClockArcMark = (spec) => {
6367
+ const themeColor = getThemeColor(spec);
6368
+ const orbitPath = (_d, ctx) => {
6369
+ const g = getClockGeometry(spec, ctx);
6370
+ const r = g.R * CLOCK_ORBIT_RATIO;
6371
+ return [
6372
+ `M ${(g.cx + r).toFixed(2)} ${g.cy.toFixed(2)}`,
6373
+ `A ${r.toFixed(2)} ${r.toFixed(2)} 0 1 1 ${(g.cx - r).toFixed(2)} ${g.cy.toFixed(2)}`,
6374
+ `A ${r.toFixed(2)} ${r.toFixed(2)} 0 1 1 ${(g.cx + r).toFixed(2)} ${g.cy.toFixed(2)}`
6375
+ ].join(' ');
6376
+ };
6377
+ return {
6378
+ type: 'group',
6379
+ name: 'storyline-clock-orbit',
6380
+ zIndex: vchart.LayoutZIndex.Mark,
6381
+ children: [
6382
+ {
6383
+ type: 'path',
6384
+ name: 'storyline-clock-orbit-path',
6385
+ interactive: false,
6386
+ style: {
6387
+ path: orbitPath,
6388
+ stroke: withAlpha(themeColor, 0.7),
6389
+ lineWidth: 1,
6390
+ lineDash: CLOCK_ORBIT_DASH,
6391
+ fill: 'transparent',
6392
+ fillOpacity: 0
6393
+ }
6394
+ }
6395
+ ]
6396
+ };
6397
+ };
6398
+ const getClockDotCenter = (spec, ctx, index) => {
6399
+ const g = getClockGeometry(spec, ctx);
6400
+ const angle = getClockBlockAngle(g, index);
6401
+ const r = g.R * CLOCK_DOT_RATIO;
6402
+ return Object.assign(Object.assign({}, polar(g.cx, g.cy, r, angle)), { diameter: g.R * CLOCK_DOT_DIAMETER_RATIO, angle });
6403
+ };
6404
+ const getClockLeadLine = (spec, ctx, index) => {
6405
+ const g = getClockGeometry(spec, ctx);
6406
+ const angle = getClockBlockAngle(g, index);
6407
+ const dotR = (g.R * CLOCK_DOT_DIAMETER_RATIO) / 2;
6408
+ const start = polar(g.cx, g.cy, g.R * CLOCK_DOT_RATIO + dotR + CLOCK_LEAD_LINE_GAP, angle);
6409
+ const end = polar(g.cx, g.cy, g.R * CLOCK_TEXT_INNER_RATIO - CLOCK_TEXT_GAP_FROM_LEAD, angle);
6410
+ return { start, end };
6411
+ };
6412
+ const getClockTextRect = (spec, ctx, index) => {
6413
+ var _a;
6414
+ const g = getClockGeometry(spec, ctx);
6415
+ const { width: regionWidth, startX } = getRegionGeometry(ctx);
6416
+ const padding = normalizePadding((_a = spec.block) === null || _a === void 0 ? void 0 : _a.padding);
6417
+ const angle = getClockBlockAngle(g, index);
6418
+ const onLeft = isOnLeftHalf(angle);
6419
+ const rInner = g.R * CLOCK_TEXT_INNER_RATIO;
6420
+ const innerPoint = polar(g.cx, g.cy, rInner, angle);
6421
+ const leftEdge = startX + padding.left;
6422
+ const rightEdge = startX + regionWidth - padding.right;
6423
+ const width = onLeft
6424
+ ? Math.min(Math.max(innerPoint.x - leftEdge, 80), CLOCK_TEXT_MAX_WIDTH)
6425
+ : Math.min(Math.max(rightEdge - innerPoint.x, 80), CLOCK_TEXT_MAX_WIDTH);
6426
+ return { x: innerPoint.x, y: innerPoint.y, width, onLeft, anchorY: innerPoint.y };
6427
+ };
6428
+ const buildClockBlockMark = (spec, block, index) => {
6429
+ var _a, _b, _c;
6430
+ const hasImage = !!block.image;
6431
+ const themeColor = getThemeColor(spec);
6432
+ const contentText = Array.isArray(block.content) ? block.content : block.content ? [block.content] : [];
6433
+ const leadPath = (_d, ctx) => {
6434
+ const { start, end } = getClockLeadLine(spec, ctx, index);
6435
+ return `M ${start.x.toFixed(2)} ${start.y.toFixed(2)} L ${end.x.toFixed(2)} ${end.y.toFixed(2)}`;
6436
+ };
6437
+ const children = [
6438
+ {
6439
+ type: 'path',
6440
+ name: `storyline-clock-lead-${index}`,
6441
+ interactive: false,
6442
+ style: {
6443
+ path: leadPath,
6444
+ stroke: withAlpha(themeColor, 0.7),
6445
+ lineWidth: 1,
6446
+ lineDash: [3, 3],
6447
+ fill: 'transparent',
6448
+ fillOpacity: 0
6449
+ }
6450
+ },
6451
+ hasImage
6452
+ ? {
6453
+ type: 'image',
6454
+ name: `storyline-clock-dot-${index}`,
6455
+ interactive: false,
6456
+ style: {
6457
+ x: (_d, ctx) => {
6458
+ const dot = getClockDotCenter(spec, ctx, index);
6459
+ return dot.x - dot.diameter / 2;
6460
+ },
6461
+ y: (_d, ctx) => {
6462
+ const dot = getClockDotCenter(spec, ctx, index);
6463
+ return dot.y - dot.diameter / 2;
6464
+ },
6465
+ width: (_d, ctx) => getClockDotCenter(spec, ctx, index).diameter,
6466
+ height: (_d, ctx) => getClockDotCenter(spec, ctx, index).diameter,
6467
+ image: block.image,
6468
+ cornerRadius: (_d, ctx) => getClockDotCenter(spec, ctx, index).diameter / 2,
6469
+ repeatX: 'no-repeat',
6470
+ repeatY: 'no-repeat',
6471
+ imageMode: 'cover',
6472
+ imagePosition: 'center',
6473
+ stroke: themeColor,
6474
+ lineWidth: 2
6475
+ }
6476
+ }
6477
+ : {
6478
+ type: 'symbol',
6479
+ name: `storyline-clock-dot-${index}`,
6480
+ interactive: false,
6481
+ style: {
6482
+ x: (_d, ctx) => getClockDotCenter(spec, ctx, index).x,
6483
+ y: (_d, ctx) => getClockDotCenter(spec, ctx, index).y,
6484
+ size: (_d, ctx) => getClockDotCenter(spec, ctx, index).diameter,
6485
+ symbolType: 'circle',
6486
+ fill: themeColor,
6487
+ stroke: '#ffffff',
6488
+ lineWidth: 1.5
6489
+ }
6490
+ },
6491
+ block.title
6492
+ ? 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 - CLOCK_TITLE_LINE_HEIGHT, text: block.title, maxLineWidth: (_d, ctx) => getClockTextRect(spec, ctx, index).width, fontSize: CLOCK_TITLE_FONT_SIZE, lineHeight: CLOCK_TITLE_LINE_HEIGHT, fontWeight: 'bold', fill: themeColor, textAlign: (_d, ctx) => getClockTextRect(spec, ctx, index).onLeft ? 'right' : 'left', textBaseline: 'top' }, (_a = spec.title) === null || _a === void 0 ? void 0 : _a.style) })
6493
+ : null,
6494
+ contentText.length
6495
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-clock-content-${index}`, interactive: false }, spec.content), { textType: 'rich', 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, maxLineWidth: (_d, ctx) => getClockTextRect(spec, ctx, index).width, text: buildRichContent(contentText, spec), fontSize: CLOCK_CONTENT_FONT_SIZE, lineHeight: CLOCK_CONTENT_LINE_HEIGHT, fill: '#3a3f4d', textAlign: (_d, ctx) => getClockTextRect(spec, ctx, index).onLeft ? 'right' : 'left', textBaseline: 'top', wordBreak: 'break-word' }, (_b = spec.content) === null || _b === void 0 ? void 0 : _b.style) })
6496
+ : null
6497
+ ];
6498
+ return {
6499
+ type: 'group',
6500
+ id: `storyline-block-${(_c = block.id) !== null && _c !== void 0 ? _c : index}`,
6501
+ name: `storyline-block-${index}`,
6502
+ zIndex: vchart.LayoutZIndex.Mark + 1,
6503
+ children: children.filter(Boolean)
6504
+ };
6505
+ };
6506
+
6507
+ const buildDefaultLineMark = (spec) => {
6508
+ var _a, _b, _c, _d;
6509
+ if (((_a = spec.line) === null || _a === void 0 ? void 0 : _a.visible) === false || ((_c = (_b = spec.data) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) <= 1) {
6510
+ return null;
6511
+ }
6512
+ return {
6513
+ type: 'group',
6514
+ name: 'storyline-links',
6515
+ zIndex: vchart.LayoutZIndex.Mark,
6516
+ children: ((_d = spec.data) !== null && _d !== void 0 ? _d : []).slice(1).map((_, index) => {
6517
+ var _a;
6518
+ const _b = (_a = spec.line) !== null && _a !== void 0 ? _a : {}, { style = {}, type = 'line', showArrow = false, arrowSize = 8 } = _b, rest = __rest(_b, ["style", "type", "showArrow", "arrowSize"]);
6519
+ return Object.assign(Object.assign({ type: 'path', name: `storyline-link-${index}`, interactive: false }, rest), { style: Object.assign(Object.assign({ stroke: '#8a94a6', lineWidth: 1.5, fill: 'transparent', fillOpacity: 0 }, style), { path: (_datum, ctx) => {
6520
+ const link = getLayout(spec, ctx).links[index];
6521
+ if (!link) {
6522
+ return '';
6523
+ }
6524
+ return buildLinkPath(link.points, type, showArrow, arrowSize);
6525
+ } }) });
6526
+ })
6527
+ };
6528
+ };
6529
+ const getDefaultBlockMetrics = (spec, ctx, index) => {
6530
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
6531
+ const block = getLayout(spec, ctx).blocks[index];
6532
+ const padding = normalizePadding((_b = (_a = spec.block) === null || _a === void 0 ? void 0 : _a.padding) !== null && _b !== void 0 ? _b : 12);
6533
+ const imagePosition = (_d = (_c = spec.image) === null || _c === void 0 ? void 0 : _c.position) !== null && _d !== void 0 ? _d : 'top';
6534
+ const imageWidth = (_f = (_e = spec.image) === null || _e === void 0 ? void 0 : _e.width) !== null && _f !== void 0 ? _f : DEFAULT_IMAGE_WIDTH;
6535
+ const imageHeight = (_h = (_g = spec.image) === null || _g === void 0 ? void 0 : _g.height) !== null && _h !== void 0 ? _h : DEFAULT_IMAGE_HEIGHT;
6536
+ const imageGap = (_k = (_j = spec.image) === null || _j === void 0 ? void 0 : _j.gap) !== null && _k !== void 0 ? _k : DEFAULT_IMAGE_GAP;
6537
+ const hasImage = !!((_m = (_l = spec.data) === null || _l === void 0 ? void 0 : _l[index]) === null || _m === void 0 ? void 0 : _m.image);
6538
+ const titleFontSize = Number((_q = (_p = (_o = spec.title) === null || _o === void 0 ? void 0 : _o.style) === null || _p === void 0 ? void 0 : _p.fontSize) !== null && _q !== void 0 ? _q : 14);
6539
+ const titleLineHeight = Number((_t = (_s = (_r = spec.title) === null || _r === void 0 ? void 0 : _r.style) === null || _s === void 0 ? void 0 : _s.lineHeight) !== null && _t !== void 0 ? _t : Math.round(titleFontSize * 1.35));
6540
+ const titleHeight = ((_v = (_u = spec.data) === null || _u === void 0 ? void 0 : _u[index]) === null || _v === void 0 ? void 0 : _v.title) ? titleLineHeight : 0;
6541
+ const blockWidth = (_w = block === null || block === void 0 ? void 0 : block.width) !== null && _w !== void 0 ? _w : resolveBlockWidth(spec, 0);
6542
+ const blockHeight = (_z = (_x = block === null || block === void 0 ? void 0 : block.height) !== null && _x !== void 0 ? _x : (_y = spec.block) === null || _y === void 0 ? void 0 : _y.height) !== null && _z !== void 0 ? _z : DEFAULT_BLOCK_HEIGHT;
6543
+ const imageBox = getImageBox(imagePosition, blockWidth, blockHeight, padding, imageWidth, imageHeight, imageGap, hasImage);
6544
+ const textBox = getTextBox(imagePosition, blockWidth, blockHeight, padding, imageWidth, imageHeight, imageGap, hasImage);
6545
+ const contentGap = ((_1 = (_0 = spec.data) === null || _0 === void 0 ? void 0 : _0[index]) === null || _1 === void 0 ? void 0 : _1.title) ? 8 : 0;
6546
+ return {
6547
+ block: {
6548
+ width: blockWidth,
6549
+ height: blockHeight
6550
+ },
6551
+ imageBox,
6552
+ textBox,
6553
+ contentBox: {
6554
+ y: textBox.y + titleHeight + contentGap,
6555
+ height: Math.max(0, textBox.height - titleHeight - contentGap)
6556
+ }
6557
+ };
6558
+ };
6559
+ const buildDefaultBlockMark = (spec, block, index) => {
6560
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
6561
+ const hasImage = !!block.image;
6562
+ const contentText = Array.isArray(block.content) ? block.content : block.content ? [block.content] : [];
6563
+ const titleFontSize = Number((_c = (_b = (_a = spec.title) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.fontSize) !== null && _c !== void 0 ? _c : 14);
6564
+ const titleLineHeight = Number((_f = (_e = (_d = spec.title) === null || _d === void 0 ? void 0 : _d.style) === null || _e === void 0 ? void 0 : _e.lineHeight) !== null && _f !== void 0 ? _f : Math.round(titleFontSize * 1.35));
6565
+ return {
6566
+ type: 'group',
6567
+ id: `storyline-block-${(_g = block.id) !== null && _g !== void 0 ? _g : index}`,
6568
+ name: `storyline-block-${index}`,
6569
+ zIndex: vchart.LayoutZIndex.Mark + 1,
6570
+ style: {
6571
+ x: (_datum, 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; },
6572
+ y: (_datum, 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; },
6573
+ width: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).block.width,
6574
+ height: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).block.height
6575
+ },
6576
+ children: [
6577
+ {
6578
+ type: 'rect',
6579
+ name: `storyline-block-bg-${index}`,
6580
+ interactive: false,
6581
+ style: Object.assign({ x: 0, y: 0, width: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).block.width, height: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).block.height, cornerRadius: 8, fill: '#ffffff', stroke: '#d7dce5', lineWidth: 1, shadowBlur: 6, shadowColor: 'rgba(0, 0, 0, 0.08)' }, (_h = spec.block) === null || _h === void 0 ? void 0 : _h.style)
6582
+ },
6583
+ hasImage
6584
+ ? 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, cornerRadius: 6 }, (_j = spec.image) === null || _j === void 0 ? void 0 : _j.style) })
6585
+ : null,
6586
+ block.title
6587
+ ? 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, fontSize: titleFontSize, lineHeight: titleLineHeight, fontWeight: 'bold', fill: '#1f2430', textAlign: 'left', textBaseline: 'top' }, (_k = spec.title) === null || _k === void 0 ? void 0 : _k.style) })
6588
+ : null,
6589
+ contentText.length
6590
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-content-${index}`, interactive: false }, spec.content), { textType: 'rich', 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, text: buildRichContent(contentText, spec), maxLineWidth: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).textBox.width, fontSize: 12, lineHeight: 18, heightLimit: (_datum, ctx) => getDefaultBlockMetrics(spec, ctx, index).contentBox.height, textAlign: 'left', textBaseline: 'top', wordBreak: 'break-word', ellipsis: '...', fill: '#596173' }, (_l = spec.content) === null || _l === void 0 ? void 0 : _l.style) })
6591
+ : null
6592
+ ].filter(Boolean)
6593
+ };
6594
+ };
6595
+ const buildLinkPath = (points, type, showArrow, arrowSize) => {
6596
+ const start = points[0];
6597
+ const end = points[points.length - 1];
6598
+ if (!start || !end) {
6599
+ return '';
6600
+ }
6601
+ let path;
6602
+ if (type === 'curve') {
6603
+ const dx = end.x - start.x;
6604
+ const dy = end.y - start.y;
6605
+ const curve = Math.max(Math.min(Math.sqrt(dx * dx + dy * dy) * 0.22, 80), 24);
6606
+ path =
6607
+ `M ${start.x} ${start.y} ` +
6608
+ `C ${start.x + dx / 2} ${start.y - curve} ${end.x - dx / 2} ${end.y + curve} ${end.x} ${end.y}`;
6609
+ }
6610
+ else if (type === 'polyline') {
6611
+ const mid = { x: (start.x + end.x) / 2, y: (start.y + end.y) / 2 };
6612
+ path = `M ${start.x} ${start.y} L ${mid.x} ${start.y} L ${mid.x} ${end.y} L ${end.x} ${end.y}`;
6613
+ }
6614
+ else {
6615
+ path = `M ${start.x} ${start.y} L ${end.x} ${end.y}`;
6616
+ }
6617
+ if (!showArrow) {
6618
+ return path;
6619
+ }
6620
+ return `${path} ${buildArrowPath(start, end, arrowSize)}`;
6621
+ };
6622
+ const buildArrowPath = (start, end, size) => {
6623
+ const angle = Math.atan2(end.y - start.y, end.x - start.x);
6624
+ const left = {
6625
+ x: end.x - Math.cos(angle - Math.PI / 6) * size,
6626
+ y: end.y - Math.sin(angle - Math.PI / 6) * size
6627
+ };
6628
+ const right = {
6629
+ x: end.x - Math.cos(angle + Math.PI / 6) * size,
6630
+ y: end.y - Math.sin(angle + Math.PI / 6) * size
6631
+ };
6632
+ return `M ${left.x} ${left.y} L ${end.x} ${end.y} L ${right.x} ${right.y}`;
6633
+ };
6634
+
6635
+ const LANDSCAPE_IMAGE_HEIGHT_RATIO = 0.42;
6636
+ const LANDSCAPE_DETACHED_GAP = 64;
6637
+ const LANDSCAPE_CONNECTOR_ARROW_SIZE = 9;
6638
+ const LANDSCAPE_CONNECTOR_X_RATIO = 0.2;
6639
+ const LANDSCAPE_TEXT_GAP_FROM_CONNECTOR = 12;
6640
+ const LANDSCAPE_CONTENT_LINES = 4;
6641
+ const LANDSCAPE_TITLE_LINE_HEIGHT = 19;
6642
+ const LANDSCAPE_CONTENT_LINE_HEIGHT = 18;
6643
+ const LANDSCAPE_CONTENT_FONT_SIZE = 12;
6644
+ const LANDSCAPE_TITLE_TO_CONTENT_GAP = 4;
6645
+ const getLandscapeImageCenter = (spec, ctx, index) => {
6646
+ var _a, _b, _c, _e;
6647
+ const lb = getLayout(spec, ctx).blocks[index];
6648
+ if (!lb) {
6649
+ return null;
6650
+ }
6651
+ const cx = (_b = (_a = lb.center) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : lb.x + lb.width / 2;
6652
+ const cy = (_e = (_c = lb.center) === null || _c === void 0 ? void 0 : _c.y) !== null && _e !== void 0 ? _e : lb.y + lb.height / 2;
6653
+ const stagger = (index % 2 === 0 ? -1 : 1) * lb.height * 0.1;
6654
+ return { x: cx, y: cy + stagger };
6655
+ };
6656
+ const buildLandscapeConnectingCurve = (spec) => {
6657
+ var _a, _b, _c, _e, _f, _g, _h;
6658
+ const themeColor = getThemeColor(spec);
6659
+ const lineStyle = (_b = (_a = spec.line) === null || _a === void 0 ? void 0 : _a.style) !== null && _b !== void 0 ? _b : {};
6660
+ const count = (_e = (_c = spec.data) === null || _c === void 0 ? void 0 : _c.length) !== null && _e !== void 0 ? _e : 0;
6661
+ const symbolSize = 14;
6662
+ const symbolChildren = [];
6663
+ for (let i = 0; i < count; i++) {
6664
+ const idx = i;
6665
+ symbolChildren.push({
6666
+ type: 'symbol',
6667
+ name: `storyline-landscape-curve-symbol-${idx}`,
6668
+ interactive: false,
6669
+ style: {
6670
+ symbolType: 'circle',
6671
+ size: symbolSize,
6672
+ fill: themeColor,
6673
+ x: (_d, ctx) => { var _a, _b; return (_b = (_a = getLandscapeImageCenter(spec, ctx, idx)) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0; },
6674
+ y: (_d, ctx) => { var _a, _b; return (_b = (_a = getLandscapeImageCenter(spec, ctx, idx)) === null || _a === void 0 ? void 0 : _a.y) !== null && _b !== void 0 ? _b : 0; }
6675
+ }
6676
+ });
6677
+ }
6678
+ return {
6679
+ type: 'group',
6680
+ name: 'storyline-landscape-curve',
6681
+ zIndex: vchart.LayoutZIndex.Mark + 2,
6682
+ children: [
6683
+ {
6684
+ type: 'path',
6685
+ name: 'storyline-landscape-curve-path',
6686
+ interactive: false,
6687
+ style: {
6688
+ stroke: (_f = lineStyle.stroke) !== null && _f !== void 0 ? _f : themeColor,
6689
+ lineWidth: (_g = lineStyle.lineWidth) !== null && _g !== void 0 ? _g : 4,
6690
+ lineDash: (_h = lineStyle.lineDash) !== null && _h !== void 0 ? _h : [6, 5],
6691
+ lineCap: 'round',
6692
+ fill: 'transparent',
6693
+ fillOpacity: 0,
6694
+ path: (_d, ctx) => {
6695
+ const points = [];
6696
+ for (let i = 0; i < count; i++) {
6697
+ const center = getLandscapeImageCenter(spec, ctx, i);
6698
+ if (center) {
6699
+ points.push(center);
6700
+ }
6701
+ }
6702
+ return buildSmoothCurvePath(points);
6703
+ }
6704
+ }
6705
+ },
6706
+ ...symbolChildren
6707
+ ]
6708
+ };
6709
+ };
6710
+ const getLandscapeMetrics = (spec, blockWidth, blockHeight, index) => {
6711
+ var _a, _b, _c, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
6712
+ const padding = normalizePadding((_b = (_a = spec.block) === null || _a === void 0 ? void 0 : _a.padding) !== null && _b !== void 0 ? _b : 12);
6713
+ const titleFontSize = Number((_f = (_e = (_c = spec.title) === null || _c === void 0 ? void 0 : _c.style) === null || _e === void 0 ? void 0 : _e.fontSize) !== null && _f !== void 0 ? _f : 14);
6714
+ const titleLineHeight = Number((_j = (_h = (_g = spec.title) === null || _g === void 0 ? void 0 : _g.style) === null || _h === void 0 ? void 0 : _h.lineHeight) !== null && _j !== void 0 ? _j : Math.max(LANDSCAPE_TITLE_LINE_HEIGHT, Math.round(titleFontSize * 1.35)));
6715
+ const contentFontSize = Number((_m = (_l = (_k = spec.content) === null || _k === void 0 ? void 0 : _k.style) === null || _l === void 0 ? void 0 : _l.fontSize) !== null && _m !== void 0 ? _m : LANDSCAPE_CONTENT_FONT_SIZE);
6716
+ const contentLineHeight = Number((_q = (_p = (_o = spec.content) === null || _o === void 0 ? void 0 : _o.style) === null || _p === void 0 ? void 0 : _p.lineHeight) !== null && _q !== void 0 ? _q : LANDSCAPE_CONTENT_LINE_HEIGHT);
6717
+ const imageHeight = Math.max((_s = (_r = spec.image) === null || _r === void 0 ? void 0 : _r.height) !== null && _s !== void 0 ? _s : Math.round(blockHeight * LANDSCAPE_IMAGE_HEIGHT_RATIO), titleLineHeight + padding.top + padding.bottom);
6718
+ const connectorGap = LANDSCAPE_DETACHED_GAP;
6719
+ const contentHeight = LANDSCAPE_CONTENT_LINES * contentLineHeight;
6720
+ const titleToContentGap = LANDSCAPE_TITLE_TO_CONTENT_GAP;
6721
+ const textHeight = titleLineHeight + titleToContentGap + contentHeight;
6722
+ const textOnTop = index % 2 === 0;
6723
+ let textBox;
6724
+ let contentBox;
6725
+ let imageBox;
6726
+ let connector;
6727
+ let groupTop;
6728
+ let groupHeight;
6729
+ const imageX = 0;
6730
+ const connectorX = imageX + blockWidth * LANDSCAPE_CONNECTOR_X_RATIO;
6731
+ const textX = connectorX + LANDSCAPE_TEXT_GAP_FROM_CONNECTOR;
6732
+ const textWidth = Math.max(blockWidth - (textX - imageX), 0);
6733
+ if (textOnTop) {
6734
+ const imageY = 0;
6735
+ const textY = imageY - connectorGap - textHeight;
6736
+ const connectorY1 = imageY;
6737
+ const connectorY2 = textY + titleLineHeight / 2;
6738
+ imageBox = { x: imageX, y: imageY, width: blockWidth, height: imageHeight };
6739
+ textBox = { x: textX, y: textY, width: textWidth, height: textHeight };
6740
+ contentBox = {
6741
+ x: textX,
6742
+ y: textY + titleLineHeight + titleToContentGap,
6743
+ width: textWidth,
6744
+ height: contentHeight
6745
+ };
6746
+ connector = { x1: connectorX, y1: connectorY1, x2: connectorX, y2: connectorY2 };
6747
+ groupTop = textY;
6748
+ groupHeight = imageHeight - groupTop;
6749
+ }
6750
+ else {
6751
+ const imageY = 0;
6752
+ const textY = imageY + imageHeight + connectorGap;
6753
+ const connectorY1 = imageY + imageHeight;
6754
+ const connectorY2 = textY + textHeight;
6755
+ imageBox = { x: imageX, y: imageY, width: blockWidth, height: imageHeight };
6756
+ textBox = { x: textX, y: textY, width: textWidth, height: textHeight };
6757
+ contentBox = {
6758
+ x: textX,
6759
+ y: textY + titleLineHeight + titleToContentGap,
6760
+ width: textWidth,
6761
+ height: contentHeight
6762
+ };
6763
+ connector = { x1: connectorX, y1: connectorY1, x2: connectorX, y2: connectorY2 };
6764
+ groupTop = imageY;
6765
+ groupHeight = textY + textHeight - imageY;
6766
+ }
6767
+ return {
6768
+ padding,
6769
+ titleFontSize,
6770
+ titleLineHeight,
6771
+ contentFontSize,
6772
+ contentLineHeight,
6773
+ contentHeight,
6774
+ blockWidth,
6775
+ imageBox,
6776
+ textBox,
6777
+ contentBox,
6778
+ connector,
6779
+ textOnTop,
6780
+ groupTop,
6781
+ groupHeight
6782
+ };
6783
+ };
6784
+ const buildLandscapeBlockMark = (spec, block, index) => {
6785
+ var _a, _b, _c, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
6786
+ const hasImage = !!block.image;
6787
+ const contentText = Array.isArray(block.content) ? block.content : block.content ? [block.content] : [];
6788
+ const titleFontSize = Number((_c = (_b = (_a = spec.title) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.fontSize) !== null && _c !== void 0 ? _c : 14);
6789
+ const titleLineHeight = Number((_g = (_f = (_e = spec.title) === null || _e === void 0 ? void 0 : _e.style) === null || _f === void 0 ? void 0 : _f.lineHeight) !== null && _g !== void 0 ? _g : Math.round(titleFontSize * 1.35));
6790
+ const getMetrics = (ctx) => {
6791
+ var _a, _b, _c, _e;
6792
+ const layoutBlock = getLayout(spec, ctx).blocks[index];
6793
+ const w = (_a = layoutBlock === null || layoutBlock === void 0 ? void 0 : layoutBlock.width) !== null && _a !== void 0 ? _a : resolveBlockWidth(spec, 0);
6794
+ const h = (_e = (_b = layoutBlock === null || layoutBlock === void 0 ? void 0 : layoutBlock.height) !== null && _b !== void 0 ? _b : (_c = spec.block) === null || _c === void 0 ? void 0 : _c.height) !== null && _e !== void 0 ? _e : DEFAULT_BLOCK_HEIGHT;
6795
+ return getLandscapeMetrics(spec, w, h, index);
6796
+ };
6797
+ const blockStyle = (_j = (_h = spec.block) === null || _h === void 0 ? void 0 : _h.style) !== null && _j !== void 0 ? _j : {};
6798
+ const lineStyle = (_l = (_k = spec.line) === null || _k === void 0 ? void 0 : _k.style) !== null && _l !== void 0 ? _l : {};
6799
+ const themeColor = getThemeColor(spec);
6800
+ const connectorStroke = (_m = lineStyle.stroke) !== null && _m !== void 0 ? _m : themeColor;
6801
+ const connectorLineWidth = (_o = lineStyle.lineWidth) !== null && _o !== void 0 ? _o : 2;
6802
+ const connectorDash = (_p = lineStyle.lineDash) !== null && _p !== void 0 ? _p : [4, 4];
6803
+ return {
6804
+ type: 'group',
6805
+ id: `storyline-block-${(_q = block.id) !== null && _q !== void 0 ? _q : index}`,
6806
+ name: `storyline-block-${index}`,
6807
+ zIndex: vchart.LayoutZIndex.Mark + 1,
6808
+ style: {
6809
+ x: (_d, ctx) => {
6810
+ var _a;
6811
+ const lb = getLayout(spec, ctx).blocks[index];
6812
+ return (_a = lb === null || lb === void 0 ? void 0 : lb.x) !== null && _a !== void 0 ? _a : 0;
6813
+ },
6814
+ y: (_d, ctx) => {
6815
+ var _a, _b, _c, _e, _f, _g, _h;
6816
+ const lb = getLayout(spec, ctx).blocks[index];
6817
+ const m = getMetrics(ctx);
6818
+ const cy = (_b = (_a = lb === null || lb === void 0 ? void 0 : lb.center) === null || _a === void 0 ? void 0 : _a.y) !== null && _b !== void 0 ? _b : ((_c = lb === null || lb === void 0 ? void 0 : lb.y) !== null && _c !== void 0 ? _c : 0) + ((_e = lb === null || lb === void 0 ? void 0 : lb.height) !== null && _e !== void 0 ? _e : 0) / 2;
6819
+ const blockH = (_h = (_f = lb === null || lb === void 0 ? void 0 : lb.height) !== null && _f !== void 0 ? _f : (_g = spec.block) === null || _g === void 0 ? void 0 : _g.height) !== null && _h !== void 0 ? _h : DEFAULT_BLOCK_HEIGHT;
6820
+ const stagger = (index % 2 === 0 ? -1 : 1) * blockH * 0.1;
6821
+ return cy - m.imageBox.height / 2 + stagger;
6822
+ },
6823
+ width: (_d, ctx) => getMetrics(ctx).blockWidth,
6824
+ height: (_d, ctx) => getMetrics(ctx).groupHeight
6825
+ },
6826
+ children: [
6827
+ {
6828
+ type: 'rect',
6829
+ name: `storyline-block-image-bg-${index}`,
6830
+ interactive: false,
6831
+ 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, cornerRadius: 8, fill: '#ffffff', stroke: themeColor, lineWidth: 2 }, blockStyle)
6832
+ },
6833
+ hasImage
6834
+ ? 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, cornerRadius: 8, repeatX: 'no-repeat', repeatY: 'no-repeat', imageMode: 'cover', imagePosition: 'center' }, (_r = spec.image) === null || _r === void 0 ? void 0 : _r.style) })
6835
+ : null,
6836
+ {
6837
+ type: 'path',
6838
+ name: `storyline-block-connector-${index}`,
6839
+ interactive: false,
6840
+ style: {
6841
+ stroke: connectorStroke,
6842
+ lineWidth: connectorLineWidth,
6843
+ lineDash: connectorDash,
6844
+ fill: connectorStroke,
6845
+ path: (_d, ctx) => {
6846
+ const m = getMetrics(ctx);
6847
+ const tipSize = LANDSCAPE_CONNECTOR_ARROW_SIZE;
6848
+ const x = m.connector.x1;
6849
+ const y0 = m.connector.y1;
6850
+ const y1 = m.connector.y2;
6851
+ const tipDir = y1 < y0 ? -1 : 1;
6852
+ const baseY = y1 - tipDir * tipSize;
6853
+ const dashLine = `M ${x} ${y0} L ${x} ${baseY}`;
6854
+ const triangle = `M ${x - tipSize / 2} ${baseY} L ${x + tipSize / 2} ${baseY} L ${x} ${y1} Z`;
6855
+ return `${dashLine} ${triangle}`;
6856
+ }
6857
+ }
6858
+ },
6859
+ block.title
6860
+ ? 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, fontSize: titleFontSize, lineHeight: titleLineHeight, fontWeight: 'bold', fill: '#1f2430', textAlign: 'left', textBaseline: 'top' }, (_s = spec.title) === null || _s === void 0 ? void 0 : _s.style) })
6861
+ : null,
6862
+ contentText.length
6863
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-content-${index}`, interactive: false }, spec.content), { textType: 'rich', 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: buildRichContent(contentText, spec), fontSize: LANDSCAPE_CONTENT_FONT_SIZE, lineHeight: LANDSCAPE_CONTENT_LINE_HEIGHT, textAlign: 'left', textBaseline: 'top', wordBreak: 'break-word', ellipsis: '...', fill: '#596173' }, (_t = spec.content) === null || _t === void 0 ? void 0 : _t.style) })
6864
+ : null
6865
+ ].filter(Boolean)
6866
+ };
6867
+ };
6868
+
6869
+ const PORTRAIT_AXIS_WIDTH = 64;
6870
+ const PORTRAIT_AXIS_PADDING = 50;
6871
+ const PORTRAIT_IMAGE_WIDTH = 180;
6872
+ const PORTRAIT_IMAGE_HEIGHT = 110;
6873
+ const PORTRAIT_IMAGE_GAP_FROM_AXIS = 24;
6874
+ const PORTRAIT_SHADOW_OFFSET_X = 36;
6875
+ const PORTRAIT_SHADOW_OFFSET_Y = 20;
6876
+ const PORTRAIT_SHADOW_SCALE = 1.12;
6877
+ const PORTRAIT_TEXT_GAP_FROM_IMAGE = 8;
6878
+ const PORTRAIT_CONTENT_LINES = 3;
6879
+ const PORTRAIT_TITLE_LINE_HEIGHT = 19;
6880
+ const PORTRAIT_CONTENT_LINE_HEIGHT = 18;
6881
+ const PORTRAIT_CONTENT_FONT_SIZE = 12;
6882
+ const PORTRAIT_TITLE_TO_CONTENT_GAP = 4;
6883
+ const getPortraitAxisRect = (spec, ctx) => {
6884
+ const blocks = getLayout(spec, ctx).blocks;
6885
+ if (!blocks.length) {
6886
+ return { x: 0, y: 0, width: 0, height: 0 };
6887
+ }
6888
+ const firstCy = blocks[0].center.y;
6889
+ const lastCy = blocks[blocks.length - 1].center.y;
6890
+ const top = Math.min(firstCy, lastCy);
6891
+ const bottom = Math.max(firstCy, lastCy);
6892
+ const cx = blocks[0].center.x;
6893
+ return {
6894
+ x: cx - PORTRAIT_AXIS_WIDTH / 2,
6895
+ y: top - PORTRAIT_AXIS_PADDING,
6896
+ width: PORTRAIT_AXIS_WIDTH,
6897
+ height: bottom - top + PORTRAIT_AXIS_PADDING * 2
6898
+ };
6899
+ };
6900
+ const buildPortraitAxisMark = (spec) => {
6901
+ var _a, _b, _c, _e, _f, _g;
6902
+ const themeColor = getThemeColor(spec);
6903
+ const lineStyle = (_b = (_a = spec.line) === null || _a === void 0 ? void 0 : _a.style) !== null && _b !== void 0 ? _b : {};
6904
+ const defaultFill = {
6905
+ gradient: 'linear',
6906
+ x0: 0,
6907
+ y0: 0,
6908
+ x1: 0,
6909
+ y1: 1,
6910
+ stops: [
6911
+ { offset: 0, color: withAlpha(themeColor, 0.2) },
6912
+ { offset: 1, color: withAlpha(themeColor, 1) }
6913
+ ]
6914
+ };
6915
+ return {
6916
+ type: 'group',
6917
+ name: 'storyline-portrait-axis',
6918
+ zIndex: vchart.LayoutZIndex.Mark,
6919
+ children: [
6920
+ {
6921
+ type: 'rect',
6922
+ name: 'storyline-portrait-axis-rect',
6923
+ interactive: false,
6924
+ style: {
6925
+ fill: (_c = lineStyle.fill) !== null && _c !== void 0 ? _c : defaultFill,
6926
+ stroke: (_e = lineStyle.stroke) !== null && _e !== void 0 ? _e : false,
6927
+ lineWidth: (_f = lineStyle.lineWidth) !== null && _f !== void 0 ? _f : 0,
6928
+ cornerRadius: (_g = lineStyle.cornerRadius) !== null && _g !== void 0 ? _g : 0,
6929
+ x: (_d, ctx) => getPortraitAxisRect(spec, ctx).x,
6930
+ y: (_d, ctx) => getPortraitAxisRect(spec, ctx).y,
6931
+ width: (_d, ctx) => getPortraitAxisRect(spec, ctx).width,
6932
+ height: (_d, ctx) => getPortraitAxisRect(spec, ctx).height
6933
+ }
6934
+ }
6935
+ ]
6936
+ };
6937
+ };
6938
+ const getPortraitMetrics = (spec, blockWidth, _blockHeight, index) => {
6939
+ var _a, _b, _c, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
6940
+ const titleFontSize = Number((_c = (_b = (_a = spec.title) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.fontSize) !== null && _c !== void 0 ? _c : 14);
6941
+ const titleLineHeight = Number((_g = (_f = (_e = spec.title) === null || _e === void 0 ? void 0 : _e.style) === null || _f === void 0 ? void 0 : _f.lineHeight) !== null && _g !== void 0 ? _g : Math.max(PORTRAIT_TITLE_LINE_HEIGHT, Math.round(titleFontSize * 1.35)));
6942
+ const contentFontSize = Number((_k = (_j = (_h = spec.content) === null || _h === void 0 ? void 0 : _h.style) === null || _j === void 0 ? void 0 : _j.fontSize) !== null && _k !== void 0 ? _k : PORTRAIT_CONTENT_FONT_SIZE);
6943
+ const contentLineHeight = Number((_o = (_m = (_l = spec.content) === null || _l === void 0 ? void 0 : _l.style) === null || _m === void 0 ? void 0 : _m.lineHeight) !== null && _o !== void 0 ? _o : PORTRAIT_CONTENT_LINE_HEIGHT);
6944
+ const contentHeight = PORTRAIT_CONTENT_LINES * contentLineHeight;
6945
+ const titleToContentGap = PORTRAIT_TITLE_TO_CONTENT_GAP;
6946
+ const textHeight = titleLineHeight + titleToContentGap + contentHeight;
6947
+ const imageWidth = (_q = (_p = spec.image) === null || _p === void 0 ? void 0 : _p.width) !== null && _q !== void 0 ? _q : PORTRAIT_IMAGE_WIDTH;
6948
+ const imageHeight = (_s = (_r = spec.image) === null || _r === void 0 ? void 0 : _r.height) !== null && _s !== void 0 ? _s : PORTRAIT_IMAGE_HEIGHT;
6949
+ const onLeft = index % 2 === 0;
6950
+ const axisHalf = PORTRAIT_AXIS_WIDTH / 2;
6951
+ const imageX = onLeft
6952
+ ? -axisHalf - PORTRAIT_IMAGE_GAP_FROM_AXIS - imageWidth
6953
+ : axisHalf + PORTRAIT_IMAGE_GAP_FROM_AXIS;
6954
+ const imageY = -imageHeight / 2;
6955
+ const textX = imageX;
6956
+ const textY = imageY + imageHeight + PORTRAIT_TEXT_GAP_FROM_IMAGE;
6957
+ const textWidth = imageWidth;
6958
+ const contentBox = {
6959
+ x: textX,
6960
+ y: textY + titleLineHeight + titleToContentGap,
6961
+ width: textWidth,
6962
+ height: contentHeight
6963
+ };
6964
+ const shadowOffsetX = PORTRAIT_SHADOW_OFFSET_X;
6965
+ const shadowOffsetY = PORTRAIT_SHADOW_OFFSET_Y;
6966
+ const shadowWidth = imageWidth * PORTRAIT_SHADOW_SCALE;
6967
+ const shadowHeight = imageHeight * PORTRAIT_SHADOW_SCALE;
6968
+ const baseShadowX = imageX - (shadowWidth - imageWidth) / 2;
6969
+ const baseShadowY = imageY - (shadowHeight - imageHeight) / 2;
6970
+ const shadowBox = {
6971
+ x: baseShadowX + (onLeft ? -shadowOffsetX : shadowOffsetX),
6972
+ y: baseShadowY + shadowOffsetY,
6973
+ width: shadowWidth,
6974
+ height: shadowHeight
6975
+ };
6976
+ return {
6977
+ onLeft,
6978
+ titleFontSize,
6979
+ titleLineHeight,
6980
+ contentFontSize,
6981
+ contentLineHeight,
6982
+ blockWidth,
6983
+ imageBox: { x: imageX, y: imageY, width: imageWidth, height: imageHeight },
6984
+ shadowBox,
6985
+ textBox: { x: textX, y: textY, width: textWidth, height: textHeight },
6986
+ contentBox
6987
+ };
6988
+ };
6989
+ const buildPortraitBlockMark = (spec, block, index) => {
6990
+ var _a, _b, _c, _e, _f, _g, _h, _j, _k, _l, _m, _o;
6991
+ const hasImage = !!block.image;
6992
+ const contentText = Array.isArray(block.content) ? block.content : block.content ? [block.content] : [];
6993
+ const titleFontSize = Number((_c = (_b = (_a = spec.title) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.fontSize) !== null && _c !== void 0 ? _c : 14);
6994
+ const titleLineHeight = Number((_g = (_f = (_e = spec.title) === null || _e === void 0 ? void 0 : _e.style) === null || _f === void 0 ? void 0 : _f.lineHeight) !== null && _g !== void 0 ? _g : Math.max(PORTRAIT_TITLE_LINE_HEIGHT, Math.round(titleFontSize * 1.35)));
6995
+ const getMetrics = (ctx) => {
6996
+ var _a, _b, _c, _e;
6997
+ const lb = getLayout(spec, ctx).blocks[index];
6998
+ const w = (_a = lb === null || lb === void 0 ? void 0 : lb.width) !== null && _a !== void 0 ? _a : resolveBlockWidth(spec, 0);
6999
+ const h = (_e = (_b = lb === null || lb === void 0 ? void 0 : lb.height) !== null && _b !== void 0 ? _b : (_c = spec.block) === null || _c === void 0 ? void 0 : _c.height) !== null && _e !== void 0 ? _e : DEFAULT_BLOCK_HEIGHT;
7000
+ return getPortraitMetrics(spec, w, h, index);
7001
+ };
7002
+ const themeColor = getThemeColor(spec);
7003
+ const blockStyle = (_j = (_h = spec.block) === null || _h === void 0 ? void 0 : _h.style) !== null && _j !== void 0 ? _j : {};
7004
+ return {
7005
+ type: 'group',
7006
+ id: `storyline-block-${(_k = block.id) !== null && _k !== void 0 ? _k : index}`,
7007
+ name: `storyline-block-${index}`,
7008
+ zIndex: vchart.LayoutZIndex.Mark + 1,
7009
+ style: {
7010
+ x: (_d, ctx) => {
7011
+ var _a, _b;
7012
+ const lb = getLayout(spec, ctx).blocks[index];
7013
+ return (_b = (_a = lb === null || lb === void 0 ? void 0 : lb.center) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0;
7014
+ },
7015
+ y: (_d, ctx) => {
7016
+ var _a, _b;
7017
+ const lb = getLayout(spec, ctx).blocks[index];
7018
+ return (_b = (_a = lb === null || lb === void 0 ? void 0 : lb.center) === null || _a === void 0 ? void 0 : _a.y) !== null && _b !== void 0 ? _b : 0;
7019
+ }
7020
+ },
7021
+ children: [
7022
+ hasImage
7023
+ ? {
7024
+ type: 'image',
7025
+ name: `storyline-block-shadow-image-${index}`,
7026
+ interactive: false,
7027
+ style: {
7028
+ x: (_d, ctx) => getMetrics(ctx).shadowBox.x,
7029
+ y: (_d, ctx) => getMetrics(ctx).shadowBox.y,
7030
+ width: (_d, ctx) => getMetrics(ctx).shadowBox.width,
7031
+ height: (_d, ctx) => getMetrics(ctx).shadowBox.height,
7032
+ image: block.image,
7033
+ cornerRadius: 8,
7034
+ repeatX: 'no-repeat',
7035
+ repeatY: 'no-repeat',
7036
+ imageMode: 'cover',
7037
+ imagePosition: 'center'
7038
+ }
7039
+ }
7040
+ : null,
7041
+ hasImage
7042
+ ? {
7043
+ type: 'rect',
7044
+ name: `storyline-block-shadow-mask-${index}`,
7045
+ interactive: false,
7046
+ style: {
7047
+ x: (_d, ctx) => getMetrics(ctx).shadowBox.x,
7048
+ y: (_d, ctx) => getMetrics(ctx).shadowBox.y,
7049
+ width: (_d, ctx) => getMetrics(ctx).shadowBox.width,
7050
+ height: (_d, ctx) => getMetrics(ctx).shadowBox.height,
7051
+ cornerRadius: 8,
7052
+ stroke: false,
7053
+ lineWidth: 0,
7054
+ fill: {
7055
+ gradient: 'linear',
7056
+ x0: 0,
7057
+ y0: 0,
7058
+ x1: 0,
7059
+ y1: 1,
7060
+ stops: [
7061
+ { offset: 0, color: withAlpha(themeColor, 0.2) },
7062
+ { offset: 1, color: withAlpha(themeColor, 1) }
7063
+ ]
7064
+ }
7065
+ }
7066
+ }
7067
+ : null,
7068
+ {
7069
+ type: 'rect',
7070
+ name: `storyline-block-image-bg-${index}`,
7071
+ interactive: false,
7072
+ 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, cornerRadius: 8, fill: '#ffffff', stroke: themeColor, lineWidth: 2 }, blockStyle)
7073
+ },
7074
+ hasImage
7075
+ ? 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, cornerRadius: 8, repeatX: 'no-repeat', repeatY: 'no-repeat', imageMode: 'cover', imagePosition: 'center' }, (_l = spec.image) === null || _l === void 0 ? void 0 : _l.style) })
7076
+ : null,
7077
+ block.title
7078
+ ? 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, fontSize: titleFontSize, lineHeight: titleLineHeight, fontWeight: 'bold', fill: '#1f2430', textAlign: 'left', textBaseline: 'top' }, (_m = spec.title) === null || _m === void 0 ? void 0 : _m.style) })
7079
+ : null,
7080
+ contentText.length
7081
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-content-${index}`, interactive: false }, spec.content), { textType: 'rich', 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: buildRichContent(contentText, spec), fontSize: PORTRAIT_CONTENT_FONT_SIZE, lineHeight: PORTRAIT_CONTENT_LINE_HEIGHT, textAlign: 'left', textBaseline: 'top', wordBreak: 'break-word', ellipsis: '...', fill: '#596173' }, (_o = spec.content) === null || _o === void 0 ? void 0 : _o.style) })
7082
+ : null
7083
+ ].filter(Boolean)
7084
+ };
7085
+ };
7086
+
7087
+ const DOME_BLOCK_IMAGE_SIZE = 140;
7088
+ const DOME_TEXT_GAP_FROM_IMAGE = 10;
7089
+ const DOME_TITLE_LINE_HEIGHT = 19;
7090
+ const DOME_CONTENT_LINE_HEIGHT = 17;
7091
+ const DOME_CONTENT_FONT_SIZE = 12;
7092
+ const DOME_TEXT_BOX_HEIGHT = 300;
7093
+ const DOME_TITLE_TO_CONTENT_GAP = 4;
7094
+ const DOME_TEXT_LEFT_PADDING = 20;
7095
+ const DOME_CENTER_IMAGE_WIDTH_RATIO = 0.32;
7096
+ const DOME_CENTER_IMAGE_HEIGHT_RATIO = 0.32;
7097
+ const DOME_ARC_TOP_GAP_FROM_CENTER_IMAGE = 300;
7098
+ const getDomeCenterImageRect = (spec, ctx) => {
7099
+ var _a, _b, _c, _e, _f;
7100
+ const { width, height, startX, startY } = getRegionGeometry(ctx);
7101
+ const padding = normalizePadding((_a = spec.block) === null || _a === void 0 ? void 0 : _a.padding);
7102
+ const innerWidth = Math.max(width - padding.left - padding.right, 1);
7103
+ const innerHeight = Math.max(height - padding.top - padding.bottom, 1);
7104
+ const w = Math.max((_c = (_b = spec.centerImage) === null || _b === void 0 ? void 0 : _b.width) !== null && _c !== void 0 ? _c : innerWidth * DOME_CENTER_IMAGE_WIDTH_RATIO, 80);
7105
+ const h = Math.max((_f = (_e = spec.centerImage) === null || _e === void 0 ? void 0 : _e.height) !== null && _f !== void 0 ? _f : innerHeight * DOME_CENTER_IMAGE_HEIGHT_RATIO, 60);
7106
+ const cx = startX + padding.left + innerWidth / 2;
7107
+ const top = startY + padding.top + innerHeight - h;
7108
+ return { x: cx - w / 2, y: top, width: w, height: h };
7109
+ };
7110
+ const getDomeArcGeometry = (spec, ctx) => {
7111
+ var _a, _b, _c, _e;
7112
+ const { width, startX } = getRegionGeometry(ctx);
7113
+ const blockPadding = normalizePadding((_a = spec.block) === null || _a === void 0 ? void 0 : _a.padding);
7114
+ const innerWidth = Math.max(width - blockPadding.left - blockPadding.right, 1);
7115
+ const blockWidth = resolveBlockWidth(spec, width);
7116
+ const layoutOpt = normalizeLayout(spec.layout);
7117
+ const startAngle = (_b = layoutOpt.startAngle) !== null && _b !== void 0 ? _b : 200;
7118
+ const endAngle = (_c = layoutOpt.endAngle) !== null && _c !== void 0 ? _c : 340;
7119
+ const ratio = (_e = layoutOpt.radiusRatio) !== null && _e !== void 0 ? _e : 0.88;
7120
+ const rx = Math.max((innerWidth - blockWidth) / 2, 1) * ratio;
7121
+ const centerRect = getDomeCenterImageRect(spec, ctx);
7122
+ const centerTop = centerRect.y;
7123
+ const centerBottom = centerRect.y + centerRect.height;
7124
+ const sinStart = Math.sin((startAngle / 180) * Math.PI);
7125
+ const denom = Math.max(1 + sinStart, 0.05);
7126
+ const ry = (centerRect.height + DOME_ARC_TOP_GAP_FROM_CENTER_IMAGE) / denom;
7127
+ const cy = centerBottom - ry * sinStart;
7128
+ return {
7129
+ cx: startX + blockPadding.left + innerWidth / 2,
7130
+ cy,
7131
+ rx,
7132
+ ry,
7133
+ startAngle,
7134
+ endAngle,
7135
+ centerTop,
7136
+ centerBottom
7137
+ };
7138
+ };
7139
+ const getDomeBlockCenter = (spec, ctx, index) => {
7140
+ var _a, _b, _c, _e;
7141
+ const arc = getDomeArcGeometry(spec, ctx);
7142
+ const count = (_b = (_a = spec.data) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
7143
+ if (count <= 0) {
7144
+ return { x: arc.cx, y: arc.cy };
7145
+ }
7146
+ const t = count === 1 ? 0.5 : index / (count - 1);
7147
+ const angle = ((arc.startAngle + (arc.endAngle - arc.startAngle) * t) / 180) * Math.PI;
7148
+ const px = arc.cx + Math.cos(angle) * arc.rx;
7149
+ const py = arc.cy + Math.sin(angle) * arc.ry;
7150
+ const nxRaw = Math.cos(angle) / arc.rx;
7151
+ const nyRaw = Math.sin(angle) / arc.ry;
7152
+ const nLen = Math.hypot(nxRaw, nyRaw) || 1;
7153
+ const nx = nxRaw / nLen;
7154
+ const ny = nyRaw / nLen;
7155
+ const imageHeight = (_e = (_c = spec.image) === null || _c === void 0 ? void 0 : _c.height) !== null && _e !== void 0 ? _e : DOME_BLOCK_IMAGE_SIZE;
7156
+ const offset = imageHeight / 2;
7157
+ return { x: px + nx * offset, y: py + ny * offset };
7158
+ };
7159
+ const buildDomeArcMark = (spec) => {
7160
+ var _a;
7161
+ if (((_a = spec.line) === null || _a === void 0 ? void 0 : _a.visible) !== true) {
7162
+ return null;
7163
+ }
7164
+ const themeColor = getThemeColor(spec);
7165
+ return {
7166
+ type: 'group',
7167
+ name: 'storyline-dome-arc',
7168
+ zIndex: vchart.LayoutZIndex.Mark,
7169
+ children: [
7170
+ {
7171
+ type: 'path',
7172
+ name: 'storyline-dome-arc-path',
7173
+ interactive: false,
7174
+ style: {
7175
+ stroke: themeColor,
7176
+ lineWidth: 2,
7177
+ lineCap: 'round',
7178
+ fill: 'transparent',
7179
+ fillOpacity: 0,
7180
+ path: (_d, ctx) => {
7181
+ const arc = getDomeArcGeometry(spec, ctx);
7182
+ const span = arc.endAngle - arc.startAngle;
7183
+ const samples = 64;
7184
+ const segments = [];
7185
+ for (let i = 0; i <= samples; i++) {
7186
+ const t = i / samples;
7187
+ const angle = ((arc.startAngle + span * t) / 180) * Math.PI;
7188
+ const x = arc.cx + Math.cos(angle) * arc.rx;
7189
+ const y = arc.cy + Math.sin(angle) * arc.ry;
7190
+ segments.push(`${i === 0 ? 'M' : 'L'} ${x.toFixed(2)} ${y.toFixed(2)}`);
7191
+ }
7192
+ return segments.join(' ');
7193
+ }
7194
+ }
7195
+ }
7196
+ ]
7197
+ };
7198
+ };
7199
+ const buildDomeCenterImageMark = (spec) => {
7200
+ var _a, _b, _c, _e;
7201
+ const visible = ((_a = spec.centerImage) === null || _a === void 0 ? void 0 : _a.visible) !== false;
7202
+ if (!visible) {
7203
+ return null;
7204
+ }
7205
+ const themeColor = getThemeColor(spec);
7206
+ const hasImage = !!((_b = spec.centerImage) === null || _b === void 0 ? void 0 : _b.image);
7207
+ const symbolGradient = {
7208
+ gradient: 'linear',
7209
+ x0: 0.5,
7210
+ y0: 0,
7211
+ x1: 0.5,
7212
+ y1: 1,
7213
+ stops: [
7214
+ { offset: 0, color: withAlpha(themeColor, 0.15) },
7215
+ { offset: 1, color: themeColor }
7216
+ ]
7217
+ };
7218
+ return {
7219
+ type: 'group',
7220
+ name: 'storyline-dome-center',
7221
+ zIndex: vchart.LayoutZIndex.Mark,
7222
+ children: [
7223
+ {
7224
+ type: 'symbol',
7225
+ name: 'storyline-dome-center-symbol',
7226
+ interactive: false,
7227
+ style: {
7228
+ x: (_d, ctx) => {
7229
+ const r = getDomeCenterImageRect(spec, ctx);
7230
+ return r.x + r.width / 2;
7231
+ },
7232
+ y: (_d, ctx) => {
7233
+ const r = getDomeCenterImageRect(spec, ctx);
7234
+ return r.y + r.height / 2;
7235
+ },
7236
+ size: (_d, ctx) => {
7237
+ const r = getDomeCenterImageRect(spec, ctx);
7238
+ return Math.max(r.width, r.height) * 1.1;
7239
+ },
7240
+ symbolType: 'circle',
7241
+ fill: symbolGradient,
7242
+ stroke: themeColor,
7243
+ lineWidth: 2
7244
+ }
7245
+ },
7246
+ {
7247
+ type: 'rect',
7248
+ name: 'storyline-dome-center-rect',
7249
+ interactive: false,
7250
+ style: {
7251
+ x: (_d, ctx) => getDomeCenterImageRect(spec, ctx).x,
7252
+ y: (_d, ctx) => getDomeCenterImageRect(spec, ctx).y,
7253
+ width: (_d, ctx) => getDomeCenterImageRect(spec, ctx).width,
7254
+ height: (_d, ctx) => getDomeCenterImageRect(spec, ctx).height,
7255
+ cornerRadius: 12,
7256
+ fill: '#ffffff',
7257
+ stroke: themeColor,
7258
+ lineWidth: 2
7259
+ }
7260
+ },
7261
+ hasImage
7262
+ ? Object.assign(Object.assign({ type: 'image', name: 'storyline-dome-center-image', interactive: false }, spec.centerImage), { style: Object.assign({ x: (_d, ctx) => getDomeCenterImageRect(spec, ctx).x, y: (_d, ctx) => getDomeCenterImageRect(spec, ctx).y, width: (_d, ctx) => getDomeCenterImageRect(spec, ctx).width, height: (_d, ctx) => getDomeCenterImageRect(spec, ctx).height, image: (_c = spec.centerImage) === null || _c === void 0 ? void 0 : _c.image, cornerRadius: 12, repeatX: 'no-repeat', repeatY: 'no-repeat', imageMode: 'cover', imagePosition: 'center' }, (_e = spec.centerImage) === null || _e === void 0 ? void 0 : _e.style) })
7263
+ : null
7264
+ ].filter(Boolean)
7265
+ };
7266
+ };
7267
+ const getDomeBlockMetrics = (spec) => {
7268
+ var _a, _b, _c, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
7269
+ const titleFontSize = Number((_c = (_b = (_a = spec.title) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.fontSize) !== null && _c !== void 0 ? _c : 14);
7270
+ const titleLineHeight = Number((_g = (_f = (_e = spec.title) === null || _e === void 0 ? void 0 : _e.style) === null || _f === void 0 ? void 0 : _f.lineHeight) !== null && _g !== void 0 ? _g : Math.max(DOME_TITLE_LINE_HEIGHT, Math.round(titleFontSize * 1.35)));
7271
+ const contentFontSize = Number((_k = (_j = (_h = spec.content) === null || _h === void 0 ? void 0 : _h.style) === null || _j === void 0 ? void 0 : _j.fontSize) !== null && _k !== void 0 ? _k : DOME_CONTENT_FONT_SIZE);
7272
+ const contentLineHeight = Number((_o = (_m = (_l = spec.content) === null || _l === void 0 ? void 0 : _l.style) === null || _m === void 0 ? void 0 : _m.lineHeight) !== null && _o !== void 0 ? _o : DOME_CONTENT_LINE_HEIGHT);
7273
+ const titleToContentGap = DOME_TITLE_TO_CONTENT_GAP;
7274
+ const textHeight = DOME_TEXT_BOX_HEIGHT;
7275
+ const contentHeight = Math.max(textHeight - titleLineHeight - titleToContentGap, contentLineHeight);
7276
+ const imageWidth = (_q = (_p = spec.image) === null || _p === void 0 ? void 0 : _p.width) !== null && _q !== void 0 ? _q : DOME_BLOCK_IMAGE_SIZE;
7277
+ const imageHeight = (_s = (_r = spec.image) === null || _r === void 0 ? void 0 : _r.height) !== null && _s !== void 0 ? _s : DOME_BLOCK_IMAGE_SIZE;
7278
+ const imageBox = {
7279
+ x: -imageWidth / 2,
7280
+ y: -imageHeight / 2,
7281
+ width: imageWidth,
7282
+ height: imageHeight
7283
+ };
7284
+ const textBox = {
7285
+ x: -imageWidth / 2 + DOME_TEXT_LEFT_PADDING,
7286
+ y: imageBox.y - DOME_TEXT_GAP_FROM_IMAGE - textHeight,
7287
+ width: imageWidth - DOME_TEXT_LEFT_PADDING,
7288
+ height: textHeight
7289
+ };
7290
+ const contentBox = {
7291
+ x: textBox.x,
7292
+ y: textBox.y + titleLineHeight + titleToContentGap,
7293
+ width: textBox.width,
7294
+ height: contentHeight
7295
+ };
7296
+ return {
7297
+ titleFontSize,
7298
+ titleLineHeight,
7299
+ contentFontSize,
7300
+ contentLineHeight,
7301
+ imageBox,
7302
+ textBox,
7303
+ contentBox
7304
+ };
7305
+ };
7306
+ const buildDomeBlockMark = (spec, block, index) => {
7307
+ var _a, _b, _c, _e;
7308
+ const hasImage = !!block.image;
7309
+ const contentText = Array.isArray(block.content) ? block.content : block.content ? [block.content] : [];
7310
+ const themeColor = getThemeColor(spec);
7311
+ const metrics = getDomeBlockMetrics(spec);
7312
+ return {
7313
+ type: 'group',
7314
+ id: `storyline-block-${(_a = block.id) !== null && _a !== void 0 ? _a : index}`,
7315
+ name: `storyline-block-${index}`,
7316
+ zIndex: vchart.LayoutZIndex.Mark + 1,
7317
+ style: {
7318
+ x: (_d, ctx) => getDomeBlockCenter(spec, ctx, index).x,
7319
+ y: (_d, ctx) => getDomeBlockCenter(spec, ctx, index).y
7320
+ },
7321
+ children: [
7322
+ {
7323
+ type: 'rect',
7324
+ name: `storyline-block-connector-${index}`,
7325
+ interactive: false,
7326
+ style: {
7327
+ x: metrics.imageBox.x,
7328
+ y: metrics.textBox.y,
7329
+ width: 2,
7330
+ height: Math.max(metrics.imageBox.y - metrics.textBox.y, 0),
7331
+ fill: themeColor,
7332
+ fillOpacity: 0.6
7333
+ }
7334
+ },
7335
+ hasImage
7336
+ ? Object.assign(Object.assign({ type: 'image', name: `storyline-block-image-${index}`, interactive: false }, omitImageLayoutSpec(spec.image)), { style: Object.assign({ x: metrics.imageBox.x, y: metrics.imageBox.y, width: metrics.imageBox.width, height: metrics.imageBox.height, image: block.image, cornerRadius: Math.min(metrics.imageBox.width, metrics.imageBox.height) / 2, repeatX: 'no-repeat', repeatY: 'no-repeat', imageMode: 'cover', imagePosition: 'center', stroke: themeColor, lineWidth: 2 }, (_b = spec.image) === null || _b === void 0 ? void 0 : _b.style) })
7337
+ : {
7338
+ type: 'rect',
7339
+ name: `storyline-block-image-bg-${index}`,
7340
+ interactive: false,
7341
+ style: {
7342
+ x: metrics.imageBox.x,
7343
+ y: metrics.imageBox.y,
7344
+ width: metrics.imageBox.width,
7345
+ height: metrics.imageBox.height,
7346
+ cornerRadius: Math.min(metrics.imageBox.width, metrics.imageBox.height) / 2,
7347
+ fill: '#ffffff',
7348
+ stroke: themeColor,
7349
+ lineWidth: 2
7350
+ }
7351
+ },
7352
+ block.title
7353
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-title-${index}`, interactive: false }, spec.title), { style: Object.assign({ x: metrics.textBox.x, y: metrics.textBox.y, text: block.title, maxLineWidth: metrics.textBox.width, fontSize: metrics.titleFontSize, lineHeight: metrics.titleLineHeight, fontWeight: 'bold', fill: '#1f2430', textAlign: 'left', textBaseline: 'top' }, (_c = spec.title) === null || _c === void 0 ? void 0 : _c.style) })
7354
+ : null,
7355
+ contentText.length
7356
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-content-${index}`, interactive: false }, spec.content), { textType: 'rich', style: Object.assign({ x: metrics.contentBox.x, y: metrics.contentBox.y, width: metrics.contentBox.width, height: metrics.contentBox.height, maxLineWidth: metrics.contentBox.width, heightLimit: metrics.contentBox.height, text: buildRichContent(contentText, spec), fontSize: DOME_CONTENT_FONT_SIZE, lineHeight: DOME_CONTENT_LINE_HEIGHT, textAlign: 'left', textBaseline: 'top', wordBreak: 'break-word', ellipsis: '...', fill: '#596173' }, (_e = spec.content) === null || _e === void 0 ? void 0 : _e.style) })
7357
+ : null
7358
+ ].filter(Boolean)
7359
+ };
7360
+ };
7361
+
7362
+ const BOWL_BLOCK_IMAGE_SIZE = 140;
7363
+ const BOWL_TEXT_GAP_FROM_IMAGE = 10;
7364
+ const BOWL_TITLE_LINE_HEIGHT = 19;
7365
+ const BOWL_CONTENT_LINE_HEIGHT = 17;
7366
+ const BOWL_CONTENT_FONT_SIZE = 12;
7367
+ const BOWL_TEXT_BOX_HEIGHT = 300;
7368
+ const BOWL_TITLE_TO_CONTENT_GAP = 4;
7369
+ const BOWL_TEXT_LEFT_PADDING = 20;
7370
+ const BOWL_CENTER_IMAGE_WIDTH_RATIO = 0.32;
7371
+ const BOWL_CENTER_IMAGE_HEIGHT_RATIO = 0.32;
7372
+ const BOWL_ARC_BOTTOM_GAP_FROM_CENTER_IMAGE = 300;
7373
+ const getBowlCenterImageRect = (spec, ctx) => {
7374
+ var _a, _b, _c, _e, _f;
7375
+ const { width, height, startX, startY } = getRegionGeometry(ctx);
7376
+ const padding = normalizePadding((_a = spec.block) === null || _a === void 0 ? void 0 : _a.padding);
7377
+ const innerWidth = Math.max(width - padding.left - padding.right, 1);
7378
+ const innerHeight = Math.max(height - padding.top - padding.bottom, 1);
7379
+ const w = Math.max((_c = (_b = spec.centerImage) === null || _b === void 0 ? void 0 : _b.width) !== null && _c !== void 0 ? _c : innerWidth * BOWL_CENTER_IMAGE_WIDTH_RATIO, 80);
7380
+ const h = Math.max((_f = (_e = spec.centerImage) === null || _e === void 0 ? void 0 : _e.height) !== null && _f !== void 0 ? _f : innerHeight * BOWL_CENTER_IMAGE_HEIGHT_RATIO, 60);
7381
+ const cx = startX + padding.left + innerWidth / 2;
7382
+ const top = startY + padding.top;
7383
+ return { x: cx - w / 2, y: top, width: w, height: h };
7384
+ };
7385
+ const getBowlArcGeometry = (spec, ctx) => {
7386
+ var _a, _b, _c, _e;
7387
+ const { width, startX } = getRegionGeometry(ctx);
7388
+ const blockPadding = normalizePadding((_a = spec.block) === null || _a === void 0 ? void 0 : _a.padding);
7389
+ const innerWidth = Math.max(width - blockPadding.left - blockPadding.right, 1);
7390
+ const blockWidth = resolveBlockWidth(spec, width);
7391
+ const layoutOpt = normalizeLayout(spec.layout);
7392
+ const startAngle = (_b = layoutOpt.startAngle) !== null && _b !== void 0 ? _b : 20;
7393
+ const endAngle = (_c = layoutOpt.endAngle) !== null && _c !== void 0 ? _c : 160;
7394
+ const ratio = (_e = layoutOpt.radiusRatio) !== null && _e !== void 0 ? _e : 0.88;
7395
+ const rx = Math.max((innerWidth - blockWidth) / 2, 1) * ratio;
7396
+ const centerRect = getBowlCenterImageRect(spec, ctx);
7397
+ const centerTop = centerRect.y;
7398
+ const centerBottom = centerRect.y + centerRect.height;
7399
+ const sinStart = Math.sin((startAngle / 180) * Math.PI);
7400
+ const denom = Math.max(1 - sinStart, 0.05);
7401
+ const ry = (centerRect.height + BOWL_ARC_BOTTOM_GAP_FROM_CENTER_IMAGE) / denom;
7402
+ const cy = centerTop - ry * sinStart;
7403
+ return {
7404
+ cx: startX + blockPadding.left + innerWidth / 2,
7405
+ cy,
7406
+ rx,
7407
+ ry,
7408
+ startAngle,
7409
+ endAngle,
7410
+ centerTop,
7411
+ centerBottom
7412
+ };
7413
+ };
7414
+ const getBowlBlockCenter = (spec, ctx, index) => {
7415
+ var _a, _b, _c, _e;
7416
+ const arc = getBowlArcGeometry(spec, ctx);
7417
+ const count = (_b = (_a = spec.data) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
7418
+ if (count <= 0) {
7419
+ return { x: arc.cx, y: arc.cy };
7420
+ }
7421
+ const t = count === 1 ? 0.5 : index / (count - 1);
7422
+ const angle = ((arc.startAngle + (arc.endAngle - arc.startAngle) * t) / 180) * Math.PI;
7423
+ const px = arc.cx + Math.cos(angle) * arc.rx;
7424
+ const py = arc.cy + Math.sin(angle) * arc.ry;
7425
+ const nxRaw = Math.cos(angle) / arc.rx;
7426
+ const nyRaw = Math.sin(angle) / arc.ry;
7427
+ const nLen = Math.hypot(nxRaw, nyRaw) || 1;
7428
+ const nx = nxRaw / nLen;
7429
+ const ny = nyRaw / nLen;
7430
+ const imageHeight = (_e = (_c = spec.image) === null || _c === void 0 ? void 0 : _c.height) !== null && _e !== void 0 ? _e : BOWL_BLOCK_IMAGE_SIZE;
7431
+ const offset = imageHeight / 2;
7432
+ return { x: px + nx * offset, y: py + ny * offset };
7433
+ };
7434
+ const buildBowlArcMark = (spec) => {
7435
+ var _a;
7436
+ if (((_a = spec.line) === null || _a === void 0 ? void 0 : _a.visible) !== true) {
7437
+ return null;
7438
+ }
7439
+ const themeColor = getThemeColor(spec);
7440
+ return {
7441
+ type: 'group',
7442
+ name: 'storyline-bowl-arc',
7443
+ zIndex: vchart.LayoutZIndex.Mark,
7444
+ children: [
7445
+ {
7446
+ type: 'path',
7447
+ name: 'storyline-bowl-arc-path',
7448
+ interactive: false,
7449
+ style: {
7450
+ stroke: themeColor,
7451
+ lineWidth: 2,
7452
+ lineCap: 'round',
7453
+ fill: 'transparent',
7454
+ fillOpacity: 0,
7455
+ path: (_d, ctx) => {
7456
+ const arc = getBowlArcGeometry(spec, ctx);
7457
+ const span = arc.endAngle - arc.startAngle;
7458
+ const samples = 64;
7459
+ const segments = [];
7460
+ for (let i = 0; i <= samples; i++) {
7461
+ const t = i / samples;
7462
+ const angle = ((arc.startAngle + span * t) / 180) * Math.PI;
7463
+ const x = arc.cx + Math.cos(angle) * arc.rx;
7464
+ const y = arc.cy + Math.sin(angle) * arc.ry;
7465
+ segments.push(`${i === 0 ? 'M' : 'L'} ${x.toFixed(2)} ${y.toFixed(2)}`);
7466
+ }
7467
+ return segments.join(' ');
7468
+ }
7469
+ }
7470
+ }
7471
+ ]
7472
+ };
7473
+ };
7474
+ const buildBowlCenterImageMark = (spec) => {
7475
+ var _a, _b, _c, _e;
7476
+ const visible = ((_a = spec.centerImage) === null || _a === void 0 ? void 0 : _a.visible) !== false;
7477
+ if (!visible) {
7478
+ return null;
7479
+ }
7480
+ const themeColor = getThemeColor(spec);
7481
+ const hasImage = !!((_b = spec.centerImage) === null || _b === void 0 ? void 0 : _b.image);
7482
+ const symbolGradient = {
7483
+ gradient: 'linear',
7484
+ x0: 0.5,
7485
+ y0: 0,
7486
+ x1: 0.5,
7487
+ y1: 1,
7488
+ stops: [
7489
+ { offset: 0, color: withAlpha(themeColor, 0.15) },
7490
+ { offset: 1, color: themeColor }
7491
+ ]
7492
+ };
7493
+ return {
7494
+ type: 'group',
7495
+ name: 'storyline-bowl-center',
7496
+ zIndex: vchart.LayoutZIndex.Mark,
7497
+ children: [
7498
+ {
7499
+ type: 'symbol',
7500
+ name: 'storyline-bowl-center-symbol',
7501
+ interactive: false,
7502
+ style: {
7503
+ x: (_d, ctx) => {
7504
+ const r = getBowlCenterImageRect(spec, ctx);
7505
+ return r.x + r.width / 2;
7506
+ },
7507
+ y: (_d, ctx) => {
7508
+ const r = getBowlCenterImageRect(spec, ctx);
7509
+ return r.y + r.height / 2;
7510
+ },
7511
+ size: (_d, ctx) => {
7512
+ const r = getBowlCenterImageRect(spec, ctx);
7513
+ return Math.max(r.width, r.height) * 1.1;
7514
+ },
7515
+ symbolType: 'circle',
7516
+ fill: symbolGradient,
7517
+ stroke: themeColor,
7518
+ lineWidth: 2
7519
+ }
7520
+ },
7521
+ {
7522
+ type: 'rect',
7523
+ name: 'storyline-bowl-center-rect',
7524
+ interactive: false,
7525
+ style: {
7526
+ x: (_d, ctx) => getBowlCenterImageRect(spec, ctx).x,
7527
+ y: (_d, ctx) => getBowlCenterImageRect(spec, ctx).y,
7528
+ width: (_d, ctx) => getBowlCenterImageRect(spec, ctx).width,
7529
+ height: (_d, ctx) => getBowlCenterImageRect(spec, ctx).height,
7530
+ cornerRadius: 12,
7531
+ fill: '#ffffff',
7532
+ stroke: themeColor,
7533
+ lineWidth: 2
7534
+ }
7535
+ },
7536
+ hasImage
7537
+ ? Object.assign(Object.assign({ type: 'image', name: 'storyline-bowl-center-image', interactive: false }, spec.centerImage), { style: Object.assign({ x: (_d, ctx) => getBowlCenterImageRect(spec, ctx).x, y: (_d, ctx) => getBowlCenterImageRect(spec, ctx).y, width: (_d, ctx) => getBowlCenterImageRect(spec, ctx).width, height: (_d, ctx) => getBowlCenterImageRect(spec, ctx).height, image: (_c = spec.centerImage) === null || _c === void 0 ? void 0 : _c.image, cornerRadius: 12, repeatX: 'no-repeat', repeatY: 'no-repeat', imageMode: 'cover', imagePosition: 'center' }, (_e = spec.centerImage) === null || _e === void 0 ? void 0 : _e.style) })
7538
+ : null
7539
+ ].filter(Boolean)
7540
+ };
7541
+ };
7542
+ const getBowlBlockMetrics = (spec) => {
7543
+ var _a, _b, _c, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
7544
+ const titleFontSize = Number((_c = (_b = (_a = spec.title) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.fontSize) !== null && _c !== void 0 ? _c : 14);
7545
+ const titleLineHeight = Number((_g = (_f = (_e = spec.title) === null || _e === void 0 ? void 0 : _e.style) === null || _f === void 0 ? void 0 : _f.lineHeight) !== null && _g !== void 0 ? _g : Math.max(BOWL_TITLE_LINE_HEIGHT, Math.round(titleFontSize * 1.35)));
7546
+ const contentFontSize = Number((_k = (_j = (_h = spec.content) === null || _h === void 0 ? void 0 : _h.style) === null || _j === void 0 ? void 0 : _j.fontSize) !== null && _k !== void 0 ? _k : BOWL_CONTENT_FONT_SIZE);
7547
+ const contentLineHeight = Number((_o = (_m = (_l = spec.content) === null || _l === void 0 ? void 0 : _l.style) === null || _m === void 0 ? void 0 : _m.lineHeight) !== null && _o !== void 0 ? _o : BOWL_CONTENT_LINE_HEIGHT);
7548
+ const titleToContentGap = BOWL_TITLE_TO_CONTENT_GAP;
7549
+ const textHeight = BOWL_TEXT_BOX_HEIGHT;
7550
+ const contentHeight = Math.max(textHeight - titleLineHeight - titleToContentGap, contentLineHeight);
7551
+ const imageWidth = (_q = (_p = spec.image) === null || _p === void 0 ? void 0 : _p.width) !== null && _q !== void 0 ? _q : BOWL_BLOCK_IMAGE_SIZE;
7552
+ const imageHeight = (_s = (_r = spec.image) === null || _r === void 0 ? void 0 : _r.height) !== null && _s !== void 0 ? _s : BOWL_BLOCK_IMAGE_SIZE;
7553
+ const imageBox = {
7554
+ x: -imageWidth / 2,
7555
+ y: -imageHeight / 2,
7556
+ width: imageWidth,
7557
+ height: imageHeight
7558
+ };
7559
+ const textBox = {
7560
+ x: -imageWidth / 2 + BOWL_TEXT_LEFT_PADDING,
7561
+ y: imageBox.y + imageHeight + BOWL_TEXT_GAP_FROM_IMAGE,
7562
+ width: imageWidth - BOWL_TEXT_LEFT_PADDING,
7563
+ height: textHeight
7564
+ };
7565
+ const contentBox = {
7566
+ x: textBox.x,
7567
+ y: textBox.y + titleLineHeight + titleToContentGap,
7568
+ width: textBox.width,
7569
+ height: contentHeight
7570
+ };
7571
+ return {
7572
+ titleFontSize,
7573
+ titleLineHeight,
7574
+ contentFontSize,
7575
+ contentLineHeight,
7576
+ imageBox,
7577
+ textBox,
7578
+ contentBox
7579
+ };
7580
+ };
7581
+ const buildBowlBlockMark = (spec, block, index) => {
7582
+ var _a, _b, _c, _e;
7583
+ const hasImage = !!block.image;
7584
+ const contentText = Array.isArray(block.content) ? block.content : block.content ? [block.content] : [];
7585
+ const themeColor = getThemeColor(spec);
7586
+ const metrics = getBowlBlockMetrics(spec);
7587
+ return {
7588
+ type: 'group',
7589
+ id: `storyline-block-${(_a = block.id) !== null && _a !== void 0 ? _a : index}`,
7590
+ name: `storyline-block-${index}`,
7591
+ zIndex: vchart.LayoutZIndex.Mark + 1,
7592
+ style: {
7593
+ x: (_d, ctx) => getBowlBlockCenter(spec, ctx, index).x,
7594
+ y: (_d, ctx) => getBowlBlockCenter(spec, ctx, index).y
7595
+ },
7596
+ children: [
7597
+ {
7598
+ type: 'rect',
7599
+ name: `storyline-block-connector-${index}`,
7600
+ interactive: false,
7601
+ style: {
7602
+ x: metrics.imageBox.x,
7603
+ y: metrics.imageBox.y + metrics.imageBox.height,
7604
+ width: 2,
7605
+ height: Math.max(metrics.textBox.y + metrics.textBox.height - (metrics.imageBox.y + metrics.imageBox.height), 0),
7606
+ fill: themeColor,
7607
+ fillOpacity: 0.6
7608
+ }
7609
+ },
7610
+ hasImage
7611
+ ? Object.assign(Object.assign({ type: 'image', name: `storyline-block-image-${index}`, interactive: false }, omitImageLayoutSpec(spec.image)), { style: Object.assign({ x: metrics.imageBox.x, y: metrics.imageBox.y, width: metrics.imageBox.width, height: metrics.imageBox.height, image: block.image, cornerRadius: Math.min(metrics.imageBox.width, metrics.imageBox.height) / 2, repeatX: 'no-repeat', repeatY: 'no-repeat', imageMode: 'cover', imagePosition: 'center', stroke: themeColor, lineWidth: 2 }, (_b = spec.image) === null || _b === void 0 ? void 0 : _b.style) })
7612
+ : {
7613
+ type: 'rect',
7614
+ name: `storyline-block-image-bg-${index}`,
7615
+ interactive: false,
7616
+ style: {
7617
+ x: metrics.imageBox.x,
7618
+ y: metrics.imageBox.y,
7619
+ width: metrics.imageBox.width,
7620
+ height: metrics.imageBox.height,
7621
+ cornerRadius: Math.min(metrics.imageBox.width, metrics.imageBox.height) / 2,
7622
+ fill: '#ffffff',
7623
+ stroke: themeColor,
7624
+ lineWidth: 2
7625
+ }
7626
+ },
7627
+ block.title
7628
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-title-${index}`, interactive: false }, spec.title), { style: Object.assign({ x: metrics.textBox.x, y: metrics.textBox.y, text: block.title, maxLineWidth: metrics.textBox.width, fontSize: metrics.titleFontSize, lineHeight: metrics.titleLineHeight, fontWeight: 'bold', fill: '#1f2430', textAlign: 'left', textBaseline: 'top' }, (_c = spec.title) === null || _c === void 0 ? void 0 : _c.style) })
7629
+ : null,
7630
+ contentText.length
7631
+ ? Object.assign(Object.assign({ type: 'text', name: `storyline-block-content-${index}`, interactive: false }, spec.content), { textType: 'rich', style: Object.assign({ x: metrics.contentBox.x, y: metrics.contentBox.y, width: metrics.contentBox.width, height: metrics.contentBox.height, maxLineWidth: metrics.contentBox.width, heightLimit: metrics.contentBox.height, text: buildRichContent(contentText, spec), fontSize: BOWL_CONTENT_FONT_SIZE, lineHeight: BOWL_CONTENT_LINE_HEIGHT, textAlign: 'left', textBaseline: 'top', wordBreak: 'break-word', ellipsis: '...', fill: '#596173' }, (_e = spec.content) === null || _e === void 0 ? void 0 : _e.style) })
7632
+ : null
7633
+ ].filter(Boolean)
7634
+ };
7635
+ };
7636
+
7637
+ class StorylineChartSpecTransformer extends vchart.CommonChartSpecTransformer {
7638
+ transformSpec(spec) {
7639
+ var _a;
7640
+ applyDefaultPadding(spec);
7641
+ const storylineSpec = Object.assign(Object.assign({}, spec), { data: [...((_a = spec.data) !== null && _a !== void 0 ? _a : [])] });
7642
+ spec.type = 'common';
7643
+ spec.data = [];
7644
+ spec.series = [];
7645
+ spec.axes = [];
7646
+ spec.customMark = buildStorylineMarks(storylineSpec);
7647
+ delete spec.layout;
7648
+ delete spec.title;
7649
+ super.transformSpec(spec);
7650
+ }
7651
+ }
7652
+ const applyDefaultPadding = (spec) => {
7653
+ var _a, _b, _c, _d;
7654
+ const DEFAULT_BOTTOM = 100;
7655
+ const DEFAULT_OTHER = 20;
7656
+ const p = spec.padding;
7657
+ if (p === undefined || p === null) {
7658
+ spec.padding = [DEFAULT_OTHER, DEFAULT_OTHER, DEFAULT_BOTTOM, DEFAULT_OTHER];
7659
+ return;
7660
+ }
7661
+ if (typeof p === 'number') {
7662
+ spec.padding = [p, p, Math.max(p, DEFAULT_BOTTOM), p];
7663
+ return;
7664
+ }
7665
+ if (Array.isArray(p)) {
7666
+ const [t = DEFAULT_OTHER, r = DEFAULT_OTHER, b, l = DEFAULT_OTHER] = p;
7667
+ spec.padding = [t, r, b !== null && b !== void 0 ? b : DEFAULT_BOTTOM, l];
7668
+ return;
7669
+ }
7670
+ if (typeof p === 'object') {
7671
+ spec.padding = {
7672
+ top: (_a = p.top) !== null && _a !== void 0 ? _a : DEFAULT_OTHER,
7673
+ right: (_b = p.right) !== null && _b !== void 0 ? _b : DEFAULT_OTHER,
7674
+ bottom: (_c = p.bottom) !== null && _c !== void 0 ? _c : DEFAULT_BOTTOM,
7675
+ left: (_d = p.left) !== null && _d !== void 0 ? _d : DEFAULT_OTHER
7676
+ };
7677
+ }
7678
+ };
7679
+ const buildStorylineMarks = (spec) => {
7680
+ var _a;
7681
+ const lineMark = buildLineMark(spec);
7682
+ const blockMarks = ((_a = spec.data) !== null && _a !== void 0 ? _a : []).map((block, index) => buildBlockMark(spec, block, index));
7683
+ if (isLandscape(spec)) {
7684
+ return [...blockMarks, lineMark].filter(Boolean);
7685
+ }
7686
+ if (isPortrait(spec)) {
7687
+ return [lineMark, ...blockMarks].filter(Boolean);
7688
+ }
7689
+ if (isDome(spec)) {
7690
+ const centerImageMark = buildDomeCenterImageMark(spec);
7691
+ const arcMark = buildDomeArcMark(spec);
7692
+ return [centerImageMark, arcMark, ...blockMarks].filter(Boolean);
7693
+ }
7694
+ if (isBowl(spec)) {
7695
+ const centerImageMark = buildBowlCenterImageMark(spec);
7696
+ const arcMark = buildBowlArcMark(spec);
7697
+ return [centerImageMark, arcMark, ...blockMarks].filter(Boolean);
7698
+ }
7699
+ if (isClock(spec)) {
7700
+ const ringsMark = buildClockArcMark(spec);
7701
+ const centerImageMark = buildClockCenterImageMark(spec);
7702
+ return [ringsMark, ...blockMarks, centerImageMark].filter(Boolean);
7703
+ }
7704
+ return [lineMark, ...blockMarks].filter(Boolean);
7705
+ };
7706
+ const buildLineMark = (spec) => {
7707
+ var _a, _b, _c;
7708
+ if (((_a = spec.line) === null || _a === void 0 ? void 0 : _a.visible) === false || ((_c = (_b = spec.data) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) <= 1) {
7709
+ return null;
7710
+ }
7711
+ if (isLandscape(spec)) {
7712
+ return buildLandscapeConnectingCurve(spec);
7713
+ }
7714
+ if (isPortrait(spec)) {
7715
+ return buildPortraitAxisMark(spec);
7716
+ }
7717
+ return buildDefaultLineMark(spec);
7718
+ };
7719
+ const buildBlockMark = (spec, block, index) => {
7720
+ if (isLandscape(spec)) {
7721
+ return buildLandscapeBlockMark(spec, block, index);
7722
+ }
7723
+ if (isPortrait(spec)) {
7724
+ return buildPortraitBlockMark(spec, block, index);
7725
+ }
7726
+ if (isDome(spec)) {
7727
+ return buildDomeBlockMark(spec, block, index);
7728
+ }
7729
+ if (isBowl(spec)) {
7730
+ return buildBowlBlockMark(spec, block, index);
7731
+ }
7732
+ if (isClock(spec)) {
7733
+ return buildClockBlockMark(spec, block, index);
7734
+ }
7735
+ return buildDefaultBlockMark(spec, block, index);
7736
+ };
7737
+
7738
+ class StorylineChart extends vchart.BaseChart {
7739
+ constructor() {
7740
+ super(...arguments);
7741
+ this.type = 'storyline';
7742
+ this.transformerConstructor = StorylineChartSpecTransformer;
7743
+ }
7744
+ init() {
7745
+ if (!this.isValid()) {
7746
+ return;
7747
+ }
7748
+ super.init();
7749
+ }
7750
+ isValid() {
7751
+ var _a, _b;
7752
+ const { data } = this._spec;
7753
+ if (!Array.isArray(data)) {
7754
+ (_b = (_a = this._option).onError) === null || _b === void 0 ? void 0 : _b.call(_a, 'Data is required and should be an array for storyline chart');
7755
+ return false;
7756
+ }
7757
+ return true;
7758
+ }
7759
+ }
7760
+ StorylineChart.type = 'storyline';
7761
+ StorylineChart.view = 'singleDefault';
7762
+ StorylineChart.transformerConstructor = StorylineChartSpecTransformer;
7763
+ const registerStorylineChart = (option) => {
7764
+ vchart.registerCommonChart();
7765
+ vchart.registerCustomMark();
7766
+ vchart.registerGroupMark();
7767
+ vchart.registerRectMark();
7768
+ vchart.registerTextMark();
7769
+ vchart.registerImageMark();
7770
+ vchart.registerLineMark();
7771
+ vchart.registerPathMark();
7772
+ vchart.registerArcMark();
7773
+ const vchartConstructor = (option === null || option === void 0 ? void 0 : option.VChart) || vchart.VChart;
7774
+ if (vchartConstructor) {
7775
+ vchartConstructor.useChart([StorylineChart]);
7776
+ }
7777
+ };
7778
+
5825
7779
  const SERIES_BREAK = 'seriesBreak';
5826
7780
 
5827
7781
  function generateZigzagPath(start, end, size, angle, isVertical = false) {
@@ -7961,6 +9915,8 @@
7961
9915
  exports.SequenceScatterPixel = SequenceScatterPixel;
7962
9916
  exports.SeriesBreakComponent = SeriesBreakComponent;
7963
9917
  exports.SeriesLabelComponent = SeriesLabelComponent;
9918
+ exports.StorylineChart = StorylineChart;
9919
+ exports.StorylineChartSpecTransformer = StorylineChartSpecTransformer;
7964
9920
  exports.TimelineChart = TimelineChart;
7965
9921
  exports.WordCloud3dChart = WordCloud3dChart;
7966
9922
  exports.WordCloud3dChartSpecTransformer = WordCloud3dChartSpecTransformer;
@@ -7972,6 +9928,7 @@
7972
9928
  exports.appendSeriesBreakConfig = appendSeriesBreakConfig;
7973
9929
  exports.appendSeriesLabelConfig = appendSeriesLabelConfig;
7974
9930
  exports.clearSVGSource = clearSVGSource;
9931
+ exports.computeStorylineLayout = computeStorylineLayout;
7975
9932
  exports.getBarLinkConfig = getBarLinkConfig;
7976
9933
  exports.getBarRegressionLineConfig = getBarRegressionLineConfig;
7977
9934
  exports.getHistogramRegressionLineConfig = getHistogramRegressionLineConfig;
@@ -7979,6 +9936,8 @@
7979
9936
  exports.getScatterRegressionLineConfig = getScatterRegressionLineConfig;
7980
9937
  exports.getSeriesBreakConfig = getSeriesBreakConfig;
7981
9938
  exports.getSeriesLabelConfig = getSeriesLabelConfig;
9939
+ exports.normalizeLayout = normalizeLayout;
9940
+ exports.normalizePadding = normalizePadding;
7982
9941
  exports.register3DPlugin = register3DPlugin;
7983
9942
  exports.registerAxis3dPlugin = registerAxis3dPlugin;
7984
9943
  exports.registerBar3dChart = registerBar3dChart;
@@ -8010,6 +9969,7 @@
8010
9969
  exports.registerSequenceScatterPixel = registerSequenceScatterPixel;
8011
9970
  exports.registerSeriesBreak = registerSeriesBreak;
8012
9971
  exports.registerSeriesLabel = registerSeriesLabel;
9972
+ exports.registerStorylineChart = registerStorylineChart;
8013
9973
  exports.registerTimelineChart = registerTimelineChart;
8014
9974
  exports.registerWordCloud3dChart = registerWordCloud3dChart;
8015
9975
  exports.registerWordCloud3dSeries = registerWordCloud3dSeries;