@hirokisakabe/pom 0.3.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,30 +1,211 @@
1
1
  import { createRequire } from "module";
2
2
  const require = createRequire(import.meta.url);
3
3
  const PptxGenJS = require("pptxgenjs");
4
- import { pxToIn } from "./units";
4
+ import { pxToIn, pxToPt } from "./units";
5
5
  import { renderBackgroundAndBorder } from "./utils/backgroundBorder";
6
- import { renderTextNode, renderImageNode, renderTableNode, renderShapeNode, renderChartNode, renderTimelineNode, renderMatrixNode, renderTreeNode, renderFlowNode, renderProcessArrowNode, } from "./nodes";
6
+ import { renderTextNode, renderImageNode, renderTableNode, renderShapeNode, renderChartNode, renderTimelineNode, renderMatrixNode, renderTreeNode, renderFlowNode, renderProcessArrowNode, renderLineNode, } from "./nodes";
7
7
  export { createTextOptions } from "./textOptions";
8
8
  export { PX_PER_IN, pxToIn, pxToPt } from "./units";
9
+ const DEFAULT_MASTER_NAME = "POM_MASTER";
10
+ /**
11
+ * MasterObject を pptxgenjs の objects 形式に変換する
12
+ */
13
+ function convertMasterObject(obj) {
14
+ switch (obj.type) {
15
+ case "text":
16
+ return {
17
+ text: {
18
+ text: obj.text,
19
+ options: {
20
+ x: pxToIn(obj.x),
21
+ y: pxToIn(obj.y),
22
+ w: pxToIn(obj.w),
23
+ h: pxToIn(obj.h),
24
+ fontSize: obj.fontPx ? pxToPt(obj.fontPx) : undefined,
25
+ fontFace: obj.fontFamily,
26
+ color: obj.color,
27
+ bold: obj.bold,
28
+ align: obj.alignText,
29
+ },
30
+ },
31
+ };
32
+ case "image": {
33
+ const imageProps = {
34
+ x: pxToIn(obj.x),
35
+ y: pxToIn(obj.y),
36
+ w: pxToIn(obj.w),
37
+ h: pxToIn(obj.h),
38
+ };
39
+ // src が data URI かパスかを判定
40
+ if (obj.src.startsWith("data:")) {
41
+ imageProps.data = obj.src;
42
+ }
43
+ else {
44
+ imageProps.path = obj.src;
45
+ }
46
+ return { image: imageProps };
47
+ }
48
+ case "rect":
49
+ return {
50
+ rect: {
51
+ x: pxToIn(obj.x),
52
+ y: pxToIn(obj.y),
53
+ w: pxToIn(obj.w),
54
+ h: pxToIn(obj.h),
55
+ fill: obj.fill
56
+ ? { color: obj.fill.color, transparency: obj.fill.transparency }
57
+ : undefined,
58
+ line: obj.border
59
+ ? {
60
+ color: obj.border.color,
61
+ width: obj.border.width,
62
+ dashType: obj.border.dashType,
63
+ }
64
+ : undefined,
65
+ },
66
+ };
67
+ case "line":
68
+ return {
69
+ line: {
70
+ x: pxToIn(obj.x),
71
+ y: pxToIn(obj.y),
72
+ w: pxToIn(obj.w),
73
+ h: pxToIn(obj.h),
74
+ line: obj.line
75
+ ? {
76
+ color: obj.line.color,
77
+ width: obj.line.width,
78
+ dashType: obj.line.dashType,
79
+ }
80
+ : { color: "000000", width: 1 },
81
+ },
82
+ };
83
+ }
84
+ }
85
+ /**
86
+ * SlideMasterOptions から pptxgenjs の defineSlideMaster を呼び出す
87
+ */
88
+ function defineSlideMasterFromOptions(pptx, master) {
89
+ const masterName = master.title || DEFAULT_MASTER_NAME;
90
+ const masterProps = {
91
+ title: masterName,
92
+ };
93
+ // background の変換
94
+ if (master.background) {
95
+ if ("color" in master.background) {
96
+ masterProps.background = { color: master.background.color };
97
+ }
98
+ else if ("path" in master.background) {
99
+ masterProps.background = { path: master.background.path };
100
+ }
101
+ else if ("data" in master.background) {
102
+ masterProps.background = { data: master.background.data };
103
+ }
104
+ }
105
+ // margin の変換 (px -> inches)
106
+ if (master.margin !== undefined) {
107
+ if (typeof master.margin === "number") {
108
+ masterProps.margin = pxToIn(master.margin);
109
+ }
110
+ else {
111
+ masterProps.margin = [
112
+ pxToIn(master.margin.top ?? 0),
113
+ pxToIn(master.margin.right ?? 0),
114
+ pxToIn(master.margin.bottom ?? 0),
115
+ pxToIn(master.margin.left ?? 0),
116
+ ];
117
+ }
118
+ }
119
+ // objects の変換
120
+ if (master.objects && master.objects.length > 0) {
121
+ masterProps.objects = master.objects.map((obj) => convertMasterObject(obj));
122
+ }
123
+ // slideNumber の変換
124
+ if (master.slideNumber) {
125
+ masterProps.slideNumber = {
126
+ x: pxToIn(master.slideNumber.x),
127
+ y: pxToIn(master.slideNumber.y),
128
+ w: master.slideNumber.w ? pxToIn(master.slideNumber.w) : undefined,
129
+ h: master.slideNumber.h ? pxToIn(master.slideNumber.h) : undefined,
130
+ fontSize: master.slideNumber.fontPx
131
+ ? pxToPt(master.slideNumber.fontPx)
132
+ : undefined,
133
+ fontFace: master.slideNumber.fontFamily,
134
+ color: master.slideNumber.color,
135
+ };
136
+ }
137
+ pptx.defineSlideMaster(masterProps);
138
+ return masterName;
139
+ }
9
140
  /**
10
141
  * PositionedNode ツリーを PptxGenJS スライドに変換する
11
142
  * @param pages PositionedNode ツリーの配列(各要素が1ページ)
12
143
  * @param slidePx スライド全体のサイズ(px)
144
+ * @param master スライドマスターオプション(省略可能)
13
145
  * @returns PptxGenJS インスタンス
14
146
  */
