@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
@@ -0,0 +1,189 @@
1
+ import { TextFieldElement } from "../elements/forms/text-field-element.js";
2
+ import { CheckboxElement } from "../elements/forms/checkbox-element.js";
3
+ import { RadioElement } from "../elements/forms/radio-element.js";
4
+ import { ChoiceElement } from "../elements/forms/choice-element.js";
5
+ import { PushButtonElement } from "../elements/forms/push-button-element.js";
6
+ import { SignatureFieldElement } from "../elements/forms/signature-element.js";
7
+ import { toColor } from "./color.js";
8
+ import { Column, Row } from "./layout.js";
9
+ import { Text } from "./text.js";
10
+ const toOptions = (opts) => opts.map((o) => (typeof o === "string" ? { value: o } : o));
11
+ /**
12
+ * An interactive text field the reader of the PDF can type into (AcroForm /Tx). Place it like any element -
13
+ * in a `Column`, `Row`, `Box` or a table cell; it reserves its box and becomes a fillable widget.
14
+ *
15
+ * ```ts
16
+ * TextField({ name: "email", border: "gray", height: 22 })
17
+ * ```
18
+ */
19
+ export function TextField(opts) {
20
+ return new TextFieldElement({
21
+ ...opts,
22
+ color: opts.color !== undefined ? toColor(opts.color) : undefined,
23
+ border: opts.border !== undefined ? toColor(opts.border) : undefined,
24
+ background: opts.background !== undefined ? toColor(opts.background) : undefined,
25
+ });
26
+ }
27
+ /**
28
+ * An interactive checkbox (AcroForm /Btn). It bakes its own checkmark appearance, so the tick shows in
29
+ * any viewer, in print, and under PDF/A - not only in ones that regenerate appearances.
30
+ *
31
+ * ```ts
32
+ * Row({ gap: 6, align: "center" }, [Checkbox({ name: "agree" }), Text("I agree")])
33
+ * ```
34
+ */
35
+ export function Checkbox(opts) {
36
+ const box = new CheckboxElement({
37
+ ...opts,
38
+ color: opts.color !== undefined ? toColor(opts.color) : undefined,
39
+ border: opts.border !== undefined ? toColor(opts.border) : undefined,
40
+ background: opts.background !== undefined ? toColor(opts.background) : undefined,
41
+ });
42
+ // Without a label the box IS the element, so nothing wraps it and the output is unchanged.
43
+ if (opts.label === undefined)
44
+ return box;
45
+ return Row({ gap: opts.labelGap ?? 8, align: "center" }, [
46
+ box,
47
+ Text(opts.label, { size: opts.labelSize ?? 12, color: opts.labelColor }),
48
+ ]);
49
+ }
50
+ /** A single radio button. Use `RadioGroup` for the common labelled-list layout, or this for custom ones. */
51
+ export function Radio(opts) {
52
+ return new RadioElement({
53
+ ...opts,
54
+ color: opts.color !== undefined ? toColor(opts.color) : undefined,
55
+ border: opts.border !== undefined ? toColor(opts.border) : undefined,
56
+ background: opts.background !== undefined ? toColor(opts.background) : undefined,
57
+ });
58
+ }
59
+ /**
60
+ * A labelled group of mutually-exclusive radio buttons. Sugar over `Radio` + `Text`: it lays each option
61
+ * out as a button-and-label row in a `Column`, and marks the one whose `value` matches the group `value`.
62
+ *
63
+ * ```ts
64
+ * RadioGroup({ name: "size", value: "m" }, [
65
+ * { value: "s", label: "Small" },
66
+ * { value: "m", label: "Medium" },
67
+ * { value: "l", label: "Large" },
68
+ * ])
69
+ * ```
70
+ */
71
+ export function RadioGroup(opts, options) {
72
+ const rows = options.map((o) => Row({ gap: 8, align: "center" }, [
73
+ Radio({
74
+ group: opts.name,
75
+ value: o.value,
76
+ selected: o.value === opts.value,
77
+ required: opts.required,
78
+ hidden: opts.hidden,
79
+ print: opts.print,
80
+ size: opts.size,
81
+ color: opts.color,
82
+ border: opts.border,
83
+ background: opts.background,
84
+ }),
85
+ Text(o.label, { size: opts.labelSize ?? 12, color: opts.labelColor }),
86
+ ]));
87
+ return Column({ gap: opts.gap ?? 8 }, rows);
88
+ }
89
+ const choiceStyle = (o) => ({
90
+ align: o.align,
91
+ tooltip: o.tooltip,
92
+ readOnly: o.readOnly,
93
+ required: o.required,
94
+ hidden: o.hidden,
95
+ print: o.print,
96
+ width: o.width,
97
+ height: o.height,
98
+ fontSize: o.fontSize,
99
+ color: o.color !== undefined ? toColor(o.color) : undefined,
100
+ border: o.border !== undefined ? toColor(o.border) : undefined,
101
+ background: o.background !== undefined ? toColor(o.background) : undefined,
102
+ borderWidth: o.borderWidth,
103
+ });
104
+ /**
105
+ * A dropdown / combo box (AcroForm /Ch). Options are plain strings or `{ value, label }`.
106
+ *
107
+ * ```ts
108
+ * Dropdown({ name: "country", value: "de" }, [{ value: "de", label: "Germany" }, "France"])
109
+ * ```
110
+ */
111
+ export function Dropdown(opts, options) {
112
+ return new ChoiceElement({
113
+ name: opts.name,
114
+ options: toOptions(options),
115
+ combo: true,
116
+ editable: opts.editable,
117
+ value: opts.value,
118
+ ...choiceStyle(opts),
119
+ });
120
+ }
121
+ /** `Select` is an alias for `Dropdown`. */
122
+ export const Select = Dropdown;
123
+ /**
124
+ * A scrollable list box (AcroForm /Ch). Give it a `height` to show more rows. Set `multiSelect` for
125
+ * several selections at once.
126
+ */
127
+ export function ListBox(opts, options) {
128
+ return new ChoiceElement({
129
+ name: opts.name,
130
+ options: toOptions(options),
131
+ combo: false,
132
+ multiSelect: opts.multiSelect,
133
+ value: opts.value,
134
+ values: opts.values,
135
+ ...choiceStyle(opts),
136
+ });
137
+ }
138
+ const toAction = (a) => {
139
+ if (a === undefined)
140
+ return undefined;
141
+ if (a === "reset")
142
+ return { kind: "reset" };
143
+ return "submit" in a ? { kind: "submit", url: a.submit } : { kind: "url", url: a.open };
144
+ };
145
+ /**
146
+ * A clickable push button (AcroForm /Btn). It holds no value - it fires an action. Its caption is baked
147
+ * into the appearance, so the button looks the same in every viewer and in print.
148
+ *
149
+ * ```ts
150
+ * PushButton({ name: "send", label: "Submit", action: { submit: "https://example.com/f" }, width: 120 })
151
+ * PushButton({ name: "clear", label: "Reset", action: "reset", width: 90 })
152
+ * ```
153
+ */
154
+ export function PushButton(opts) {
155
+ return new PushButtonElement({
156
+ name: opts.name,
157
+ label: opts.label,
158
+ action: toAction(opts.action),
159
+ tooltip: opts.tooltip,
160
+ readOnly: opts.readOnly,
161
+ required: opts.required,
162
+ hidden: opts.hidden,
163
+ print: opts.print,
164
+ width: opts.width,
165
+ height: opts.height,
166
+ fontSize: opts.fontSize,
167
+ color: opts.color !== undefined ? toColor(opts.color) : undefined,
168
+ border: opts.border !== undefined ? toColor(opts.border) : undefined,
169
+ background: opts.background !== undefined ? toColor(opts.background) : undefined,
170
+ borderWidth: opts.borderWidth,
171
+ });
172
+ }
173
+ /**
174
+ * A signature field (AcroForm /Sig) - a placeholder someone can sign later in a PDF tool. jasy creates
175
+ * the field and draws its empty "sign here" box; it does not apply signatures itself (real signing needs
176
+ * a certificate and a byte-range digest).
177
+ *
178
+ * ```ts
179
+ * SignatureField({ name: "approver", label: "Signature", width: 240 })
180
+ * ```
181
+ */
182
+ export function SignatureField(opts) {
183
+ return new SignatureFieldElement({
184
+ ...opts,
185
+ color: opts.color !== undefined ? toColor(opts.color) : undefined,
186
+ border: opts.border !== undefined ? toColor(opts.border) : undefined,
187
+ background: opts.background !== undefined ? toColor(opts.background) : undefined,
188
+ });
189
+ }
@@ -0,0 +1,53 @@
1
+ import { type ColorInput } from "./color.js";
2
+ import type { Gradient } from "../ir/display-list.js";
3
+ /**
4
+ * Gradients for a box background.
5
+ *
6
+ * The public form is BOX-RELATIVE - an angle and some stops - because that is what an author knows
7
+ * when writing the document. The engine's `Gradient` wants absolute page coordinates, so the renderer
8
+ * resolves one against the box it is painting; see `resolveGradient`.
9
+ */
10
+ /** A stop as written: a colour, optionally pinned to a position 0..1 along the axis. */
11
+ export type StopInput = ColorInput | {
12
+ color: ColorInput;
13
+ at: number;
14
+ };
15
+ export interface LinearGradientInput {
16
+ kind: "linear";
17
+ /** Direction in degrees, CSS convention: 0 = to the top, 90 = to the right (default 180, downwards). */
18
+ angle: number;
19
+ stops: StopInput[];
20
+ }
21
+ export interface RadialGradientInput {
22
+ kind: "radial";
23
+ /** Centre as a fraction of the box, `[0.5, 0.5]` being the middle (the default). */
24
+ center: [number, number];
25
+ /** Outer radius as a fraction of the box's larger side (default 0.5, i.e. it touches the edges). */
26
+ radius: number;
27
+ stops: StopInput[];
28
+ }
29
+ export type GradientInput = LinearGradientInput | RadialGradientInput;
30
+ export declare const isGradientInput: (v: unknown) => v is GradientInput;
31
+ /**
32
+ * A linear gradient. `linearGradient("#fff", "#000")` runs top to bottom; pass `{ angle }` for any
33
+ * other direction, and `{ color, at }` for a stop that is not evenly spaced.
34
+ */
35
+ export declare function linearGradient(...args: [...StopInput[]] | [{
36
+ angle?: number;
37
+ stops: StopInput[];
38
+ }]): LinearGradientInput;
39
+ /** A radial gradient, centred by default and reaching the edges. */
40
+ export declare function radialGradient(...args: [...StopInput[]] | [{
41
+ center?: [number, number];
42
+ radius?: number;
43
+ stops: StopInput[];
44
+ }]): RadialGradientInput;
45
+ /**
46
+ * Resolve a box-relative gradient against the box it paints, into the absolute page coordinates the
47
+ * IR wants. Called by the renderer, which is the first place the box's geometry is known.
48
+ *
49
+ * The angle follows CSS: 0 points to the top and it turns clockwise, so 90 goes to the right. The
50
+ * axis runs through the box centre and is scaled so it spans the box on that diagonal - which is why
51
+ * a 45-degree gradient reaches the corners rather than stopping short of them.
52
+ */
53
+ export declare function resolveGradient(g: GradientInput, x: number, y: number, width: number, height: number): Gradient;
@@ -0,0 +1,97 @@
1
+ import { toColor } from "./color.js";
2
+ export const isGradientInput = (v) => typeof v === "object" && v !== null && "kind" in v && "stops" in v;
3
+ /**
4
+ * A linear gradient. `linearGradient("#fff", "#000")` runs top to bottom; pass `{ angle }` for any
5
+ * other direction, and `{ color, at }` for a stop that is not evenly spaced.
6
+ */
7
+ export function linearGradient(...args) {
8
+ const first = args[0];
9
+ if (args.length === 1 && typeof first === "object" && first !== null && "stops" in first) {
10
+ return { kind: "linear", angle: first.angle ?? 180, stops: first.stops };
11
+ }
12
+ return { kind: "linear", angle: 180, stops: args };
13
+ }
14
+ /** A radial gradient, centred by default and reaching the edges. */
15
+ export function radialGradient(...args) {
16
+ const first = args[0];
17
+ if (args.length === 1 && typeof first === "object" && first !== null && "stops" in first) {
18
+ return {
19
+ kind: "radial",
20
+ center: first.center ?? [0.5, 0.5],
21
+ radius: first.radius ?? 0.5,
22
+ stops: first.stops,
23
+ };
24
+ }
25
+ return { kind: "radial", center: [0.5, 0.5], radius: 0.5, stops: args };
26
+ }
27
+ /**
28
+ * Spread the stops that carry no `at` evenly, first to last, the way CSS does - and check the pinned
29
+ * ones, because they end up in a PDF stitching function's `/Bounds`, which the format requires to be
30
+ * strictly increasing inside the domain. A bad offset there is not a wrong-looking gradient, it is a
31
+ * malformed file, so it is refused by name here rather than emitted.
32
+ */
33
+ function toStops(stops) {
34
+ if (stops.length < 2) {
35
+ throw new Error("A gradient needs at least two colour stops.");
36
+ }
37
+ const last = stops.length - 1;
38
+ const out = stops.map((s, i) => {
39
+ const pinned = typeof s === "object" && s !== null && "at" in s;
40
+ const at = pinned ? s.at : i / last;
41
+ if (!Number.isFinite(at) || at < 0 || at > 1) {
42
+ throw new Error(`Invalid gradient stop position ${at}: it must be a number between 0 and 1.`);
43
+ }
44
+ return {
45
+ offset: at,
46
+ color: toColor(pinned ? s.color : s),
47
+ };
48
+ });
49
+ for (let i = 1; i < out.length; i++) {
50
+ if (out[i].offset <= out[i - 1].offset) {
51
+ throw new Error(`Gradient stops must move forward: stop ${i} sits at ${out[i].offset}, which is not after ` +
52
+ `${out[i - 1].offset}. (Two stops at the SAME position would be a hard colour edge in CSS; ` +
53
+ `PDF cannot express that in one shading, so it is refused rather than drawn wrongly.)`);
54
+ }
55
+ }
56
+ // A pinned first or last stop would otherwise be IGNORED - the shading's domain is always 0..1 and
57
+ // only the INTERIOR offsets reach /Bounds. Carrying the edge colour outwards is what CSS does.
58
+ if (out[0].offset > 0)
59
+ out.unshift({ offset: 0, color: out[0].color });
60
+ if (out[out.length - 1].offset < 1)
61
+ out.push({ offset: 1, color: out[out.length - 1].color });
62
+ return out;
63
+ }
64
+ /**
65
+ * Resolve a box-relative gradient against the box it paints, into the absolute page coordinates the
66
+ * IR wants. Called by the renderer, which is the first place the box's geometry is known.
67
+ *
68
+ * The angle follows CSS: 0 points to the top and it turns clockwise, so 90 goes to the right. The
69
+ * axis runs through the box centre and is scaled so it spans the box on that diagonal - which is why
70
+ * a 45-degree gradient reaches the corners rather than stopping short of them.
71
+ */
72
+ export function resolveGradient(g, x, y, width, height) {
73
+ const stops = toStops(g.stops);
74
+ if (g.kind === "radial") {
75
+ const cx = x + g.center[0] * width;
76
+ const cy = y + g.center[1] * height;
77
+ const r = g.radius * Math.max(width, height);
78
+ return { type: "radial", x0: cx, y0: cy, r0: 0, x1: cx, y1: cy, r1: r, stops, extend: "pad" };
79
+ }
80
+ const rad = ((g.angle % 360) * Math.PI) / 180;
81
+ // CSS angles: 0 = up, clockwise. The engine lays out top-left down, so "up" is -y here.
82
+ const dx = Math.sin(rad);
83
+ const dy = -Math.cos(rad);
84
+ // Half the box's extent along the axis, so the line covers the whole box for any angle.
85
+ const half = (Math.abs(dx) * width + Math.abs(dy) * height) / 2;
86
+ const cx = x + width / 2;
87
+ const cy = y + height / 2;
88
+ return {
89
+ type: "linear",
90
+ x0: cx - dx * half,
91
+ y0: cy - dy * half,
92
+ x1: cx + dx * half,
93
+ y1: cy + dy * half,
94
+ stops,
95
+ extend: "pad",
96
+ };
97
+ }
@@ -1,8 +1,13 @@
1
- export * from "./color";
2
- export * from "./insets";
3
- export * from "./text";
4
- export * from "./layout";
5
- export * from "./content";
6
- export * from "./structure";
7
- export * from "./table";
8
- export * from "./descriptor";
1
+ export * from "./color.js";
2
+ export * from "./insets.js";
3
+ export * from "./gradient.js";
4
+ export * from "./font-url.js";
5
+ export * from "./dimension.js";
6
+ export * from "./text.js";
7
+ export * from "./layout.js";
8
+ export * from "./content.js";
9
+ export * from "./page-builder.js";
10
+ export * from "./structure.js";
11
+ export * from "./table.js";
12
+ export * from "./forms.js";
13
+ export * from "./descriptor.js";
package/dist/api/index.js CHANGED
@@ -1,27 +1,16 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
1
  // The intuitive API layer: declarative factory functions + input normalizers that compile
