@hirokisakabe/pom 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +3 -2
  2. package/dist/calcYogaLayout/calcYogaLayout.d.ts.map +1 -1
  3. package/dist/calcYogaLayout/calcYogaLayout.js +49 -84
  4. package/dist/calcYogaLayout/fontLoader.d.ts +20 -0
  5. package/dist/calcYogaLayout/fontLoader.d.ts.map +1 -0
  6. package/dist/calcYogaLayout/fontLoader.js +59 -0
  7. package/dist/calcYogaLayout/fonts/notoSansJPBold.d.ts +7 -0
  8. package/dist/calcYogaLayout/fonts/notoSansJPBold.d.ts.map +1 -0
  9. package/dist/calcYogaLayout/fonts/notoSansJPBold.js +6 -0
  10. package/dist/calcYogaLayout/fonts/notoSansJPRegular.d.ts +7 -0
  11. package/dist/calcYogaLayout/fonts/notoSansJPRegular.d.ts.map +1 -0
  12. package/dist/calcYogaLayout/fonts/notoSansJPRegular.js +6 -0
  13. package/dist/calcYogaLayout/measureText.d.ts +1 -1
  14. package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
  15. package/dist/calcYogaLayout/measureText.js +65 -114
  16. package/dist/renderPptx/nodes/box.d.ts +1 -0
  17. package/dist/renderPptx/nodes/box.d.ts.map +1 -0
  18. package/dist/renderPptx/nodes/box.js +2 -0
  19. package/dist/renderPptx/nodes/chart.d.ts +8 -0
  20. package/dist/renderPptx/nodes/chart.d.ts.map +1 -0
  21. package/dist/renderPptx/nodes/chart.js +23 -0
  22. package/dist/renderPptx/nodes/flow.d.ts +8 -0
  23. package/dist/renderPptx/nodes/flow.d.ts.map +1 -0
  24. package/dist/renderPptx/nodes/flow.js +208 -0
  25. package/dist/renderPptx/nodes/image.d.ts +8 -0
  26. package/dist/renderPptx/nodes/image.d.ts.map +1 -0
  27. package/dist/renderPptx/nodes/image.js +17 -0
  28. package/dist/renderPptx/nodes/index.d.ts +11 -0
  29. package/dist/renderPptx/nodes/index.d.ts.map +1 -0
  30. package/dist/renderPptx/nodes/index.js +10 -0
  31. package/dist/renderPptx/nodes/matrix.d.ts +8 -0
  32. package/dist/renderPptx/nodes/matrix.d.ts.map +1 -0
  33. package/dist/renderPptx/nodes/matrix.js +150 -0
  34. package/dist/renderPptx/nodes/processArrow.d.ts +8 -0
  35. package/dist/renderPptx/nodes/processArrow.d.ts.map +1 -0
  36. package/dist/renderPptx/nodes/processArrow.js +75 -0
  37. package/dist/renderPptx/nodes/shape.d.ts +8 -0
  38. package/dist/renderPptx/nodes/shape.d.ts.map +1 -0
  39. package/dist/renderPptx/nodes/shape.js +49 -0
  40. package/dist/renderPptx/nodes/table.d.ts +8 -0
  41. package/dist/renderPptx/nodes/table.d.ts.map +1 -0
  42. package/dist/renderPptx/nodes/table.js +29 -0
  43. package/dist/renderPptx/nodes/text.d.ts +8 -0
  44. package/dist/renderPptx/nodes/text.d.ts.map +1 -0
  45. package/dist/renderPptx/nodes/text.js +5 -0
  46. package/dist/renderPptx/nodes/timeline.d.ts +8 -0
  47. package/dist/renderPptx/nodes/timeline.d.ts.map +1 -0
  48. package/dist/renderPptx/nodes/timeline.js +157 -0
  49. package/dist/renderPptx/nodes/tree.d.ts +8 -0
  50. package/dist/renderPptx/nodes/tree.d.ts.map +1 -0
  51. package/dist/renderPptx/nodes/tree.js +223 -0
  52. package/dist/renderPptx/renderPptx.d.ts.map +1 -1
  53. package/dist/renderPptx/renderPptx.js +27 -945
  54. package/dist/renderPptx/types.d.ts +10 -0
  55. package/dist/renderPptx/types.d.ts.map +1 -0
  56. package/dist/renderPptx/types.js +1 -0
  57. package/dist/renderPptx/utils/backgroundBorder.d.ts +8 -0
  58. package/dist/renderPptx/utils/backgroundBorder.d.ts.map +1 -0
  59. package/dist/renderPptx/utils/backgroundBorder.js +44 -0
  60. package/dist/renderPptx/utils/index.d.ts +6 -0
  61. package/dist/renderPptx/utils/index.d.ts.map +1 -0
  62. package/dist/renderPptx/utils/index.js +3 -0
  63. package/dist/renderPptx/utils/shapeDrawing.d.ts +27 -0
  64. package/dist/renderPptx/utils/shapeDrawing.d.ts.map +1 -0
  65. package/dist/renderPptx/utils/shapeDrawing.js +36 -0
  66. package/dist/renderPptx/utils/textDrawing.d.ts +20 -0
  67. package/dist/renderPptx/utils/textDrawing.d.ts.map +1 -0
  68. package/dist/renderPptx/utils/textDrawing.js +20 -0
  69. package/package.json +3 -2