15
- export function renderPptx(pages, slidePx) {
147
+ export function renderPptx(pages, slidePx, master) {
16
148
  const slideIn = { w: pxToIn(slidePx.w), h: pxToIn(slidePx.h) }; // layout(=px) → PptxGenJS(=inch) への最終変換
17
149
  const pptx = new PptxGenJS();
18
150
  pptx.defineLayout({ name: "custom", width: slideIn.w, height: slideIn.h });
19
151
  pptx.layout = "custom";
152
+ // マスターが指定されている場合、defineSlideMaster を呼び出す
153
+ const masterName = master
154
+ ? defineSlideMasterFromOptions(pptx, master)
155
+ : undefined;
20
156
  for (const data of pages) {
21
- const slide = pptx.addSlide();
157
+ // マスターが指定されている場合は masterName を使用
158
+ const slide = masterName ? pptx.addSlide({ masterName }) : pptx.addSlide();
22
159
  const ctx = { slide, pptx };
160
+ // ルートノードの backgroundColor はスライドの background プロパティとして適用
161
+ // これにより、マスタースライドのオブジェクトを覆い隠さない
162
+ // line ノードは backgroundColor を持たないためスキップ
163
+ const rootBackgroundColor = data.type !== "line" ? data.backgroundColor : undefined;
164
+ if (rootBackgroundColor) {
165
+ slide.background = { color: rootBackgroundColor };
166
+ }
23
167
  /**
24
168
  * node をスライドにレンダリングする
169
+ * @param isRoot ルートノードかどうか(ルートノードの background は slide.background で処理済み)
25
170
  */
26
- function renderNode(node) {
27
- renderBackgroundAndBorder(node, ctx);
171
+ function renderNode(node, isRoot = false) {
172
+ // line ノードは backgroundColor/border を持たないため、background/border の描画をスキップ
173
+ if (node.type !== "line") {
174
+ // ルートノードの backgroundColor は既に slide.background に適用済みなのでスキップ
175
+ if (isRoot && rootBackgroundColor) {
176
+ // border のみ描画(backgroundColor はスキップ)
177
+ const { border, borderRadius } = node;
178
+ const hasBorder = Boolean(border &&
179
+ (border.color !== undefined ||
180
+ border.width !== undefined ||
181
+ border.dashType !== undefined));
182
+ if (hasBorder) {
183
+ const line = {
184
+ color: border?.color ?? "000000",
185
+ width: border?.width !== undefined ? pxToPt(border.width) : undefined,
186
+ dashType: border?.dashType,
187
+ };
188
+ const shapeType = borderRadius
189
+ ? ctx.pptx.ShapeType.roundRect
190
+ : ctx.pptx.ShapeType.rect;
191
+ const rectRadius = borderRadius
192
+ ? Math.min((borderRadius / Math.min(node.w, node.h)) * 2, 1)
193
+ : undefined;
194
+ ctx.slide.addShape(shapeType, {
195
+ x: pxToIn(node.x),
196
+ y: pxToIn(node.y),
197
+ w: pxToIn(node.w),
198
+ h: pxToIn(node.h),
199
+ fill: { type: "none" },
200
+ line,
201
+ rectRadius,
202
+ });
203
+ }
204
+ }
205
+ else {
206
+ renderBackgroundAndBorder(node, ctx);
207
+ }
208
+ }
28
209
  switch (node.type) {
29
210
  case "text":
30
211
  renderTextNode(node, ctx);
@@ -67,9 +248,18 @@ export function renderPptx(pages, slidePx) {
67
248
  case "processArrow":
68
249
  renderProcessArrowNode(node, ctx);
69
250
  break;
251
+ case "line":
252
+ renderLineNode(node, ctx);
253
+ break;
254
+ case "layer":
255
+ // layer の子要素を配列順に描画(後の要素が上に来る)
256
+ for (const child of node.children) {
257
+ renderNode(child);
258
+ }
259
+ break;
70
260
  }
71
261
  }
72
- renderNode(data);
262
+ renderNode(data, true); // ルートノードとして処理
73
263
  }
74
264
  return pptx;
75
265
  }
package/dist/schema.d.ts CHANGED
@@ -18,6 +18,6 @@
18
18
  * }
19
19
  * ```
20
20
  */
21
- export { inputPomNodeSchema, inputTextNodeSchema, inputImageNodeSchema, inputTableNodeSchema, inputBoxNodeSchema, inputVStackNodeSchema, inputHStackNodeSchema, inputShapeNodeSchema, inputChartNodeSchema, inputMasterSlideOptionsSchema, inputBaseNodeSchema, type InputPOMNode, type InputTextNode, type InputImageNode, type InputTableNode, type InputBoxNode, type InputVStackNode, type InputHStackNode, type InputShapeNode, type InputChartNode, type InputMasterSlideOptions, } from "./inputSchema";
22
- export { lengthSchema, paddingSchema, borderStyleSchema, borderDashSchema, fillStyleSchema, shadowStyleSchema, alignItemsSchema, justifyContentSchema, shapeTypeSchema, chartTypeSchema, chartDataSchema, bulletOptionsSchema, bulletNumberTypeSchema, tableColumnSchema, tableRowSchema, tableCellSchema, pageNumberPositionSchema, type Length, type Padding, type BorderStyle, type BorderDash, type FillStyle, type ShadowStyle, type AlignItems, type JustifyContent, type ShapeType, type ChartType, type ChartData, type BulletOptions, type BulletNumberType, type TableColumn, type TableRow, type TableCell, type PageNumberPosition, } from "./types";
21
+ export { inputPomNodeSchema, inputTextNodeSchema, inputImageNodeSchema, inputTableNodeSchema, inputBoxNodeSchema, inputVStackNodeSchema, inputHStackNodeSchema, inputShapeNodeSchema, inputChartNodeSchema, inputSlideMasterOptionsSchema, inputMasterTextObjectSchema, inputMasterImageObjectSchema, inputMasterRectObjectSchema, inputMasterLineObjectSchema, inputMasterObjectSchema, inputSlideNumberOptionsSchema, inputSlideMasterBackgroundSchema, inputSlideMasterMarginSchema, inputBaseNodeSchema, type InputPOMNode, type InputTextNode, type InputImageNode, type InputTableNode, type InputBoxNode, type InputVStackNode, type InputHStackNode, type InputShapeNode, type InputChartNode, type InputSlideMasterOptions, } from "./inputSchema";
22
+ export { lengthSchema, paddingSchema, borderStyleSchema, borderDashSchema, fillStyleSchema, shadowStyleSchema, alignItemsSchema, justifyContentSchema, shapeTypeSchema, chartTypeSchema, chartDataSchema, bulletOptionsSchema, bulletNumberTypeSchema, tableColumnSchema, tableRowSchema, tableCellSchema, slideMasterOptionsSchema, masterTextObjectSchema, masterImageObjectSchema, masterRectObjectSchema, masterLineObjectSchema, masterObjectSchema, slideNumberOptionsSchema, slideMasterBackgroundSchema, slideMasterMarginSchema, type Length, type Padding, type BorderStyle, type BorderDash, type FillStyle, type ShadowStyle, type AlignItems, type JustifyContent, type ShapeType, type ChartType, type ChartData, type BulletOptions, type BulletNumberType, type TableColumn, type TableRow, type TableCell, type SlideMasterOptions, type MasterTextObject, type MasterImageObject, type MasterRectObject, type MasterLineObject, type MasterObject, type SlideNumberOptions, type SlideMasterBackground, type SlideMasterMargin, } from "./types";
23
23
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,6BAA6B,EAC7B,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,uBAAuB,GAC7B,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,wBAAwB,EACxB,KAAK,MAAM,EACX,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,kBAAkB,GACxB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,6BAA6B,EAC7B,2BAA2B,EAC3B,4BAA4B,EAC5B,2BAA2B,EAC3B,2BAA2B,EAC3B,uBAAuB,EACvB,6BAA6B,EAC7B,gCAAgC,EAChC,4BAA4B,EAC5B,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,uBAAuB,GAC7B,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,wBAAwB,EACxB,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,wBAAwB,EACxB,2BAA2B,EAC3B,uBAAuB,EACvB,KAAK,MAAM,EACX,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,GACvB,MAAM,SAAS,CAAC"}
package/dist/schema.js CHANGED
@@ -19,6 +19,6 @@
19
19
  * ```
20
20
  */
21
21
  // Input schemas for LLM/external input validation
22
- export { inputPomNodeSchema, inputTextNodeSchema, inputImageNodeSchema, inputTableNodeSchema, inputBoxNodeSchema, inputVStackNodeSchema, inputHStackNodeSchema, inputShapeNodeSchema, inputChartNodeSchema, inputMasterSlideOptionsSchema, inputBaseNodeSchema, } from "./inputSchema";
22
+ export { inputPomNodeSchema, inputTextNodeSchema, inputImageNodeSchema, inputTableNodeSchema, inputBoxNodeSchema, inputVStackNodeSchema, inputHStackNodeSchema, inputShapeNodeSchema, inputChartNodeSchema, inputSlideMasterOptionsSchema, inputMasterTextObjectSchema, inputMasterImageObjectSchema, inputMasterRectObjectSchema, inputMasterLineObjectSchema, inputMasterObjectSchema, inputSlideNumberOptionsSchema, inputSlideMasterBackgroundSchema, inputSlideMasterMarginSchema, inputBaseNodeSchema, } from "./inputSchema";
23
23
  // Basic type schemas (browser-compatible)
24
- export { lengthSchema, paddingSchema, borderStyleSchema, borderDashSchema, fillStyleSchema, shadowStyleSchema, alignItemsSchema, justifyContentSchema, shapeTypeSchema, chartTypeSchema, chartDataSchema, bulletOptionsSchema, bulletNumberTypeSchema, tableColumnSchema, tableRowSchema, tableCellSchema, pageNumberPositionSchema, } from "./types";
24
+ export { lengthSchema, paddingSchema, borderStyleSchema, borderDashSchema, fillStyleSchema, shadowStyleSchema, alignItemsSchema, justifyContentSchema, shapeTypeSchema, chartTypeSchema, chartDataSchema, bulletOptionsSchema, bulletNumberTypeSchema, tableColumnSchema, tableRowSchema, tableCellSchema, slideMasterOptionsSchema, masterTextObjectSchema, masterImageObjectSchema, masterRectObjectSchema, masterLineObjectSchema, masterObjectSchema, slideNumberOptionsSchema, slideMasterBackgroundSchema, slideMasterMarginSchema, } from "./types";
@@ -1 +1 @@
1
- {"version":3,"file":"toPositioned.d.ts","sourceRoot":"","sources":["../../src/toPositioned/toPositioned.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAGxD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,OAAO,SAAI,EACX,OAAO,SAAI,GACV,cAAc,CAyIhB"}
1
+ {"version":3,"file":"toPositioned.d.ts","sourceRoot":"","sources":["../../src/toPositioned/toPositioned.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAGxD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,OAAO,SAAI,EACX,OAAO,SAAI,GACV,cAAc,CAyMhB"}
@@ -136,5 +136,65 @@ export function toPositioned(pom, parentX = 0, parentY = 0) {
136
136
  children: pom.children.map((child) => toPositioned(child, absoluteX, absoluteY)),
137
137
  };
138
138
  }
139
+ case "line": {
140
+ // line ノードは絶対座標(x1, y1, x2, y2)を持つため、
141
+ // yogaNode の座標ではなく自身の座標からバウンディングボックスを計算
142
+ return {
143
+ ...pom,
144
+ x: Math.min(pom.x1, pom.x2),
145
+ y: Math.min(pom.y1, pom.y2),
146
+ w: Math.abs(pom.x2 - pom.x1),
147
+ h: Math.abs(pom.y2 - pom.y1),
148
+ };
149
+ }
150
+ case "layer": {
151
+ // layer の子要素は layer 内の相対座標(child.x, child.y)を持つ
152
+ // layer の絶対座標に加算してスライド上の絶対座標に変換
153
+ return {
154
+ ...pom,
155
+ x: absoluteX,
156
+ y: absoluteY,
157
+ w: layout.width,
158
+ h: layout.height,
159
+ children: pom.children.map((child) => {
160
+ // layer 内での子要素の絶対座標(child.x, child.y がない場合は 0)
161
+ const childX = child.x ?? 0;
162
+ const childY = child.y ?? 0;
163
+ // line ノードは特別な処理が必要
164
+ // x1, y1, x2, y2 は layer 内の相対座標として扱い、layer の座標を加算
165
+ if (child.type === "line") {
166
+ const lineAbsoluteX = absoluteX + childX;
167
+ const lineAbsoluteY = absoluteY + childY;
168
+ const adjustedX1 = child.x1 + lineAbsoluteX;
169
+ const adjustedY1 = child.y1 + lineAbsoluteY;
170
+ const adjustedX2 = child.x2 + lineAbsoluteX;
171
+ const adjustedY2 = child.y2 + lineAbsoluteY;
172
+ return {
173
+ ...child,
174
+ x1: adjustedX1,
175
+ y1: adjustedY1,
176
+ x2: adjustedX2,
177
+ y2: adjustedY2,
178
+ x: Math.min(adjustedX1, adjustedX2),
179
+ y: Math.min(adjustedY1, adjustedY2),
180
+ w: Math.abs(adjustedX2 - adjustedX1),
181
+ h: Math.abs(adjustedY2 - adjustedY1),
182
+ };
183
+ }
184
+ // その他のノードは通常の処理
185
+ // Yoga で計算された子要素の相対座標を取得
186
+ const childLayout = child.yogaNode.getComputedLayout();
187
+ // 正しい親座標を計算: layer の座標 + child.x - Yoga の相対座標
188
+ // こうすることで toPositioned 内で:
189
+ // absoluteX = adjustedParentX + childLayout.left
190
+ // = (absoluteX + child.x - childLayout.left) + childLayout.left
191
+ // = absoluteX + child.x
192
+ // となり、子要素とその内部の子要素が正しい座標で配置される
193
+ const adjustedParentX = absoluteX + childX - childLayout.left;
194
+ const adjustedParentY = absoluteY + childY - childLayout.top;
195
+ return toPositioned(child, adjustedParentX, adjustedParentY);
196
+ }),
197
+ };
198
+ }
139
199
  }
140
200
  }