@jasy/pdf 1.0.0-alpha.1 → 1.0.0-alpha.10

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 (275) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -21
  3. package/dist/api/args.d.ts +1 -1
  4. package/dist/api/args.js +2 -5
  5. package/dist/api/color.d.ts +4 -4
  6. package/dist/api/color.js +11 -17
  7. package/dist/api/content.d.ts +20 -13
  8. package/dist/api/content.js +44 -29
  9. package/dist/api/descriptor.d.ts +2 -2
  10. package/dist/api/descriptor.js +121 -31
  11. package/dist/api/dimension.d.ts +76 -0
  12. package/dist/api/dimension.js +43 -0
  13. package/dist/api/font-url.d.ts +28 -0
  14. package/dist/api/font-url.js +134 -0
  15. package/dist/api/forms.d.ts +347 -0
  16. package/dist/api/forms.js +189 -0
  17. package/dist/api/gradient.d.ts +53 -0
  18. package/dist/api/gradient.js +97 -0
  19. package/dist/api/index.d.ts +13 -8
  20. package/dist/api/index.js +13 -24
  21. package/dist/api/insets.d.ts +19 -12
  22. package/dist/api/insets.js +19 -12
  23. package/dist/api/layout.d.ts +149 -25
  24. package/dist/api/layout.js +182 -51
  25. package/dist/api/page-builder.d.ts +40 -0
  26. package/dist/api/page-builder.js +44 -0
  27. package/dist/api/structure.d.ts +100 -13
  28. package/dist/api/structure.js +179 -88
  29. package/dist/api/table.d.ts +5 -5
  30. package/dist/api/table.js +38 -26
  31. package/dist/api/text.d.ts +90 -4
  32. package/dist/api/text.js +116 -31
  33. package/dist/assets/font-data.d.ts +2 -0
  34. package/dist/assets/font-data.js +21 -0
  35. package/dist/assets/font-data.ts +37 -0
  36. package/dist/common/color.js +1 -5
  37. package/dist/constants/page-sizes.js +3 -6
  38. package/dist/constants/pdf-parts.js +1 -4
  39. package/dist/crypto/legacy-handler.d.ts +43 -0
  40. package/dist/crypto/legacy-handler.js +145 -0
  41. package/dist/crypto/security-handler.d.ts +62 -0
  42. package/dist/crypto/security-handler.js +155 -0
  43. package/dist/crypto/webcrypto.d.ts +11 -0
  44. package/dist/crypto/webcrypto.js +62 -0
  45. package/dist/edit/acroform-reader.d.ts +70 -0
  46. package/dist/edit/acroform-reader.js +126 -0
  47. package/dist/edit/appearance.d.ts +47 -0
  48. package/dist/edit/appearance.js +171 -0
  49. package/dist/edit/document.d.ts +145 -0
  50. package/dist/edit/document.js +642 -0
  51. package/dist/edit/fill.d.ts +65 -0
  52. package/dist/edit/fill.js +424 -0
  53. package/dist/edit/flatten.d.ts +54 -0
  54. package/dist/edit/flatten.js +462 -0
  55. package/dist/edit/index.d.ts +20 -0
  56. package/dist/edit/index.js +18 -0
  57. package/dist/edit/lexer.d.ts +30 -0
  58. package/dist/edit/lexer.js +285 -0
  59. package/dist/edit/objects.d.ts +68 -0
  60. package/dist/edit/objects.js +83 -0
  61. package/dist/edit/writer.d.ts +60 -0
  62. package/dist/edit/writer.js +283 -0
  63. package/dist/elements/container-element.d.ts +50 -5
  64. package/dist/elements/container-element.js +100 -39
  65. package/dist/elements/forms/checkbox-element.d.ts +51 -0
  66. package/dist/elements/forms/checkbox-element.js +48 -0
  67. package/dist/elements/forms/choice-element.d.ts +53 -0
  68. package/dist/elements/forms/choice-element.js +59 -0
  69. package/dist/elements/forms/push-button-element.d.ts +56 -0
  70. package/dist/elements/forms/push-button-element.js +49 -0
  71. package/dist/elements/forms/radio-element.d.ts +52 -0
  72. package/dist/elements/forms/radio-element.js +49 -0
  73. package/dist/elements/forms/signature-element.d.ts +54 -0
  74. package/dist/elements/forms/signature-element.js +47 -0
  75. package/dist/elements/forms/text-field-element.d.ts +61 -0
  76. package/dist/elements/forms/text-field-element.js +54 -0
  77. package/dist/elements/image-element.d.ts +58 -6
  78. package/dist/elements/image-element.js +145 -111
  79. package/dist/elements/index.d.ts +26 -10
  80. package/dist/elements/index.js +26 -28
  81. package/dist/elements/layout/anchor-element.d.ts +23 -0
  82. package/dist/elements/layout/anchor-element.js +27 -0
  83. package/dist/elements/layout/bookmark-element.d.ts +27 -0
  84. package/dist/elements/layout/bookmark-element.js +30 -0
  85. package/dist/elements/layout/default-text-style-element.d.ts +30 -0
  86. package/dist/elements/layout/default-text-style-element.js +47 -0
  87. package/dist/elements/layout/deferred-element.d.ts +3 -3
  88. package/dist/elements/layout/deferred-element.js +4 -8
  89. package/dist/elements/layout/expanded-element.d.ts +6 -4
  90. package/dist/elements/layout/expanded-element.js +22 -17
  91. package/dist/elements/layout/keep-together-element.d.ts +42 -0
  92. package/dist/elements/layout/keep-together-element.js +85 -0
  93. package/dist/elements/layout/link-element.d.ts +33 -0
  94. package/dist/elements/layout/link-element.js +39 -0
  95. package/dist/elements/layout/padding-element.d.ts +10 -5
  96. package/dist/elements/layout/padding-element.js +25 -16
  97. package/dist/elements/layout/page-break-element.d.ts +17 -0
  98. package/dist/elements/layout/page-break-element.js +24 -0
  99. package/dist/elements/layout/page-builder-element.d.ts +32 -0
  100. package/dist/elements/layout/page-builder-element.js +45 -0
  101. package/dist/elements/layout/positioned-element.d.ts +47 -0
  102. package/dist/elements/layout/positioned-element.js +73 -0
  103. package/dist/elements/layout/repeating-header-element.d.ts +3 -3
  104. package/dist/elements/layout/repeating-header-element.js +8 -12
  105. package/dist/elements/layout/rotated-box-element.d.ts +35 -0
  106. package/dist/elements/layout/rotated-box-element.js +54 -0
  107. package/dist/elements/layout/rotated-element.d.ts +32 -0
  108. package/dist/elements/layout/rotated-element.js +41 -0
  109. package/dist/elements/layout/sized-container-element.d.ts +2 -2
  110. package/dist/elements/layout/sized-container-element.js +6 -11
  111. package/dist/elements/layout/struct-group.d.ts +28 -0
  112. package/dist/elements/layout/struct-group.js +42 -0
  113. package/dist/elements/line-element.d.ts +3 -3
  114. package/dist/elements/line-element.js +5 -10
  115. package/dist/elements/page-element.d.ts +26 -6
  116. package/dist/elements/page-element.js +72 -27
  117. package/dist/elements/pdf-document-element.d.ts +10 -4
  118. package/dist/elements/pdf-document-element.js +11 -10
  119. package/dist/elements/pdf-element.d.ts +150 -4
  120. package/dist/elements/pdf-element.js +138 -20
  121. package/dist/elements/rectangle-element.d.ts +52 -11
  122. package/dist/elements/rectangle-element.js +129 -36
  123. package/dist/elements/row-element.d.ts +45 -4
  124. package/dist/elements/row-element.js +66 -18
  125. package/dist/elements/text-element.d.ts +132 -11
  126. package/dist/elements/text-element.js +206 -56
  127. package/dist/forms/acroform.d.ts +63 -0
  128. package/dist/forms/acroform.js +427 -0
  129. package/dist/forms/appearance.d.ts +58 -0
  130. package/dist/forms/appearance.js +204 -0
  131. package/dist/forms/field.d.ts +164 -0
  132. package/dist/forms/field.js +1 -0
  133. package/dist/forms/pdf.d.ts +19 -0
  134. package/dist/forms/pdf.js +28 -0
  135. package/dist/index.d.ts +3 -3
  136. package/dist/index.js +3 -19
  137. package/dist/ir/display-list.d.ts +197 -8
  138. package/dist/ir/display-list.js +8 -2
  139. package/dist/layout/alignment.d.ts +10 -0
  140. package/dist/layout/alignment.js +6 -0
  141. package/dist/layout/box-constraints.d.ts +61 -0
  142. package/dist/layout/box-constraints.js +88 -6
  143. package/dist/layout/collect-images.d.ts +9 -0
  144. package/dist/layout/collect-images.js +34 -0
  145. package/dist/layout/fragmentation.d.ts +20 -1
  146. package/dist/layout/fragmentation.js +74 -18
  147. package/dist/layout/insets.d.ts +28 -0
  148. package/dist/layout/insets.js +20 -0
  149. package/dist/platform/browser-fs.d.ts +2 -0
  150. package/dist/platform/browser-fs.js +9 -0
  151. package/dist/platform/browser-image.d.ts +5 -0
  152. package/dist/platform/browser-image.js +13 -0
  153. package/dist/platform/node-fs.d.ts +2 -0
  154. package/dist/platform/node-fs.js +10 -0
  155. package/dist/platform/node-image.d.ts +5 -0
  156. package/dist/platform/node-image.js +9 -0
  157. package/dist/renderer/anchor-renderer.d.ts +6 -0
  158. package/dist/renderer/anchor-renderer.js +11 -0
  159. package/dist/renderer/bookmark-renderer.d.ts +6 -0
  160. package/dist/renderer/bookmark-renderer.js +11 -0
  161. package/dist/renderer/container-renderer.d.ts +3 -3
  162. package/dist/renderer/container-renderer.js +11 -28
  163. package/dist/renderer/default-text-style-renderer.d.ts +6 -0
  164. package/dist/renderer/default-text-style-renderer.js +10 -0
  165. package/dist/renderer/deferred-renderer.d.ts +3 -3
  166. package/dist/renderer/deferred-renderer.js +8 -23
  167. package/dist/renderer/emoji-image.d.ts +9 -0
  168. package/dist/renderer/emoji-image.js +68 -0
  169. package/dist/renderer/expanded-renderer.d.ts +3 -3
  170. package/dist/renderer/expanded-renderer.js +6 -21
  171. package/dist/renderer/form-field-renderer.d.ts +20 -0
  172. package/dist/renderer/form-field-renderer.js +12 -0
  173. package/dist/renderer/image-renderer.d.ts +4 -4
  174. package/dist/renderer/image-renderer.js +86 -75
  175. package/dist/renderer/index.d.ts +10 -10
  176. package/dist/renderer/index.js +10 -26
  177. package/dist/renderer/keep-together-renderer.d.ts +10 -0
  178. package/dist/renderer/keep-together-renderer.js +12 -0
  179. package/dist/renderer/line-renderer.d.ts +3 -3
  180. package/dist/renderer/line-renderer.js +13 -28
  181. package/dist/renderer/link-renderer.d.ts +6 -0
  182. package/dist/renderer/link-renderer.js +11 -0
  183. package/dist/renderer/padding-renderer.d.ts +3 -3
  184. package/dist/renderer/padding-renderer.js +6 -21
  185. package/dist/renderer/page-break-renderer.d.ts +14 -0
  186. package/dist/renderer/page-break-renderer.js +15 -0
  187. package/dist/renderer/page-builder-renderer.d.ts +6 -0
  188. package/dist/renderer/page-builder-renderer.js +11 -0
  189. package/dist/renderer/page-renderer.d.ts +2 -2
  190. package/dist/renderer/page-renderer.js +115 -77
  191. package/dist/renderer/pdf-backend.d.ts +31 -4
  192. package/dist/renderer/pdf-backend.js +287 -49
  193. package/dist/renderer/pdf-config.js +4 -7
  194. package/dist/renderer/pdf-document-class.d.ts +5 -5
  195. package/dist/renderer/pdf-document-class.js +27 -41
  196. package/dist/renderer/pdf-document-renderer.d.ts +19 -10
  197. package/dist/renderer/pdf-document-renderer.js +135 -91
  198. package/dist/renderer/pdf-renderer.d.ts +2 -2
  199. package/dist/renderer/pdf-renderer.js +165 -90
  200. package/dist/renderer/positioned-renderer.d.ts +6 -0
  201. package/dist/renderer/positioned-renderer.js +10 -0
  202. package/dist/renderer/rectangle-renderer.d.ts +3 -3
  203. package/dist/renderer/rectangle-renderer.js +49 -44
  204. package/dist/renderer/repeating-header-renderer.d.ts +3 -3
  205. package/dist/renderer/repeating-header-renderer.js +10 -26
  206. package/dist/renderer/rotated-renderer.d.ts +7 -0
  207. package/dist/renderer/rotated-renderer.js +29 -0
  208. package/dist/renderer/row-renderer.d.ts +3 -3
  209. package/dist/renderer/row-renderer.js +11 -28
  210. package/dist/renderer/struct-group-renderer.d.ts +10 -0
  211. package/dist/renderer/struct-group-renderer.js +24 -0
  212. package/dist/renderer/text-renderer.d.ts +9 -5
  213. package/dist/renderer/text-renderer.js +437 -89
  214. package/dist/text/advance.d.ts +34 -0
  215. package/dist/text/advance.js +45 -0
  216. package/dist/text/arabic.d.ts +20 -0
  217. package/dist/text/arabic.js +101 -0
  218. package/dist/text/bidi.d.ts +33 -0
  219. package/dist/text/bidi.js +94 -0
  220. package/dist/text/emoji-codepoints.d.ts +1 -0
  221. package/dist/text/emoji-codepoints.js +29 -0
  222. package/dist/text/font-fallback.d.ts +25 -0
  223. package/dist/text/font-fallback.js +38 -0
  224. package/dist/text/line-breaker.d.ts +50 -12
  225. package/dist/text/line-breaker.js +158 -37
  226. package/dist/text/line-metrics.d.ts +49 -0
  227. package/dist/text/line-metrics.js +57 -0
  228. package/dist/text/orphans-widows.d.ts +27 -0
  229. package/dist/text/orphans-widows.js +53 -0
  230. package/dist/text/shape.d.ts +29 -0
  231. package/dist/text/shape.js +67 -0
  232. package/dist/text/text-decoration.d.ts +50 -0
  233. package/dist/text/text-decoration.js +62 -0
  234. package/dist/text/text-style.d.ts +60 -0
  235. package/dist/text/text-style.js +79 -0
  236. package/dist/utils/afm-parser.d.ts +34 -0
  237. package/dist/utils/afm-parser.js +76 -17
  238. package/dist/utils/bytes.d.ts +24 -0
  239. package/dist/utils/bytes.js +76 -0
  240. package/dist/utils/dest-registry.d.ts +22 -0
  241. package/dist/utils/dest-registry.js +32 -0
  242. package/dist/utils/flex-layout.d.ts +36 -9
  243. package/dist/utils/flex-layout.js +207 -30
  244. package/dist/utils/font-metrics.d.ts +20 -1
  245. package/dist/utils/font-metrics.js +1 -2
  246. package/dist/utils/font-path.js +3 -6
  247. package/dist/utils/gsub.d.ts +36 -0
  248. package/dist/utils/gsub.js +178 -0
  249. package/dist/utils/image-helper.d.ts +6 -5
  250. package/dist/utils/image-helper.js +101 -111
  251. package/dist/utils/inflate.d.ts +16 -0
  252. package/dist/utils/inflate.js +52 -0
  253. package/dist/utils/md5.d.ts +4 -0
  254. package/dist/utils/md5.js +79 -0
  255. package/dist/utils/outline.d.ts +21 -0
  256. package/dist/utils/outline.js +79 -0
  257. package/dist/utils/pdf-object-manager.d.ts +110 -8
  258. package/dist/utils/pdf-object-manager.js +583 -141
  259. package/dist/utils/renderer-registry.d.ts +13 -1
  260. package/dist/utils/renderer-registry.js +23 -6
  261. package/dist/utils/struct-tree.d.ts +44 -0
  262. package/dist/utils/struct-tree.js +129 -0
  263. package/dist/utils/ttf-parser.d.ts +134 -2
  264. package/dist/utils/ttf-parser.js +873 -50
  265. package/dist/utils/ttf-subsetter.d.ts +1 -1
  266. package/dist/utils/ttf-subsetter.js +40 -42
  267. package/dist/utils/ua-xmp.d.ts +9 -0
  268. package/dist/utils/ua-xmp.js +32 -0
  269. package/dist/utils/utf8-to-windows1252-encoder.d.ts +6 -0
  270. package/dist/utils/utf8-to-windows1252-encoder.js +11 -4
  271. package/dist/utils/woff.d.ts +10 -0
  272. package/dist/utils/woff.js +116 -0
  273. package/dist/validators/element-validator.d.ts +2 -2
  274. package/dist/validators/element-validator.js +31 -26
  275. package/package.json +22 -2