18
2
  // down to the core engine elements. A thin, curated surface ON TOP of the engine - the
19
3
  // core classes stay untouched and remain exported for power users.
20
- __exportStar(require("./color"), exports);
21
- __exportStar(require("./insets"), exports);
22
- __exportStar(require("./text"), exports);
23
- __exportStar(require("./layout"), exports);
24
- __exportStar(require("./content"), exports);
25
- __exportStar(require("./structure"), exports);
26
- __exportStar(require("./table"), exports);
27
- __exportStar(require("./descriptor"), exports);
4
+ export * from "./color.js";
5
+ export * from "./insets.js";
6
+ export * from "./gradient.js";
7
+ export * from "./font-url.js";
8
+ export * from "./dimension.js";
9
+ export * from "./text.js";
10
+ export * from "./layout.js";
11
+ export * from "./content.js";
12
+ export * from "./page-builder.js";
13
+ export * from "./structure.js";
14
+ export * from "./table.js";
15
+ export * from "./forms.js";
16
+ export * from "./descriptor.js";
@@ -1,16 +1,23 @@
1
+ import { SizeInput } from "./dimension.js";
2
+ import type { EdgeSpecs } from "../layout/insets.js";
1
3
  /**
2
- * Spacing input for padding / margin (locked design §3). Units are PDF points. Every form
3
- * normalizes to the engine's `[top, right, bottom, left]` via `toEdges`, so you can reach
4
+ * Spacing input for padding / margin (locked design §3). Points, or a percentage string like `"5%"`.
5
+ * Every form normalizes to the engine's `[top, right, bottom, left]` via `toEdges`, so you can reach
4
6
  * for whichever shape fits and never think about the engine order.
7
+ *
8
+ * **A percentage resolves against the available WIDTH - on all four sides, top and bottom included.**
9
+ * That is the CSS rule, and Yoga's, so react-pdf behaves the same. It reads as wrong the first time and
10
+ * is what makes `padding-bottom: 56.25%` a 16:9 box on the web. A percentage needs a bounded width; in
11
+ * an unbounded region it resolves to 0, the same no-op a percentage SIZE gives there.
5
12
  */