@@ -0,0 +1,150 @@
1
+ import { pxToIn, pxToPt } from "../units";
2
+ export function renderMatrixNode(node, ctx) {
3
+ const items = node.items;
4
+ const axes = node.axes;
5
+ const quadrants = node.quadrants;
6
+ const defaultItemColor = "1D4ED8"; // blue
7
+ const itemSize = 24; // px
8
+ const lineWidth = 2; // px
9
+ const axisColor = "E2E8F0";
10
+ // マトリクスの描画領域(パディングを考慮)
11
+ const padding = 60; // 軸ラベル用の余白
12
+ const areaX = node.x + padding;
13
+ const areaY = node.y + padding;
14
+ const areaW = node.w - padding * 2;
15
+ const areaH = node.h - padding * 2;
16
+ // 中心座標
17
+ const centerX = areaX + areaW / 2;
18
+ const centerY = areaY + areaH / 2;
19
+ // === 1. 十字線(軸線)を描画 ===
20
+ // 横線(X軸)
21
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
22
+ x: pxToIn(areaX),
23
+ y: pxToIn(centerY),
24
+ w: pxToIn(areaW),
25
+ h: 0,
26
+ line: { color: axisColor, width: pxToPt(lineWidth) },
27
+ });
28
+ // 縦線(Y軸)
29
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
30
+ x: pxToIn(centerX),
31
+ y: pxToIn(areaY),
32
+ w: 0,
33
+ h: pxToIn(areaH),
34
+ line: { color: axisColor, width: pxToPt(lineWidth) },
35
+ });
36
+ // === 2. 軸ラベルを描画 ===
37
+ // X軸ラベル(下部中央)
38
+ ctx.slide.addText(axes.x, {
39
+ x: pxToIn(centerX - 60),
40
+ y: pxToIn(areaY + areaH + 8),
41
+ w: pxToIn(120),
42
+ h: pxToIn(24),
43
+ fontSize: pxToPt(12),
44
+ fontFace: "Noto Sans JP",
45
+ color: "64748B",
46
+ align: "center",
47
+ valign: "top",
48
+ });
49
+ // Y軸ラベル(左部中央)
50
+ ctx.slide.addText(axes.y, {
51
+ x: pxToIn(node.x + 4),
52
+ y: pxToIn(centerY - 12),
53
+ w: pxToIn(48),
54
+ h: pxToIn(24),
55
+ fontSize: pxToPt(12),
56
+ fontFace: "Noto Sans JP",
57
+ color: "64748B",
58
+ align: "center",
59
+ valign: "middle",
60
+ });
61
+ // === 3. 象限ラベルを描画 ===
62
+ if (quadrants) {
63
+ renderQuadrantLabels(ctx, quadrants, areaX, areaY, areaW, areaH, centerX, centerY);
64
+ }
65
+ // === 4. アイテムをプロット ===
66
+ for (const item of items) {
67
+ // 座標変換: (0,0)=左下, (1,1)=右上
68
+ // x: 0 -> areaX, 1 -> areaX + areaW
69
+ // y: 0 -> areaY + areaH, 1 -> areaY (反転)
70
+ const itemX = areaX + item.x * areaW;
71
+ const itemY = areaY + (1 - item.y) * areaH; // Y軸反転
72
+ const itemColor = item.color ?? defaultItemColor;
73
+ // 円を描画
74
+ ctx.slide.addShape(ctx.pptx.ShapeType.ellipse, {
75
+ x: pxToIn(itemX - itemSize / 2),
76
+ y: pxToIn(itemY - itemSize / 2),
77
+ w: pxToIn(itemSize),
78
+ h: pxToIn(itemSize),
79
+ fill: { color: itemColor },
80
+ line: { type: "none" },
81
+ });
82
+ // ラベルを描画(円の上)
83
+ ctx.slide.addText(item.label, {
84
+ x: pxToIn(itemX - 50),
85
+ y: pxToIn(itemY - itemSize / 2 - 20),
86
+ w: pxToIn(100),
87
+ h: pxToIn(18),
88
+ fontSize: pxToPt(11),
89
+ fontFace: "Noto Sans JP",
90
+ color: "1E293B",
91
+ bold: true,
92
+ align: "center",
93
+ valign: "bottom",
94
+ });
95
+ }
96
+ }
97
+ function renderQuadrantLabels(ctx, quadrants, areaX, areaY, areaW, areaH, centerX, centerY) {
98
+ const quadrantFontSize = 11;
99
+ const quadrantColor = "94A3B8"; // slate-400
100
+ const quadrantW = areaW / 2 - 20;
101
+ const quadrantH = 48;
102
+ // 左上
103
+ ctx.slide.addText(quadrants.topLeft, {
104
+ x: pxToIn(areaX + 10),
105
+ y: pxToIn(areaY + 10),
106
+ w: pxToIn(quadrantW),
107
+ h: pxToIn(quadrantH),
108
+ fontSize: pxToPt(quadrantFontSize),
109
+ fontFace: "Noto Sans JP",
110
+ color: quadrantColor,
111
+ align: "left",
112
+ valign: "top",
113
+ });
114
+ // 右上
115
+ ctx.slide.addText(quadrants.topRight, {
116
+ x: pxToIn(centerX + 10),
117
+ y: pxToIn(areaY + 10),
118
+ w: pxToIn(quadrantW),
119
+ h: pxToIn(quadrantH),
120
+ fontSize: pxToPt(quadrantFontSize),
121
+ fontFace: "Noto Sans JP",
122
+ color: quadrantColor,
123
+ align: "right",
124
+ valign: "top",
125
+ });
126
+ // 左下
127
+ ctx.slide.addText(quadrants.bottomLeft, {
128
+ x: pxToIn(areaX + 10),
129
+ y: pxToIn(centerY + areaH / 2 - quadrantH - 10),
130
+ w: pxToIn(quadrantW),
131
+ h: pxToIn(quadrantH),
132
+ fontSize: pxToPt(quadrantFontSize),
133
+ fontFace: "Noto Sans JP",
134
+ color: quadrantColor,
135
+ align: "left",
136
+ valign: "bottom",
137
+ });
138
+ // 右下
139
+ ctx.slide.addText(quadrants.bottomRight, {
140
+ x: pxToIn(centerX + 10),
141
+ y: pxToIn(centerY + areaH / 2 - quadrantH - 10),
142
+ w: pxToIn(quadrantW),
143
+ h: pxToIn(quadrantH),
144
+ fontSize: pxToPt(quadrantFontSize),
145
+ fontFace: "Noto Sans JP",
146
+ color: quadrantColor,
147
+ align: "right",
148
+ valign: "bottom",
149
+ });
150
+ }
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type ProcessArrowPositionedNode = Extract<PositionedNode, {
4
+ type: "processArrow";
5
+ }>;
6
+ export declare function renderProcessArrowNode(node: ProcessArrowPositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=processArrow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processArrow.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/processArrow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,KAAK,0BAA0B,GAAG,OAAO,CACvC,cAAc,EACd;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,CACzB,CAAC;AAEF,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,0BAA0B,EAChC,GAAG,EAAE,aAAa,GACjB,IAAI,CAsCN"}
@@ -0,0 +1,75 @@
1
+ import { pxToIn, pxToPt } from "../units";
2
+ export function renderProcessArrowNode(node, ctx) {
3
+ const direction = node.direction ?? "horizontal";
4
+ const steps = node.steps;
5
+ const stepCount = steps.length;
6
+ if (stepCount === 0)
7
+ return;
8
+ const defaultColor = "4472C4"; // PowerPoint標準の青
9
+ const defaultTextColor = "FFFFFF";
10
+ const itemWidth = node.itemWidth ?? 150;
11
+ const itemHeight = node.itemHeight ?? 60;
12
+ const gap = node.gap ?? -15; // 負の値でシェブロンを重ねる
13
+ if (direction === "horizontal") {
14
+ renderHorizontalProcessArrow(node, ctx, steps, stepCount, itemWidth, itemHeight, gap, defaultColor, defaultTextColor);
15
+ }
16
+ else {
17
+ renderVerticalProcessArrow(node, ctx, steps, stepCount, itemWidth, itemHeight, gap, defaultColor, defaultTextColor);
18
+ }
19
+ }
20
+ function renderHorizontalProcessArrow(node, ctx, steps, stepCount, itemWidth, itemHeight, gap, defaultColor, defaultTextColor) {
21
+ const totalWidth = stepCount * itemWidth + (stepCount - 1) * gap;
22
+ const startX = node.x + (node.w - totalWidth) / 2;
23
+ const centerY = node.y + node.h / 2;
24
+ steps.forEach((step, index) => {
25
+ const stepX = startX + index * (itemWidth + gap);
26
+ const stepY = centerY - itemHeight / 2;
27
+ const fillColor = step.color?.replace("#", "") ?? defaultColor;
28
+ const textColor = step.textColor?.replace("#", "") ?? defaultTextColor;
29
+ // 最初のステップは homePlate、以降は chevron
30
+ const shapeType = index === 0 ? ctx.pptx.ShapeType.homePlate : ctx.pptx.ShapeType.chevron;
31
+ ctx.slide.addText(step.label, {
32
+ x: pxToIn(stepX),
33
+ y: pxToIn(stepY),
34
+ w: pxToIn(itemWidth),
35
+ h: pxToIn(itemHeight),
36
+ shape: shapeType,
37
+ fill: { color: fillColor },
38
+ line: { type: "none" },
39
+ fontSize: pxToPt(node.fontPx ?? 14),
40
+ fontFace: "Noto Sans JP",
41
+ color: textColor,
42
+ bold: node.bold ?? false,
43
+ align: "center",
44
+ valign: "middle",
45
+ });
46
+ });
47
+ }
48
+ function renderVerticalProcessArrow(node, ctx, steps, stepCount, itemWidth, itemHeight, gap, defaultColor, defaultTextColor) {
49
+ const totalHeight = stepCount * itemHeight + (stepCount - 1) * gap;
50
+ const startY = node.y + (node.h - totalHeight) / 2;
51
+ const centerX = node.x + node.w / 2;
52
+ steps.forEach((step, index) => {
53
+ const stepX = centerX - itemWidth / 2;
54
+ const stepY = startY + index * (itemHeight + gap);
55
+ const fillColor = step.color?.replace("#", "") ?? defaultColor;
56
+ const textColor = step.textColor?.replace("#", "") ?? defaultTextColor;
57
+ // 垂直方向では pentagon を使用(下向き矢印風)
58
+ const shapeType = index === 0 ? ctx.pptx.ShapeType.rect : ctx.pptx.ShapeType.pentagon;
59
+ ctx.slide.addText(step.label, {
60
+ x: pxToIn(stepX),
61
+ y: pxToIn(stepY),
62
+ w: pxToIn(itemWidth),
63
+ h: pxToIn(itemHeight),
64
+ shape: shapeType,
65
+ fill: { color: fillColor },
66
+ line: { type: "none" },
67
+ fontSize: pxToPt(node.fontPx ?? 14),
68
+ fontFace: "Noto Sans JP",
69
+ color: textColor,
70
+ bold: node.bold ?? false,
71
+ align: "center",
72
+ valign: "middle",
73
+ });
74
+ });
75
+ }
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type ShapePositionedNode = Extract<PositionedNode, {
4
+ type: "shape";
5
+ }>;
6
+ export declare function renderShapeNode(node: ShapePositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=shape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/shape.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,KAAK,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAEtE,wBAAgB,eAAe,CAC7B,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,aAAa,GACjB,IAAI,CAgDN"}
@@ -0,0 +1,49 @@
1
+ import { pxToIn, pxToPt } from "../units";
2
+ export function renderShapeNode(node, ctx) {
3
+ const shapeOptions = {
4
+ x: pxToIn(node.x),
5
+ y: pxToIn(node.y),
6
+ w: pxToIn(node.w),
7
+ h: pxToIn(node.h),
8
+ fill: node.fill
9
+ ? {
10
+ color: node.fill.color,
11
+ transparency: node.fill.transparency,
12
+ }
13
+ : undefined,
14
+ line: node.line
15
+ ? {
16
+ color: node.line.color,
17
+ width: node.line.width !== undefined ? pxToPt(node.line.width) : undefined,
18
+ dashType: node.line.dashType,
19
+ }
20
+ : undefined,
21
+ shadow: node.shadow
22
+ ? {
23
+ type: node.shadow.type,
24
+ opacity: node.shadow.opacity,
25
+ blur: node.shadow.blur,
26
+ angle: node.shadow.angle,
27
+ offset: node.shadow.offset,
28
+ color: node.shadow.color,
29
+ }
30
+ : undefined,
31
+ };
32
+ if (node.text) {
33
+ // テキストがある場合:addTextでshapeを指定
34
+ ctx.slide.addText(node.text, {
35
+ ...shapeOptions,
36
+ shape: node.shapeType,
37
+ fontSize: pxToPt(node.fontPx ?? 24),
38
+ fontFace: "Noto Sans JP",
39
+ color: node.color,
40
+ align: node.alignText ?? "center",
41
+ valign: "middle",
42
+ lineSpacingMultiple: 1.3,
43
+ });
44
+ }
45
+ else {
46
+ // テキストがない場合:addShapeを使用
47
+ ctx.slide.addShape(node.shapeType, shapeOptions);
48
+ }
49
+ }
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type TablePositionedNode = Extract<PositionedNode, {
4
+ type: "table";
5
+ }>;
6
+ export declare function renderTableNode(node: TablePositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/table.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAI9C,KAAK,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAEtE,wBAAgB,eAAe,CAC7B,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,aAAa,GACjB,IAAI,CA+BN"}
@@ -0,0 +1,29 @@
1
+ import { resolveColumnWidths, resolveRowHeights } from "../../table/utils";
2
+ import { pxToIn, pxToPt } from "../units";
3
+ export function renderTableNode(node, ctx) {
4
+ const tableRows = node.rows.map((row) => row.cells.map((cell) => {
5
+ const cellOptions = {
6
+ fontSize: pxToPt(cell.fontPx ?? 18),
7
+ color: cell.color,
8
+ bold: cell.bold,
9
+ align: cell.alignText ?? "left",
10
+ fill: cell.backgroundColor
11
+ ? { color: cell.backgroundColor }
12
+ : undefined,
13
+ };
14
+ return {
15
+ text: cell.text,
16
+ options: cellOptions,
17
+ };
18
+ }));
19
+ const tableOptions = {
20
+ x: pxToIn(node.x),
21
+ y: pxToIn(node.y),
22
+ w: pxToIn(node.w),
23
+ h: pxToIn(node.h),
24
+ colW: resolveColumnWidths(node, node.w).map((width) => pxToIn(width)),
25
+ rowH: resolveRowHeights(node).map((height) => pxToIn(height)),
26
+ margin: 0,
27
+ };
28
+ ctx.slide.addTable(tableRows, tableOptions);
29
+ }
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type TextPositionedNode = Extract<PositionedNode, {
4
+ type: "text";
5
+ }>;
6
+ export declare function renderTextNode(node: TextPositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,KAAK,kBAAkB,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEpE,wBAAgB,cAAc,CAC5B,IAAI,EAAE,kBAAkB,EACxB,GAAG,EAAE,aAAa,GACjB,IAAI,CAGN"}
@@ -0,0 +1,5 @@
1
+ import { createTextOptions } from "../textOptions";
2
+ export function renderTextNode(node, ctx) {
3
+ const textOptions = createTextOptions(node);
4
+ ctx.slide.addText(node.text ?? "", textOptions);
5
+ }
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type TimelinePositionedNode = Extract<PositionedNode, {
4
+ type: "timeline";
5
+ }>;
6
+ export declare function renderTimelineNode(node: TimelinePositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=timeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/timeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,KAAK,sBAAsB,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAAC;AAE5E,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,sBAAsB,EAC5B,GAAG,EAAE,aAAa,GACjB,IAAI,CA8BN"}
@@ -0,0 +1,157 @@
1
+ import { pxToIn, pxToPt } from "../units";
2
+ export function renderTimelineNode(node, ctx) {
3
+ const direction = node.direction ?? "horizontal";
4
+ const items = node.items;
5
+ const itemCount = items.length;
6
+ if (itemCount === 0)
7
+ return;
8
+ const defaultColor = "1D4ED8"; // blue
9
+ const nodeRadius = 12; // px
10
+ const lineWidth = 4; // px
11
+ if (direction === "horizontal") {
12
+ renderHorizontalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth);
13
+ }
14
+ else {
15
+ renderVerticalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth);
16
+ }
17
+ }
18
+ function renderHorizontalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth) {
19
+ const itemCount = items.length;
20
+ const lineY = node.y + node.h / 2;
21
+ const startX = node.x + nodeRadius;
22
+ const endX = node.x + node.w - nodeRadius;
23
+ const lineLength = endX - startX;
24
+ // メインの線を描画
25
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
26
+ x: pxToIn(startX),
27
+ y: pxToIn(lineY),
28
+ w: pxToIn(lineLength),
29
+ h: 0,
30
+ line: { color: "E2E8F0", width: pxToPt(lineWidth) },
31
+ });
32
+ // 各アイテムを描画
33
+ items.forEach((item, index) => {
34
+ const progress = itemCount === 1 ? 0.5 : index / (itemCount - 1);
35
+ const cx = startX + lineLength * progress;
36
+ const cy = lineY;
37
+ const color = item.color ?? defaultColor;
38
+ // ノード(円)を描画
39
+ ctx.slide.addShape(ctx.pptx.ShapeType.ellipse, {
40
+ x: pxToIn(cx - nodeRadius),
41
+ y: pxToIn(cy - nodeRadius),
42
+ w: pxToIn(nodeRadius * 2),
43
+ h: pxToIn(nodeRadius * 2),
44
+ fill: { color },
45
+ line: { type: "none" },
46
+ });
47
+ // 日付を上に表示
48
+ ctx.slide.addText(item.date, {
49
+ x: pxToIn(cx - 60),
50
+ y: pxToIn(cy - nodeRadius - 40),
51
+ w: pxToIn(120),
52
+ h: pxToIn(24),
53
+ fontSize: pxToPt(12),
54
+ fontFace: "Noto Sans JP",
55
+ color: "64748B",
56
+ align: "center",
57
+ valign: "bottom",
58
+ });
59
+ // タイトルを下に表示
60
+ ctx.slide.addText(item.title, {
61
+ x: pxToIn(cx - 60),
62
+ y: pxToIn(cy + nodeRadius + 8),
63
+ w: pxToIn(120),
64
+ h: pxToIn(24),
65
+ fontSize: pxToPt(14),
66
+ fontFace: "Noto Sans JP",
67
+ color: "1E293B",
68
+ bold: true,
69
+ align: "center",
70
+ valign: "top",
71
+ });
72
+ // 説明を表示
73
+ if (item.description) {
74
+ ctx.slide.addText(item.description, {
75
+ x: pxToIn(cx - 60),
76
+ y: pxToIn(cy + nodeRadius + 32),
77
+ w: pxToIn(120),
78
+ h: pxToIn(32),
79
+ fontSize: pxToPt(11),
80
+ fontFace: "Noto Sans JP",
81
+ color: "64748B",
82
+ align: "center",
83
+ valign: "top",
84
+ });
85
+ }
86
+ });
87
+ }
88
+ function renderVerticalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth) {
89
+ const itemCount = items.length;
90
+ const lineX = node.x + 40;
91
+ const startY = node.y + nodeRadius;
92
+ const endY = node.y + node.h - nodeRadius;
93
+ const lineLength = endY - startY;
94
+ // メインの線を描画
95
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
96
+ x: pxToIn(lineX),
97
+ y: pxToIn(startY),
98
+ w: 0,
99
+ h: pxToIn(lineLength),
100
+ line: { color: "E2E8F0", width: pxToPt(lineWidth) },
101
+ });
102
+ // 各アイテムを描画
103
+ items.forEach((item, index) => {
104
+ const progress = itemCount === 1 ? 0.5 : index / (itemCount - 1);
105
+ const cx = lineX;
106
+ const cy = startY + lineLength * progress;
107
+ const color = item.color ?? defaultColor;
108
+ // ノード(円)を描画
109
+ ctx.slide.addShape(ctx.pptx.ShapeType.ellipse, {
110
+ x: pxToIn(cx - nodeRadius),
111
+ y: pxToIn(cy - nodeRadius),
112
+ w: pxToIn(nodeRadius * 2),
113
+ h: pxToIn(nodeRadius * 2),
114
+ fill: { color },
115
+ line: { type: "none" },
116
+ });
117
+ // 日付を左上に表示
118
+ ctx.slide.addText(item.date, {
119
+ x: pxToIn(cx + nodeRadius + 16),
120
+ y: pxToIn(cy - nodeRadius - 4),
121
+ w: pxToIn(100),
122
+ h: pxToIn(20),
123
+ fontSize: pxToPt(12),
124
+ fontFace: "Noto Sans JP",
125
+ color: "64748B",
126
+ align: "left",
127
+ valign: "bottom",
128
+ });
129
+ // タイトルを右に表示
130
+ ctx.slide.addText(item.title, {
131
+ x: pxToIn(cx + nodeRadius + 16),
132
+ y: pxToIn(cy - 4),
133
+ w: pxToIn(node.w - 80),
134
+ h: pxToIn(24),
135
+ fontSize: pxToPt(14),
136
+ fontFace: "Noto Sans JP",
137
+ color: "1E293B",
138
+ bold: true,
139
+ align: "left",
140
+ valign: "top",
141
+ });
142
+ // 説明を表示
143
+ if (item.description) {
144
+ ctx.slide.addText(item.description, {
145
+ x: pxToIn(cx + nodeRadius + 16),
146
+ y: pxToIn(cy + 20),
147
+ w: pxToIn(node.w - 80),
148
+ h: pxToIn(32),
149
+ fontSize: pxToPt(11),
150
+ fontFace: "Noto Sans JP",
151
+ color: "64748B",
152
+ align: "left",
153
+ valign: "top",
154
+ });
155
+ }
156
+ });
157
+ }
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type TreePositionedNode = Extract<PositionedNode, {
4
+ type: "tree";
5
+ }>;
6
+ export declare function renderTreeNode(node: TreePositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAIf,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,KAAK,kBAAkB,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAWpE,wBAAgB,cAAc,CAC5B,IAAI,EAAE,kBAAkB,EACxB,GAAG,EAAE,aAAa,GACjB,IAAI,CAwQN"}