@@ -1,8 +1,10 @@
1
- import { Color } from "../common/color";
2
- import { BoxConstraints, Offset, Size } from "../layout/box-constraints";
3
- import { Fragmentable, FragmentResult } from "../layout/fragmentation";
4
- import { LayoutContext, PDFElement, SizedElement, SizedPDFElement, WithChildren } from "./pdf-element";
5
- /** Per-side border colours. When set, each present side is stroked individually (sharp
1
+ import type { Radii } from "../ir/display-list.js";
2
+ import type { GradientInput } from "../api/gradient.js";
3
+ import { Color } from "../common/color.js";
4
+ import { BoxConstraints, Offset, Size } from "../layout/box-constraints.js";
5
+ import { Fragmentable, FragmentResult } from "../layout/fragmentation.js";
6
+ import { LayoutContext, PDFElement, SizedElement, SizedPDFElement, WithChildren } from "./pdf-element.js";
7
+ /** Per-side border colors. When set, each present side is stroked individually (sharp
6
8
  * corners), instead of the uniform `color` border - this is what enables grid lines. */
7
9
  export interface SideBorders {
8
10
  top?: Color;
@@ -12,12 +14,38 @@ export interface SideBorders {
12
14
  }
13
15
  interface RectangleElementParams extends SizedElement, WithChildren {
14
16
  color?: Color;
15
- backgroundColor?: Color;
17
+ /** Solid colour, or a box-relative gradient the renderer resolves against this box. */
18
+ backgroundColor?: Color | GradientInput;
16
19
  borderWidth?: number;
17
- /** Corner radius in points; 0 = sharp corners (default). */
18
- radius?: number;
20
+ /** Corner radius in points - one number for all four corners, or per corner. 0 = sharp (default). */
21
+ radius?: number | Radii;
19
22
  /** Individual side borders; overrides the uniform `color` border when present. */
20
23
  sideBorders?: SideBorders;
24
+ /** When true, this box is a positioning frame for `Positioned` descendants (CSS `relative`). */
25
+ relative?: boolean;
26
+ /** `"hidden"` crops children to the box (CSS `overflow: hidden`); `"visible"` (default) lets a
27
+ * `Positioned` child spill over the edge. */
28
+ overflow?: "hidden" | "visible";
29
+ /** Width as a fraction (0..1) of the offered width, instead of a fixed `width` (CSS `50%`). Only
30
+ * resolves in a bounded region; an explicit `width` wins over it. */
31
+ widthFactor?: number;
32
+ /** Height as a fraction (0..1) of the offered height; see `widthFactor`. */
33
+ heightFactor?: number;
34
+ /** Lower / upper bounds per axis, in points or as a fraction; see `SizingParams`. */
35
+ minWidth?: number;
36
+ maxWidth?: number;
37
+ minHeight?: number;
38
+ maxHeight?: number;
39
+ minWidthFactor?: number;
40
+ maxWidthFactor?: number;
41
+ minHeightFactor?: number;
42
+ maxHeightFactor?: number;
43
+ /** width / height; derives whichever axis is left open (CSS `aspect-ratio`). */
44
+ aspectRatio?: number;
45
+ /** Start this box on a fresh page (CSS `break-before: page`). */
46
+ breakBefore?: boolean;
47
+ /** Start everything after this box on a fresh page (CSS `break-after: page`). */
48
+ breakAfter?: boolean;
21
49
  }
22
50
  export declare class RectangleElement extends SizedPDFElement implements Fragmentable {
23
51
  private children;
@@ -26,8 +54,14 @@ export declare class RectangleElement extends SizedPDFElement implements Fragmen
26
54
  private borderWidth;
27
55
  private radius;
28
56
  private sideBorders?;
57
+ private relative;
58
+ private overflow;
59
+ private breakBefore;
60
+ private breakAfter;
29
61
  private sizeMemory;
30
- constructor({ children, color, backgroundColor, borderWidth, width, height, radius, sideBorders, }: RectangleElementParams);
62
+ constructor({ children, color, backgroundColor, borderWidth, width, height, radius, sideBorders, relative, overflow, breakBefore, breakAfter, ...sizing }: RectangleElementParams);
63
+ breaksBefore(): boolean;
64
+ breaksAfter(): boolean;
31
65
  /**
32
66
  * Splits the bordered box across pages (box-decoration-break: clone - every fragment
33
67
  * gets its own full border). The children stack is packed into the space left after
@@ -37,7 +71,13 @@ export declare class RectangleElement extends SizedPDFElement implements Fragmen
37
71
  * box is sized by what it actually holds on each page.
38
72
  */
39
73
  fragment(maxHeight: number, width: number, ctx: LayoutContext): FragmentResult;
74
+ hasForcedBreak(): boolean;
40
75
  private cloneWithChildren;
76
+ relativeSizeFactor(horizontal: boolean): number | undefined;
77
+ /** A box has no flex children of its own, but it must not swallow the need of the stack inside it: a
78
+ * `Spacer` in a box can only resolve if the box itself was given a bounded extent to pass down. With an
79
+ * explicit size on an axis the box already knows its extent there and asks for nothing. */
80
+ needsBoundedMain(horizontal: boolean): boolean;
41
81
  calculateLayout(constraints: BoxConstraints, offset: Offset, ctx: LayoutContext): Size;
42
82
  getProps(): {
43
83
  x: number;
@@ -46,10 +86,11 @@ export declare class RectangleElement extends SizedPDFElement implements Fragmen
46
86
  height: number | undefined;
47
87
  children: PDFElement[];
48
88
  color: Color;
49
- backgroundColor: Color | undefined;
89
+ backgroundColor: Color | GradientInput | undefined;
50
90
  borderWidth: number;
51
- radius: number;
91
+ radius: number | Radii;
52
92
  sideBorders: SideBorders | undefined;
93
+ overflow: "hidden" | "visible";
53
94
  };
54
95
  }
55
96
  export {};
@@ -1,22 +1,29 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RectangleElement = void 0;
4
- const color_1 = require("../common/color");
5
- const box_constraints_1 = require("../layout/box-constraints");
6
- const fragmentation_1 = require("../layout/fragmentation");
7
- const pdf_element_1 = require("./pdf-element");
8
- class RectangleElement extends pdf_element_1.SizedPDFElement {
9
- constructor({ children = [], color = new color_1.Color(0, 0, 0), backgroundColor, borderWidth, width, height, radius, sideBorders, }) {
1
+ import { Color } from "../common/color.js";
2
+ import { BoxConstraints, extentSpecs, resolveSize, } from "../layout/box-constraints.js";
3
+ import { childrenForceBreak, packChildren, } from "../layout/fragmentation.js";
4
+ import { SizedPDFElement, } from "./pdf-element.js";
5
+ export class RectangleElement extends SizedPDFElement {
6
+ constructor({ children = [], color = new Color(0, 0, 0), backgroundColor, borderWidth, width, height, radius, sideBorders, relative, overflow, breakBefore, breakAfter, ...sizing }) {
10
7
  super({ x: 0, y: 0, width, height });
11
8
  this.children = [];
12
9
  this.children = children;
13
10
  this.color = color;
14
11
  this.backgroundColor = backgroundColor;
15
12
  // `?? 1` (not `|| 1`) so an explicit `0` means "no border" instead of snapping to 1.
16
- this.borderWidth = borderWidth !== null && borderWidth !== void 0 ? borderWidth : 1;
17
- this.radius = radius !== null && radius !== void 0 ? radius : 0;
13
+ this.borderWidth = borderWidth ?? 1;
14
+ this.radius = radius ?? 0;
18
15
  this.sideBorders = sideBorders;
19
- this.sizeMemory = { x: 0, y: 0, width, height };
16
+ this.relative = relative ?? false;
17
+ this.overflow = overflow ?? "visible";
18
+ this.breakBefore = breakBefore ?? false;
19
+ this.breakAfter = breakAfter ?? false;
20
+ this.sizeMemory = { ...sizing, x: 0, y: 0, width, height };
21
+ }
22
+ breaksBefore() {
23
+ return this.breakBefore;
24
+ }
25
+ breaksAfter() {
26
+ return this.breakAfter;
20
27
  }
21
28
  /**
22
29
  * Splits the bordered box across pages (box-decoration-break: clone - every fragment
@@ -27,28 +34,45 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
27
34
  * box is sized by what it actually holds on each page.
28
35
  */
29
36
  fragment(maxHeight, width, ctx) {
30
- var _a;
31
- const boxWidth = (_a = this.sizeMemory.width) !== null && _a !== void 0 ? _a : width;
37
+ // A percentage width resolves against the region width the page driver hands us, so a
38
+ // paginating %-box keeps its fraction on every page.
39
+ const boxWidth = this.sizeMemory.width ??
40
+ (this.sizeMemory.widthFactor !== undefined ? width * this.sizeMemory.widthFactor : width);
32
41
  const innerWidth = Math.max(0, boxWidth - 2 * this.borderWidth);
33
42
  // Border-box: the content is inset by the border on top and bottom, so a fragment
34
43
  // holding `c` of content is `c + 2*border` tall. (Derived, not a fudge factor.)
35
44
  const innerMaxHeight = maxHeight - 2 * this.borderWidth;
36
- const { fitted, remainder } = (0, fragmentation_1.packChildren)(this.children, innerMaxHeight, innerWidth, ctx);
37
- if (remainder.length === 0)
45
+ const { fitted, remainder, forceBreak } = packChildren(this.children, innerMaxHeight, innerWidth, ctx);
46
+ // Fits with no forced cut: return the whole box unchanged. A trailing forced break is the
47
+ // exception - fall through so the box is rebuilt from the packed children (without the consumed
48
+ // break marker), rather than handing back the original that still holds it.
49
+ if (remainder.length === 0 && !forceBreak)
38
50
  return { fitted: this, remainder: null };
39
51
  const contentHeight = (kids) => kids.reduce((sum, child) => sum +
40
- child.calculateLayout(box_constraints_1.BoxConstraints.loose(innerWidth, Infinity), { x: 0, y: 0 }, ctx)
52
+ child.calculateLayout(BoxConstraints.loose(innerWidth, Infinity), { x: 0, y: 0 }, ctx)
41
53
  .height, 0);
42
54
  return {
43
55
  fitted: this.cloneWithChildren(fitted, contentHeight(fitted) + 2 * this.borderWidth),
44
- remainder: this.cloneWithChildren(remainder, contentHeight(remainder) + 2 * this.borderWidth),
56
+ // A trailing forced break leaves nothing to carry over: no remainder box, no extra page.
57
+ // Only the CONTINUATION carries `breakAfter` (a box that splits still breaks after its LAST
58
+ // fragment, not its first); `breakBefore` is dropped, already honoured before the split.
59
+ remainder: remainder.length === 0
60
+ ? null
61
+ : this.cloneWithChildren(remainder, contentHeight(remainder) + 2 * this.borderWidth, this.breakAfter),
62
+ forceBreak,
45
63
  };
46
64
  }
47
- cloneWithChildren(children, height) {
65
+ hasForcedBreak() {
66
+ return childrenForceBreak(this.children);
67
+ }
68
+ cloneWithChildren(children, height, breakAfter = false) {
48
69
  return new RectangleElement({
49
70
  x: 0,
50
71
  y: 0,
51
72
  width: this.sizeMemory.width,
73
+ widthFactor: this.sizeMemory.widthFactor,
74
+ // A split box is sized by its per-page content (height passed in), so the height factor
75
+ // is intentionally dropped here - box-decoration-break, same as an explicit height.
52
76
  height,
53
77
  children,
54
78
  color: this.color,
@@ -56,50 +80,119 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
56
80
  borderWidth: this.borderWidth,
57
81
  radius: this.radius,
58
82
  sideBorders: this.sideBorders,
83
+ relative: this.relative,
84
+ overflow: this.overflow,
85
+ breakAfter,
59
86
  });
60
87
  }
88
+ relativeSizeFactor(horizontal) {
89
+ return horizontal ? this.sizeMemory.widthFactor : this.sizeMemory.heightFactor;
90
+ }
91
+ /** A box has no flex children of its own, but it must not swallow the need of the stack inside it: a
92
+ * `Spacer` in a box can only resolve if the box itself was given a bounded extent to pass down. With an
93
+ * explicit size on an axis the box already knows its extent there and asks for nothing. */
94
+ needsBoundedMain(horizontal) {
95
+ const requested = horizontal
96
+ ? [this.sizeMemory.width, this.sizeMemory.widthFactor]
97
+ : [this.sizeMemory.height, this.sizeMemory.heightFactor];
98
+ if (requested.some((v) => v !== undefined))
99
+ return false;
100
+ return this.children.some((c) => c.needsBoundedMain(horizontal));
101
+ }
61
102
  calculateLayout(constraints, offset, ctx) {
62
- var _a, _b, _c;
103
+ // An explicit extent is a fixed point size or a fraction of the offered box (relative sizing);
104
+ // the fraction only resolves in a bounded region. `undefined` = fill / shrink-wrap below.
105
+ const specs = extentSpecs(this.sizeMemory);
106
+ const resolved = resolveSize(specs.width, specs.height, this.sizeMemory.aspectRatio, constraints);
107
+ const explicitWidth = resolved.width;
108
+ const explicitHeight = resolved.height;
109
+ // min/max come back as narrowed constraints, so the fill and shrink-wrap paths below obey them too.
110
+ const bounds = resolved.constraints;
63
111
  // Width: an explicit size wins (clamped), else fill the offered box. (Without this a
64
112
  // fixed box would balloon to the parent's size.)
113
+ // Whether there is a region to fill is decided by the constraints we were GIVEN: a `maxWidth` caps
114
+ // a box, it does not turn a shrink-wrapping one into a filling one (CSS `max-width` does not either).
65
115
  this.width =
66
- this.sizeMemory.width !== undefined
67
- ? constraints.constrainWidth(this.sizeMemory.width)
116
+ explicitWidth !== undefined
117
+ ? bounds.constrainWidth(explicitWidth)
68
118
  : constraints.hasBoundedWidth
69
- ? constraints.maxWidth
119
+ ? bounds.maxWidth
70
120
  : this.width;
121
+ // Width shrink-wrap: no explicit width AND an unbounded region (e.g. a `Box` badge inside a
122
+ // `Positioned`). Resolved after the children are measured, just below.
123
+ const shrinkWrapWidth = explicitWidth === undefined && !constraints.hasBoundedWidth;
71
124
  // Height: explicit wins; otherwise FILL a bounded region (e.g. inside an Expanded) but
72
125
  // SHRINK-WRAP the content in an unbounded one (a note box in a stack). Shrink-wrap is
73
126
  // resolved after the children are measured, just below.
74
- const shrinkWrapHeight = this.sizeMemory.height === undefined && !constraints.hasBoundedHeight;
127
+ const shrinkWrapHeight = explicitHeight === undefined && !constraints.hasBoundedHeight;
75
128
  this.height =
76
- this.sizeMemory.height !== undefined
77
- ? constraints.constrainHeight(this.sizeMemory.height)
129
+ explicitHeight !== undefined
130
+ ? bounds.constrainHeight(explicitHeight)
78
131
  : constraints.hasBoundedHeight
79
- ? constraints.maxHeight
132
+ ? bounds.maxHeight
80
133
  : this.height;
81
134
  this.x = this.sizeMemory.x + offset.x;
82
135
  this.y = this.sizeMemory.y + offset.y;
83
- // Lay out children stacked inside the border (inset by the border width). Width is
84
- // finalized here; height is left unbounded so each child sizes to its own content.
85
- const innerWidth = Math.max(0, ((_a = this.width) !== null && _a !== void 0 ? _a : 0) - 2 * this.borderWidth);
136
+ // A `relative` box is a positioning frame: thread a fresh frame to the subtree so any
137
+ // `Positioned` descendant registers against it (out of flow), then drain it below once the
138
+ // box is sized. A plain box leaves `ctx` untouched -> byte-identical.
139
+ const frame = this.relative
140
+ ? { origin: { x: 0, y: 0 }, size: { width: 0, height: 0 }, place: [] }
141
+ : undefined;
142
+ const childCtx = frame ? { ...ctx, frame } : ctx;
143
+ // Lay out children stacked inside the border (inset by the border width). Width is finalized here;
144
+ // height is left unbounded so each child sizes to its own content - EXCEPT for a child that cannot
145
+ // lay itself out without a bound (a stack holding an `Expanded`/`Spacer`). That one gets the height
146
+ // still free inside the box, so its flex child has real leftover space instead of an infinite one.
147
+ const innerWidth = shrinkWrapWidth
148
+ ? Infinity
149
+ : Math.max(0, (this.width ?? 0) - 2 * this.borderWidth);
150
+ const innerHeight = shrinkWrapHeight
151
+ ? Infinity
152
+ : Math.max(0, (this.height ?? 0) - 2 * this.borderWidth);
153
+ let contentWidth = 0;
86
154
  let contentHeight = 0;
87
155
  let yCursor = this.y + this.borderWidth;
88
156
  for (const child of this.children) {
89
- const childSize = child.calculateLayout(box_constraints_1.BoxConstraints.loose(innerWidth, Infinity), { x: this.x + this.borderWidth, y: yCursor }, ctx);
157
+ const consumed = yCursor - (this.y + this.borderWidth);
158
+ // Same rule the flex helper applies: a child gets a finite main extent when it cannot lay itself
159
+ // out without one - a stack holding an `Expanded`/`Spacer`, or a child sized as a percentage of us.
160
+ const needsBound = child.needsBoundedMain(false) || child.relativeSizeFactor(false) !== undefined;
161
+ const childHeight = needsBound
162
+ ? Math.max(0, innerHeight - consumed) // Infinity - consumed stays Infinity, as it should
163
+ : Infinity;
164
+ const childSize = child.calculateLayout(BoxConstraints.loose(innerWidth, childHeight), { x: this.x + this.borderWidth, y: yCursor }, childCtx);
90
165
  yCursor += childSize.height;
91
166
  contentHeight += childSize.height;
167
+ contentWidth = Math.max(contentWidth, childSize.width);
92
168
  }
169
+ // No explicit width and no bounded region: shrink-wrap to the widest child.
170
+ // Clamped, so a min/max still applies to a box that sized itself to its content.
171
+ if (shrinkWrapWidth)
172
+ this.width = bounds.constrainWidth(contentWidth + 2 * this.borderWidth);
173
+ // A ratio on a shrink-wrapping box can only be applied HERE: before the children were measured
174
+ // there was no width to derive the height from.
175
+ const ratio = this.sizeMemory.aspectRatio;
176
+ const ratioSizesHeight = ratio !== undefined && ratio > 0 && shrinkWrapWidth && shrinkWrapHeight;
93
177
  // No explicit height and no bounded region: the border hugs its content.
94
- if (shrinkWrapHeight)
95
- this.height = contentHeight + 2 * this.borderWidth;
178
+ if (ratioSizesHeight)
179
+ this.height = bounds.constrainHeight((this.width ?? 0) / ratio);
180
+ else if (shrinkWrapHeight)
181
+ this.height = bounds.constrainHeight(contentHeight + 2 * this.borderWidth);
182
+ // The box is sized now: place any out-of-flow `Positioned` descendants against its box.
183
+ if (frame) {
184
+ frame.origin = { x: this.x, y: this.y };
185
+ frame.size = { width: this.width ?? 0, height: this.height ?? 0 };
186
+ for (const place of frame.place)
187
+ place(frame, ctx);
188
+ }
96
189
  // Border-box model: width/height ARE the outer box (the rect we draw); the content
97
190
  // is inset by the border on every side. Report the honest box size - no phantom
98
191
  // border added on (that asymmetric "+border" was the source of the magic-3 fudge in
99
192
  // fragment). Top-left coordinates; the Y-flip happens at the IR -> backend seam.
100
193
  return {
101
- width: (_b = this.width) !== null && _b !== void 0 ? _b : 0,
102
- height: (_c = this.height) !== null && _c !== void 0 ? _c : 0,
194
+ width: this.width ?? 0,
195
+ height: this.height ?? 0,
103
196
  };
104
197
  }
105
198
  getProps() {
@@ -114,7 +207,7 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
114
207
  borderWidth: this.borderWidth,
115
208
  radius: this.radius,
116
209
  sideBorders: this.sideBorders,
210
+ overflow: this.overflow,
117
211
  };
118
212
  }
119
213
  }
120
- exports.RectangleElement = RectangleElement;
@@ -1,6 +1,6 @@
1
- import { BoxConstraints, Offset, Size } from "../layout/box-constraints";
2
- import { MainAlign, CrossAlign } from "../utils/flex-layout";
3
- import { LayoutContext, PDFElement, SizedPDFElement, WithChildren } from "./pdf-element";
1
+ import { BoxConstraints, Offset, Size } from "../layout/box-constraints.js";
2
+ import { MainAlign, CrossAlign } from "../utils/flex-layout.js";
3
+ import { LayoutContext, PDFElement, SizedPDFElement, WithChildren } from "./pdf-element.js";
4
4
  interface RowElementParams extends WithChildren {
5
5
  /** Space inserted between children, in points. */
6
6
  gap?: number;
@@ -8,6 +8,32 @@ interface RowElementParams extends WithChildren {
8
8
  main?: MainAlign;
9
9
  /** Vertical alignment of each child (cross axis); defaults to `stretch`. */
10
10
  cross?: CrossAlign;
11
+ /** Lay the children out backwards along the main axis (CSS `row-reverse`). */
12
+ reverse?: boolean;
13
+ /** Let the children flow onto further lines when they do not fit (CSS `flex-wrap`). */
14
+ wrap?: boolean;
15
+ /** How the block of wrapped lines sits across the axis (CSS `align-content`). */
16
+ alignContent?: MainAlign;
17
+ /** Width/height as points (fixed) or a fraction (0..1) of the offered box (relative sizing). */
18
+ width?: number;
19
+ height?: number;
20
+ widthFactor?: number;
21
+ heightFactor?: number;
22
+ /** Lower / upper bounds per axis, in points or as a fraction; see `SizingParams`. */
23
+ minWidth?: number;
24
+ maxWidth?: number;
25
+ minHeight?: number;
26
+ maxHeight?: number;
27
+ minWidthFactor?: number;
28
+ maxWidthFactor?: number;
29
+ minHeightFactor?: number;
30
+ maxHeightFactor?: number;
31
+ /** width / height; derives whichever axis is left open (CSS `aspect-ratio`). */
32
+ aspectRatio?: number;
33
+ /** Start this row on a fresh page (CSS `break-before: page`). */
34
+ breakBefore?: boolean;
35
+ /** Start everything after this row on a fresh page (CSS `break-after: page`). */
36
+ breakAfter?: boolean;
11
37
  }
12
38
  /**
13
39
  * Horizontal stack: the mirror of `ContainerElement` (Column). Children are laid out
@@ -26,7 +52,19 @@ export declare class RowElement extends SizedPDFElement {
26
52
  private gap;
27
53
  private main;
28
54
  private cross;
29
- constructor({ children, gap, main, cross }: RowElementParams);
55
+ private reverse;
56
+ private wrap;
57
+ private alignContent?;
58
+ private breakBefore;
59
+ private breakAfter;
60
+ private requested;
61
+ constructor({ children, gap, main, cross, reverse, wrap, alignContent, width, height, breakBefore, breakAfter, ...sizing }: RowElementParams);
62
+ breaksBefore(): boolean;
63
+ breaksAfter(): boolean;
64
+ relativeSizeFactor(horizontal: boolean): number | undefined;
65
+ /** The mirror of `ContainerElement`: a Row's OWN flex child needs a bounded width, and the need of any
66
+ * descendant propagates on both axes (see the Column for the reasoning). */
67
+ needsBoundedMain(horizontal: boolean): boolean;
30
68
  calculateLayout(constraints: BoxConstraints, offset: Offset, ctx: LayoutContext): Size;
31
69
  getProps(): {
32
70
  x: number;
@@ -37,6 +75,9 @@ export declare class RowElement extends SizedPDFElement {
37
75
  gap: number;
38
76
  main: MainAlign;
39
77
  cross: CrossAlign;
78
+ reverse: boolean;
79
+ wrap: boolean;
80
+ alignContent: MainAlign | undefined;
40
81
  };
41
82
  }
42
83
  export {};
@@ -1,8 +1,6 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RowElement = void 0;
4
- const flex_layout_1 = require("../utils/flex-layout");
5
- const pdf_element_1 = require("./pdf-element");
1
+ import { extentSpecs, resolveSize, } from "../layout/box-constraints.js";
2
+ import { FlexLayoutHelper, HORIZONTAL_AXIS } from "../utils/flex-layout.js";
3
+ import { FlexiblePDFElement, SizedPDFElement, } from "./pdf-element.js";
6
4
  /**
7
5
  * Horizontal stack: the mirror of `ContainerElement` (Column). Children are laid out
8
6
  * left-to-right via the shared `FlexLayoutHelper` on the horizontal axis; fixed children
@@ -15,27 +13,75 @@ const pdf_element_1 = require("./pdf-element");
15
13
  * does not fit (handled by the parent's `packChildren`); synchronized cell splitting is a
16
14
  * Grid/Table concern.
17
15
  */
18
- class RowElement extends pdf_element_1.SizedPDFElement {
19
- constructor({ children, gap, main, cross }) {
16
+ export class RowElement extends SizedPDFElement {
17
+ constructor({ children, gap, main, cross, reverse, wrap, alignContent, width, height, breakBefore, breakAfter, ...sizing }) {
20
18
  super({ x: 0, y: 0 });
21
19
  this.children = children;
22
- this.gap = gap !== null && gap !== void 0 ? gap : 0;
23
- this.main = main !== null && main !== void 0 ? main : "start";
24
- this.cross = cross !== null && cross !== void 0 ? cross : "stretch";
20
+ this.gap = gap ?? 0;
21
+ this.main = main ?? "start";
22
+ this.cross = cross ?? "stretch";
23
+ this.reverse = reverse ?? false;
24
+ this.wrap = wrap ?? false;
25
+ this.alignContent = alignContent;
26
+ this.requested = { ...sizing, width, height };
27
+ this.breakBefore = breakBefore ?? false;
28
+ this.breakAfter = breakAfter ?? false;
29
+ }
30
+ breaksBefore() {
31
+ return this.breakBefore;
32
+ }
33
+ breaksAfter() {
34
+ return this.breakAfter;
35
+ }
36
+ relativeSizeFactor(horizontal) {
37
+ return horizontal ? this.requested.widthFactor : this.requested.heightFactor;
38
+ }
39
+ /** The mirror of `ContainerElement`: a Row's OWN flex child needs a bounded width, and the need of any
40
+ * descendant propagates on both axes (see the Column for the reasoning). */
41
+ needsBoundedMain(horizontal) {
42
+ const requested = horizontal
43
+ ? [this.requested.width, this.requested.widthFactor]
44
+ : [this.requested.height, this.requested.heightFactor];
45
+ if (requested.some((v) => v !== undefined))
46
+ return false;
47
+ const ownFlexChild = horizontal && this.children.some((c) => c instanceof FlexiblePDFElement);
48
+ return ownFlexChild || this.children.some((c) => c.needsBoundedMain(horizontal));
25
49
  }
26
50
  calculateLayout(constraints, offset, ctx) {
27
51
  this.x = offset.x;
28
52
  this.y = offset.y;
29
- // Width fills the offered space (flex children split the leftover); height is the
30
- // tallest child unless the parent bounds it.
31
- const mainAvail = constraints.hasBoundedWidth ? constraints.maxWidth : Infinity;
32
- const crossAvail = constraints.hasBoundedHeight ? constraints.maxHeight : Infinity;
53
+ // Relative sizing: a pinned extent (fixed or a fraction of the offered box, clamped) wins; else
54
+ // width fills the offered space (flex children split the leftover) and height is the tallest child.
55
+ const specs = extentSpecs(this.requested);
56
+ const resolved = resolveSize(specs.width, specs.height, this.requested.aspectRatio, constraints);
57
+ const { width: explicitWidth, height: explicitHeight, constraints: bounds } = resolved;
58
+ // Fill-or-shrink-wrap is decided by the constraints we were GIVEN; a min/max only caps the result.
59
+ const boundedWidth = explicitWidth !== undefined
60
+ ? bounds.constrainWidth(explicitWidth)
61
+ : constraints.hasBoundedWidth
62
+ ? bounds.maxWidth
63
+ : undefined;
64
+ const boundedHeight = explicitHeight !== undefined
65
+ ? bounds.constrainHeight(explicitHeight)
66
+ : constraints.hasBoundedHeight
67
+ ? bounds.maxHeight
68
+ : undefined;
69
+ // Horizontal stack: main = width (children fill it), cross = height (children can stretch to it).
70
+ const mainAvail = boundedWidth ?? Infinity;
71
+ const crossAvail = boundedHeight ?? Infinity;
33
72
  let result = { mainUsed: 0, crossUsed: 0 };
34
73
  if (this.children.length > 0) {
35
- result = flex_layout_1.FlexLayoutHelper.layout(this.children, flex_layout_1.HORIZONTAL_AXIS, mainAvail, crossAvail, this.x, this.y, { gap: this.gap, main: this.main, cross: this.cross }, ctx);
74
+ result = FlexLayoutHelper.layout(this.children, HORIZONTAL_AXIS, mainAvail, crossAvail, this.x, this.y, {
75
+ gap: this.gap,
76
+ main: this.main,
77
+ cross: this.cross,
78
+ reverse: this.reverse,
79
+ wrap: this.wrap,
80
+ alignContent: this.alignContent,
81
+ }, ctx);
36
82
  }
37
- this.width = constraints.hasBoundedWidth ? constraints.maxWidth : result.mainUsed;
38
- this.height = constraints.hasBoundedHeight ? constraints.maxHeight : result.crossUsed;
83
+ this.width = boundedWidth ?? result.mainUsed;
84
+ this.height = boundedHeight ?? result.crossUsed;
39
85
  return { width: this.width, height: this.height };
40
86
  }
41
87
  getProps() {
@@ -48,7 +94,9 @@ class RowElement extends pdf_element_1.SizedPDFElement {
48
94
  gap: this.gap,
49
95
  main: this.main,
50
96
  cross: this.cross,
97
+ reverse: this.reverse,
98
+ wrap: this.wrap,
99
+ alignContent: this.alignContent,
51
100
  };
52
101
  }
53
102
  }
54
- exports.RowElement = RowElement;