6
- export type Insets = number | {
7
- x?: number;
8
- y?: number;
13
+ export type Insets = SizeInput | {
14
+ x?: SizeInput;
15
+ y?: SizeInput;
9
16
  } | {
10
- top?: number;
11
- right?: number;
12
- bottom?: number;
13
- left?: number;
14
- } | [number, number, number, number];
15
- /** Normalizes any `Insets` to the engine's `[top, right, bottom, left]`. */
16
- export declare function toEdges(i: Insets): [number, number, number, number];
17
+ top?: SizeInput;
18
+ right?: SizeInput;
19
+ bottom?: SizeInput;
20
+ left?: SizeInput;
21
+ } | [SizeInput, SizeInput, SizeInput, SizeInput];
22
+ /** Normalizes any `Insets` to the engine's `[top, right, bottom, left]`, percentages still unresolved. */
23
+ export declare function toEdges(i: Insets): EdgeSpecs;
@@ -1,21 +1,28 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toEdges = toEdges;
4
- /** Normalizes any `Insets` to the engine's `[top, right, bottom, left]`. */
5
- function toEdges(i) {
6
- var _a, _b, _c, _d, _e, _f;
7
- if (typeof i === "number")
8
- return [i, i, i, i];
1
+ import { toDimension } from "./dimension.js";
2
+ // A fixed side stays a plain NUMBER, so the output is unchanged for every input that was legal before
3
+ // this file learned percentages - `toEdges` is publicly exported and did not need to break.
4
+ const spec = (v) => {
5
+ if (v === undefined)
6
+ return 0;
7
+ const d = toDimension(v);
8
+ return d.points ?? { factor: d.factor };
9
+ };
10
+ /** Normalizes any `Insets` to the engine's `[top, right, bottom, left]`, percentages still unresolved. */
11
+ export function toEdges(i) {
12
+ if (typeof i === "number" || typeof i === "string") {
13
+ const s = spec(i);
14
+ return [s, s, s, s];
15
+ }
9
16
  if (Array.isArray(i))
10
- return i;
17
+ return [spec(i[0]), spec(i[1]), spec(i[2]), spec(i[3])];
11
18
  // Axis form ({x, y}) and per-side form ({top,...}) are both all-optional objects (TS
12
19
  // can't discriminate them), so read through one shape: an axis key present picks the
13
20
  // axis interpretation (an empty object is all-zero either way).
14
21
  const o = i;
15
22
  if (o.x !== undefined || o.y !== undefined) {
16
- const x = (_a = o.x) !== null && _a !== void 0 ? _a : 0;
17
- const y = (_b = o.y) !== null && _b !== void 0 ? _b : 0;
23
+ const x = spec(o.x);
24
+ const y = spec(o.y);
18
25
  return [y, x, y, x];
19
26
  }
20
- return [(_c = o.top) !== null && _c !== void 0 ? _c : 0, (_d = o.right) !== null && _d !== void 0 ? _d : 0, (_e = o.bottom) !== null && _e !== void 0 ? _e : 0, (_f = o.left) !== null && _f !== void 0 ? _f : 0];
27
+ return [spec(o.top), spec(o.right), spec(o.bottom), spec(o.left)];
21
28
  }