@useprint/preview 0.1.1 → 0.1.2

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 (228) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +5 -5
  3. package/.next/diagnostics/framework.json +1 -1
  4. package/.next/images-manifest.json +1 -0
  5. package/.next/next-minimal-server.js.nft.json +1 -1
  6. package/.next/next-server.js.nft.json +1 -1
  7. package/.next/prerender-manifest.json +3 -5
  8. package/.next/required-server-files.js +324 -0
  9. package/.next/required-server-files.json +11 -8
  10. package/.next/routes-manifest.json +1 -1
  11. package/.next/server/app/_global-error/page.js +3 -3
  12. package/.next/server/app/_global-error/page.js.nft.json +1 -1
  13. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  14. package/.next/server/app/_global-error.html +2 -2
  15. package/.next/server/app/_global-error.meta +2 -1
  16. package/.next/server/app/_global-error.rsc +2 -3
  17. package/.next/server/app/_global-error.segments/_full.segment.rsc +2 -3
  18. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  19. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  20. package/.next/server/app/_global-error.segments/_head.segment.rsc +5 -0
  21. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  22. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -8
  23. package/.next/server/app/_not-found/page.js +2 -2
  24. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  25. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  26. package/.next/server/app/favicon.ico/route.js +1 -1
  27. package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
  28. package/.next/server/app/favicon.ico.body +0 -0
  29. package/.next/server/app/page.js +2 -2
  30. package/.next/server/app/page.js.nft.json +1 -1
  31. package/.next/server/app/page_client-reference-manifest.js +1 -1
  32. package/.next/server/app/preview/[...slug]/page.js +102 -219
  33. package/.next/server/app/preview/[...slug]/page.js.nft.json +1 -1
  34. package/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +1 -1
  35. package/.next/server/chunks/337.js +3 -0
  36. package/.next/server/chunks/377.js +1 -0
  37. package/.next/server/chunks/445.js +22 -0
  38. package/.next/server/chunks/471.js +13 -0
  39. package/.next/server/chunks/820.js +1 -0
  40. package/.next/server/chunks/95.js +4 -4
  41. package/.next/server/chunks/static/media/pdf.worker.min.3327dba1.mjs +8 -0
  42. package/.next/server/middleware-build-manifest.js +1 -1
  43. package/.next/server/next-font-manifest.js +1 -1
  44. package/.next/server/next-font-manifest.json +1 -1
  45. package/.next/server/pages/500.html +2 -2
  46. package/.next/server/server-reference-manifest.js +1 -1
  47. package/.next/server/server-reference-manifest.json +1 -1
  48. package/.next/server/webpack-runtime.js +1 -1
  49. package/.next/static/chunks/134-e1901aa4c8d7c5e4.js +1 -0
  50. package/.next/static/chunks/399-119d2a8d117d3501.js +1 -0
  51. package/.next/static/chunks/4bd1b696-096d35a2bd1da3af.js +1 -0
  52. package/.next/static/chunks/576-c76dd52ea4e7fe70.js +1 -0
  53. package/.next/static/chunks/794-96cfa93198fb4e82.js +2 -0
  54. package/.next/static/chunks/818-09ed5fa3e6aa2cec.js +9 -0
  55. package/.next/static/chunks/aad4249a-49e9609864e9e734.js +2 -0
  56. package/.next/static/chunks/app/layout-7711ba9e6b7bcccc.js +1 -0
  57. package/.next/static/chunks/app/preview/[...slug]/page-2ce7c5eb36e7cd8b.js +1 -0
  58. package/.next/static/chunks/{c828b8b5-6f56633e9da941cb.js → c828b8b5-fe0be434537dde60.js} +2 -2
  59. package/.next/static/chunks/framework-2d4b35820b5e3e1e.js +1 -0
  60. package/.next/static/chunks/main-d2bae8996dc5307c.js +5 -0
  61. package/.next/static/chunks/{webpack-b8e17eaab329ee72.js → webpack-96cba10d3fe872ec.js} +1 -1
  62. package/.next/static/css/30dcbab3549c2dfe.css +4 -0
  63. package/.next/static/media/inter-cyrillic-400-normal.372704ff.woff2 +0 -0
  64. package/.next/static/media/inter-cyrillic-400-normal.a6b6ef6f.woff +0 -0
  65. package/.next/static/media/inter-cyrillic-500-normal.7c15bba8.woff2 +0 -0
  66. package/.next/static/media/inter-cyrillic-500-normal.b9f8c929.woff +0 -0
  67. package/.next/static/media/inter-cyrillic-600-normal.2f42892a.woff2 +0 -0
  68. package/.next/static/media/inter-cyrillic-600-normal.c3987adc.woff +0 -0
  69. package/.next/static/media/inter-cyrillic-700-normal.93eba3c3.woff +0 -0
  70. package/.next/static/media/inter-cyrillic-700-normal.e9e5b2dc.woff2 +0 -0
  71. package/.next/static/media/inter-cyrillic-ext-400-normal.2a31c04b.woff +0 -0
  72. package/.next/static/media/inter-cyrillic-ext-400-normal.f572b170.woff2 +0 -0
  73. package/.next/static/media/inter-cyrillic-ext-500-normal.5a6bb1da.woff +0 -0
  74. package/.next/static/media/inter-cyrillic-ext-500-normal.fe0d9b14.woff2 +0 -0
  75. package/.next/static/media/inter-cyrillic-ext-600-normal.ecbdecad.woff +0 -0
  76. package/.next/static/media/inter-cyrillic-ext-600-normal.f7b3c15b.woff2 +0 -0
  77. package/.next/static/media/inter-cyrillic-ext-700-normal.4b4022a6.woff +0 -0
  78. package/.next/static/media/inter-cyrillic-ext-700-normal.74b516d2.woff2 +0 -0
  79. package/.next/static/media/inter-greek-400-normal.cc58c11b.woff +0 -0
  80. package/.next/static/media/inter-greek-400-normal.d7020e3c.woff2 +0 -0
  81. package/.next/static/media/inter-greek-500-normal.d9a33207.woff +0 -0
  82. package/.next/static/media/inter-greek-500-normal.f41f43db.woff2 +0 -0
  83. package/.next/static/media/inter-greek-600-normal.4ec0c1c1.woff +0 -0
  84. package/.next/static/media/inter-greek-600-normal.cc532937.woff2 +0 -0
  85. package/.next/static/media/inter-greek-700-normal.5ec6c758.woff +0 -0
  86. package/.next/static/media/inter-greek-700-normal.97f0eeeb.woff2 +0 -0
  87. package/.next/static/media/inter-greek-ext-400-normal.4ce1df5d.woff2 +0 -0
  88. package/.next/static/media/inter-greek-ext-400-normal.88ede1ea.woff +0 -0
  89. package/.next/static/media/inter-greek-ext-500-normal.7a4aa726.woff +0 -0
  90. package/.next/static/media/inter-greek-ext-500-normal.cbd51e2d.woff2 +0 -0
  91. package/.next/static/media/inter-greek-ext-600-normal.089a95ee.woff +0 -0
  92. package/.next/static/media/inter-greek-ext-600-normal.1f33d317.woff2 +0 -0
  93. package/.next/static/media/inter-greek-ext-700-normal.31f1075d.woff +0 -0
  94. package/.next/static/media/inter-greek-ext-700-normal.827cd618.woff2 +0 -0
  95. package/.next/static/media/inter-latin-400-normal.2c7a775c.woff +0 -0
  96. package/.next/static/media/inter-latin-400-normal.ef6d3f52.woff2 +0 -0
  97. package/.next/static/media/inter-latin-500-normal.b7b43ace.woff2 +0 -0
  98. package/.next/static/media/inter-latin-500-normal.cb4c8ceb.woff +0 -0
  99. package/.next/static/media/inter-latin-600-normal.8fb1a964.woff2 +0 -0
  100. package/.next/static/media/inter-latin-600-normal.ce0f5f43.woff +0 -0
  101. package/.next/static/media/inter-latin-700-normal.953b7aa5.woff2 +0 -0
  102. package/.next/static/media/inter-latin-700-normal.9c21d4dc.woff +0 -0
  103. package/.next/static/media/inter-latin-ext-400-normal.32a25442.woff2 +0 -0
  104. package/.next/static/media/inter-latin-ext-400-normal.4edcaace.woff +0 -0
  105. package/.next/static/media/inter-latin-ext-500-normal.a19a84a6.woff +0 -0
  106. package/.next/static/media/inter-latin-ext-500-normal.d9b491de.woff2 +0 -0
  107. package/.next/static/media/inter-latin-ext-600-normal.38b075d8.woff2 +0 -0
  108. package/.next/static/media/inter-latin-ext-600-normal.49faa47a.woff +0 -0
  109. package/.next/static/media/inter-latin-ext-700-normal.93534b50.woff +0 -0
  110. package/.next/static/media/inter-latin-ext-700-normal.b63daa1a.woff2 +0 -0
  111. package/.next/static/media/inter-vietnamese-400-normal.a9dd2faf.woff +0 -0
  112. package/.next/static/media/inter-vietnamese-400-normal.de4fc44f.woff2 +0 -0
  113. package/.next/static/media/inter-vietnamese-500-normal.7c0a695f.woff2 +0 -0
  114. package/.next/static/media/inter-vietnamese-500-normal.a3a73b95.woff +0 -0
  115. package/.next/static/media/inter-vietnamese-600-normal.9d518599.woff2 +0 -0
  116. package/.next/static/media/inter-vietnamese-600-normal.c5ce3fcb.woff +0 -0
  117. package/.next/static/media/inter-vietnamese-700-normal.bc68b199.woff +0 -0
  118. package/.next/static/media/inter-vietnamese-700-normal.faf12809.woff2 +0 -0
  119. package/.next/static/media/pdf.worker.min.67f75a11.mjs +8 -0
  120. package/.next/trace +32 -32
  121. package/.next/trace-build +1 -1
  122. package/CHANGELOG.md +9 -0
  123. package/next.config.js +5 -1
  124. package/package.json +2 -3
  125. package/public/apple-touch-icon.png +0 -0
  126. package/public/favicon-96x96.png +0 -0
  127. package/public/favicon.ico +0 -0
  128. package/public/favicon.svg +3 -0
  129. package/public/site.webmanifest +21 -0
  130. package/public/web-app-manifest-192x192.png +0 -0
  131. package/public/web-app-manifest-512x512.png +0 -0
  132. package/readme.md +9 -27
  133. package/scripts/utils/default-seed/contracts/project-proposal.tsx +68 -0
  134. package/scripts/utils/default-seed/finance/payment-summary.tsx +55 -0
  135. package/scripts/utils/default-seed/reports/incident-report.tsx +49 -0
  136. package/scripts/utils/default-seed/updates/release-notes.tsx +58 -0
  137. package/src/actions/generate-pdf-from-html.ts +0 -8
  138. package/src/actions/render-document-by-path.tsx +0 -3
  139. package/src/app/favicon.ico +0 -0
  140. package/src/app/fonts.ts +0 -7
  141. package/src/app/globals.css +9 -0
  142. package/src/app/layout.tsx +13 -8
  143. package/src/app/page.tsx +14 -12
  144. package/src/app/preview/[...slug]/page.tsx +9 -61
  145. package/src/app/preview/[...slug]/preview.tsx +5 -6
  146. package/src/components/logo.tsx +21 -13
  147. package/src/components/pdf-viewer.tsx +61 -20
  148. package/src/components/print.tsx +37 -5
  149. package/src/components/shell.tsx +1 -2
  150. package/src/utils/__snapshots__/get-document-component.spec.ts.snap +25 -181
  151. package/src/utils/canidocument/ast/get-object-variables.ts +1 -1
  152. package/src/utils/canidocument/ast/get-used-style-properties.ts +1 -1
  153. package/src/utils/canidocument/get-compatibility-stats-for-entry.ts +1 -1
  154. package/src/utils/canidocument/tailwind/get-tailwind-config.ts +1 -1
  155. package/src/utils/canidocument/tailwind/get-tailwind-metadata.spec.ts +2 -2
  156. package/src/utils/canidocument/tailwind/get-tailwind-metadata.ts +1 -1
  157. package/src/utils/canidocument/types.ts +12 -0
  158. package/src/utils/contains-document-template.spec.ts +1 -1
  159. package/src/utils/esbuild/renderring-utilities-exporter.ts +248 -0
  160. package/src/utils/get-document-component.spec.ts +6 -4
  161. package/src/utils/get-document-component.ts +61 -10
  162. package/src/utils/get-documents-directory-metadata.spec.ts +18 -55
  163. package/src/utils/iframe-processing.spec.ts +13 -25
  164. package/src/utils/js-document-detection.spec.ts +11 -5
  165. package/src/utils/linting.ts +29 -33
  166. package/src/utils/margin-calculation.spec.ts +5 -5
  167. package/src/utils/testing/js-document-export-default.js +3 -0
  168. package/src/utils/testing/js-document-test.js +3 -0
  169. package/src/utils/testing/mdx-document-test.js +3 -0
  170. package/src/utils/testing/request-response-document.tsx +15 -0
  171. package/.next/server/chunks/134.js +0 -22
  172. package/.next/server/chunks/286.js +0 -27
  173. package/.next/server/chunks/489.js +0 -13
  174. package/.next/server/chunks/731.js +0 -1
  175. package/.next/server/chunks/static/media/pdf.worker.min.3fa7f4f1.mjs +0 -8
  176. package/.next/static/chunks/134-488429db271f07ce.js +0 -1
  177. package/.next/static/chunks/399-38210d4b480adc3a.js +0 -1
  178. package/.next/static/chunks/4bd1b696-f2999b4e17b2fd5f.js +0 -1
  179. package/.next/static/chunks/576-d2a7761fb68a178e.js +0 -1
  180. package/.next/static/chunks/794-de04f3efd45c53dd.js +0 -20
  181. package/.next/static/chunks/818-708fabc8a2438ba2.js +0 -9
  182. package/.next/static/chunks/aad4249a-8397af6f169152d5.js +0 -2
  183. package/.next/static/chunks/app/layout-38d6d79a819ab362.js +0 -1
  184. package/.next/static/chunks/app/preview/[...slug]/page-1097b557142aa22c.js +0 -1
  185. package/.next/static/chunks/framework-9fb1a057e8adf51d.js +0 -1
  186. package/.next/static/chunks/main-66c819c51fec57bf.js +0 -23
  187. package/.next/static/css/2f4a632dc94d1fb7.css +0 -3
  188. package/.next/static/media/19cfc7226ec3afaa-s.woff2 +0 -0
  189. package/.next/static/media/21350d82a1f187e9-s.woff2 +0 -0
  190. package/.next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
  191. package/.next/static/media/ba9851c3c22cd980-s.woff2 +0 -0
  192. package/.next/static/media/c5fe6dc8356a8c31-s.woff2 +0 -0
  193. package/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
  194. package/.next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
  195. package/.next/static/media/pdf.worker.min.539a26ca.mjs +0 -8
  196. package/.next/types/app/layout.ts +0 -86
  197. package/.next/types/cache-life.d.ts +0 -145
  198. package/scripts/utils/default-seed/auth/account-confirmation.tsx +0 -68
  199. package/scripts/utils/default-seed/auth/forgot-password.tsx +0 -71
  200. package/scripts/utils/default-seed/communications/payment-overdue.tsx +0 -82
  201. package/scripts/utils/default-seed/communications/team-invite.tsx +0 -78
  202. package/scripts/utils/default-seed/communications/webhooks-failed.tsx +0 -89
  203. package/scripts/utils/default-seed/feedback-request.tsx +0 -78
  204. package/scripts/utils/default-seed/marketing/changelog.tsx +0 -98
  205. package/src/actions/document-validation/__snapshots__/check-images.spec.tsx.snap +0 -84
  206. package/src/actions/document-validation/canidocument-data.ts +0 -85993
  207. package/src/actions/document-validation/check-compatibility.ts +0 -333
  208. package/src/actions/document-validation/check-images.spec.tsx +0 -21
  209. package/src/actions/document-validation/check-images.ts +0 -160
  210. package/src/actions/document-validation/check-links.spec.tsx +0 -113
  211. package/src/actions/document-validation/check-links.ts +0 -113
  212. package/src/actions/document-validation/get-code-location-from-ast-element.ts +0 -18
  213. package/src/actions/document-validation/quick-fetch.ts +0 -14
  214. package/src/animated-icons-data/help.json +0 -1082
  215. package/src/animated-icons-data/link.json +0 -1309
  216. package/src/animated-icons-data/mail.json +0 -1320
  217. package/src/components/toolbar/checking-results.tsx +0 -150
  218. package/src/components/toolbar/code-preview-line-link.tsx +0 -39
  219. package/src/components/toolbar/compatibility.tsx +0 -113
  220. package/src/components/toolbar/linter.tsx +0 -278
  221. package/src/components/toolbar/results-table.tsx +0 -0
  222. package/src/components/toolbar/results.tsx +0 -52
  223. package/src/components/toolbar/spam-assassin.tsx +0 -153
  224. package/src/components/toolbar/toolbar-button.tsx +0 -52
  225. package/src/components/toolbar/use-cached-state.ts +0 -33
  226. package/src/components/toolbar.tsx +0 -349
  227. /package/.next/static/{ZCqBZ8ZswPjX7K5Zalrpy → dBOUMD9vJ2VLASRDl2YeR}/_buildManifest.js +0 -0
  228. /package/.next/static/{ZCqBZ8ZswPjX7K5Zalrpy → dBOUMD9vJ2VLASRDl2YeR}/_ssgManifest.js +0 -0
@@ -2,20 +2,13 @@ import path from "node:path";
2
2
  import type { PAGE_SIZES } from "@useprint/shared";
3
3
  import { redirect } from "next/navigation";
4
4
  import { Suspense } from "react";
5
- import {
6
- type CompatibilityCheckingResult,
7
- checkCompatibility,
8
- } from "../../../actions/document-validation/check-compatibility";
9
5
  import { getDocumentPathFromSlug } from "../../../actions/get-document-path-from-slug";
10
6
  import { renderDocumentByPath } from "../../../actions/render-document-by-path";
11
7
  import { Shell } from "../../../components/shell";
12
- import type { LintingRow } from "../../../components/toolbar/linter";
13
8
 
14
9
  import { PreviewProvider } from "../../../contexts/preview";
15
10
  import { getDocumentsDirectoryMetadata } from "../../../utils/get-documents-directory-metadata";
16
- import { getLintingSources, loadLintingRowsFrom } from "../../../utils/linting";
17
- import { loadStream } from "../../../utils/load-stream";
18
- import { documentsDirectoryAbsolutePath, isBuilding } from "../../env";
11
+ import { documentsDirectoryAbsolutePath } from "../../env";
19
12
  import Preview from "./preview";
20
13
 
21
14
  export const dynamicParams = true;
@@ -35,7 +28,6 @@ const Page = async ({
35
28
  }) => {
36
29
  const params = await paramsPromise;
37
30
  const searchParams = await searchParamsPromise;
38
- console.log("searchParams", searchParams);
39
31
  // will come in here as segments of a relative path to the document
40
32
  // ex: ['authentication', 'verify-password.tsx']
41
33
  const slug = decodeURIComponent(params.slug.join("/"));
@@ -73,44 +65,6 @@ This is most likely not an issue with the preview server. Maybe there was a typo
73
65
  pageSize,
74
66
  isLandscape,
75
67
  );
76
- let lintingRows: LintingRow[] | undefined;
77
- let compatibilityCheckingResults: CompatibilityCheckingResult[] | undefined;
78
-
79
- if (isBuilding) {
80
- if ("error" in serverDocumentRenderingResult) {
81
- throw new Error(serverDocumentRenderingResult.error.message, {
82
- cause: serverDocumentRenderingResult.error,
83
- });
84
- }
85
- const lintingSources = getLintingSources(
86
- serverDocumentRenderingResult.markup,
87
- "",
88
- );
89
- lintingRows = [];
90
- for await (const row of loadLintingRowsFrom(lintingSources)) {
91
- lintingRows.push(row);
92
- }
93
- lintingRows.sort((a, b) => {
94
- if (a.result.status === "error" && b.result.status === "warning") {
95
- return -1;
96
- }
97
-
98
- if (a.result.status === "warning" && b.result.status === "error") {
99
- return 1;
100
- }
101
-
102
- return 0;
103
- });
104
- compatibilityCheckingResults = [];
105
- for await (const result of loadStream(
106
- await checkCompatibility(
107
- serverDocumentRenderingResult.reactMarkup,
108
- documentPath,
109
- ),
110
- )) {
111
- compatibilityCheckingResults.push(result);
112
- }
113
- }
114
68
 
115
69
  return (
116
70
  <PreviewProvider
@@ -125,20 +79,14 @@ This is most likely not an issue with the preview server. Maybe there was a typo
125
79
  {/* This suspense is so that this page doesn't throw warnings */}
126
80
  {/* on the build of the preview server de-opting into */}
127
81
  {/* client-side rendering on build */}
128
- <Suspense>
129
- <Preview
130
- documentTitle={path.basename(documentPath)}
131
- pageSize={pageSize || "A4"}
132
- />
133
-
134
- {/* <Toolbar
135
- serverLintingRows={lintingRows}
136
- serverSpamCheckingResult={spamCheckingResult}
137
- serverCompatibilityResults={compatibilityCheckingResults}
138
- /> */}
139
- </Suspense>
140
- </Shell>
141
- </PreviewProvider>
82
+ <Suspense>
83
+ <Preview
84
+ documentTitle={path.basename(documentPath)}
85
+ pageSize={pageSize || "A4"}
86
+ />
87
+ </Suspense>
88
+ </Shell>
89
+ </PreviewProvider>
142
90
  );
143
91
  };
144
92
 
@@ -11,7 +11,6 @@ import { CodeContainer } from "../../../components/code-container";
11
11
  import { PdfViewer } from "../../../components/pdf-viewer";
12
12
  import { Print } from "../../../components/print";
13
13
 
14
- import { useToolbarState } from "../../../components/toolbar";
15
14
  import { Tooltip } from "../../../components/tooltip";
16
15
  import { ActiveViewToggleGroup } from "../../../components/topbar/active-view-toggle-group";
17
16
  import { LandscapeToggle } from "../../../components/topbar/landscape-toggle";
@@ -109,15 +108,14 @@ const Preview = ({
109
108
  router.push(`${pathname}?${params.toString()}${location.hash}`);
110
109
  }, 300);
111
110
 
112
- const { toggled: toolbarToggled } = useToolbarState();
113
111
  const effectiveDimensions = isLandscape
114
112
  ? { width: currentPreset.dimensions.height, height: currentPreset.dimensions.width }
115
113
  : currentPreset.dimensions;
116
- console.log(effectiveDimensions)
117
114
  return (
118
115
  <>
119
116
  <PrintPreview documentTitle={documentTitle} />
120
117
 
118
+ <div className="flex min-h-0 flex-1 flex-col">
121
119
  <Topbar documentTitle={documentTitle} className="print:hidden">
122
120
  <ViewSizeControls
123
121
  setViewHeight={(height) => {
@@ -160,13 +158,12 @@ const Preview = ({
160
158
  <div
161
159
  {...props}
162
160
  className={cn(
163
- "h-[calc(100%-3.5rem-2.375rem)] will-change-[height] flex transition-[height] duration-300",
161
+ "min-h-0 flex-1 will-change-[height] flex transition-[height] duration-300",
164
162
  activeView === "preview" && "bg-gray-200",
165
163
  activeView === "preview" &&
166
164
  renderedDocumentMetadata?.pdfData &&
167
- "p-0",
165
+ "flex-col overflow-hidden p-0",
168
166
  activeView !== "preview" && "p-4 overflow-auto",
169
- toolbarToggled && "h-[calc(100%-3.5rem-13rem)]",
170
167
  className,
171
168
  )}
172
169
  ref={(element) => {
@@ -195,6 +192,7 @@ const Preview = ({
195
192
  renderedDocumentMetadata.pdfData &&
196
193
  PdfViewer && (
197
194
  <PdfViewer
195
+ className="min-h-0 min-w-0 flex-1"
198
196
  pdfData={renderedDocumentMetadata.pdfData}
199
197
  width={effectiveDimensions.width}
200
198
  height={effectiveDimensions.height}
@@ -236,6 +234,7 @@ const Preview = ({
236
234
 
237
235
  <Toaster />
238
236
  </div>
237
+ </div>
239
238
  </>
240
239
  );
241
240
  };
@@ -3,17 +3,25 @@ import * as React from "react";
3
3
  import logo from "../app/logo.png";
4
4
 
5
5
  export const Logo = () => {
6
- return (
7
- <div className="flex flex-col items-start justify-center py-4 px-6">
8
- <span className="flex flex-row items-center gap-2 text-white">
9
-
10
- <svg width="24" height="24" viewBox="0 0 1000 1043" fill="none" xmlns="http://www.w3.org/2000/svg">
11
- <rect width="1000" height="1042.55"/>
12
- <path d="M276.594 425.53V177.303M702.126 425.53V177.303M843.97 744.679V425.53M134.75 744.679V425.53M276.594 886.523V602.835M702.126 886.523V602.835" stroke="white" stroke-width="70.922"/>
13
- </svg>
14
- useprint.dev
15
-
16
- </span>
17
- </div>
18
- );
6
+ return (
7
+ <div className="flex flex-col items-start justify-center py-4 px-6">
8
+ <span className="flex flex-row items-center gap-2 text-white">
9
+ <svg
10
+ width="24"
11
+ height="24"
12
+ viewBox="0 0 1000 1043"
13
+ fill="none"
14
+ xmlns="http://www.w3.org/2000/svg"
15
+ >
16
+ <rect width="1000" height="1042.55" />
17
+ <path
18
+ d="M276.594 425.53V177.303M702.126 425.53V177.303M843.97 744.679V425.53M134.75 744.679V425.53M276.594 886.523V602.835M702.126 886.523V602.835"
19
+ stroke="white"
20
+ strokeWidth="70.922"
21
+ />
22
+ </svg>
23
+ usePrint
24
+ </span>
25
+ </div>
26
+ );
19
27
  };
@@ -2,6 +2,7 @@
2
2
  import type React from "react";
3
3
  import { useMemo, useState } from "react";
4
4
  import { Document, Page, pdfjs} from "react-pdf";
5
+ import { cn } from "../utils";
5
6
  import "react-pdf/dist/esm/Page/AnnotationLayer.css";
6
7
  import "react-pdf/dist/esm/Page/TextLayer.css";
7
8
  // Set up the worker for react-pdf (which uses pdfjs-dist under the hood)
@@ -16,20 +17,58 @@ pdfjs.GlobalWorkerOptions.workerSrc = new URL(
16
17
  import.meta.url,
17
18
  ).toString();
18
19
 
20
+ /** Letter height/width using the same mm proportions as PAGE_SIZES (279mm × 216mm). */
21
+ const DEFAULT_PAGE_ASPECT = 279 / 216;
22
+
23
+ function PdfPageSkeleton({
24
+ width,
25
+ height,
26
+ }: {
27
+ width: string | number;
28
+ height?: string | number;
29
+ }) {
30
+ const wNum = typeof width === "number" ? width : null;
31
+ const hNum =
32
+ typeof height === "number" && Number.isFinite(height) ? height : null;
33
+ const boxHeight =
34
+ hNum ?? (wNum != null ? Math.round(wNum * DEFAULT_PAGE_ASPECT) : null);
35
+
36
+ const style: React.CSSProperties = {};
37
+ if (wNum != null) {
38
+ style.width = wNum;
39
+ } else {
40
+ style.width = typeof width === "string" ? width : "100%";
41
+ }
42
+ if (boxHeight != null) {
43
+ style.height = boxHeight;
44
+ } else {
45
+ style.aspectRatio = `216 / 279`;
46
+ }
47
+
48
+ return (
49
+ <div
50
+ aria-busy="true"
51
+ aria-label="Loading PDF"
52
+ className="mb-6 shrink-0 animate-pulse rounded-sm bg-gray-300/80 shadow-sm ring-1 ring-black/5"
53
+ style={style}
54
+ />
55
+ );
56
+ }
57
+
19
58
  type PdfViewerProps = {
20
59
  pdfData: string; // base64 encoded PDF
21
60
  width?: string | number;
22
61
  height?: string | number;
23
- style?: React.CSSProperties;
24
62
  zoom?: number;
25
- };
63
+ } & Omit<React.ComponentProps<"div">, "children">;
26
64
 
27
65
  export const PdfViewer = ({
28
66
  pdfData,
29
67
  width = "100%",
30
68
  height,
31
69
  style,
32
- zoom: initialZoom,
70
+ zoom: _zoom,
71
+ className,
33
72
  ...props
34
73
  }: PdfViewerProps) => {
35
74
  const [numPages, setNumPages] = useState<number | null>(null);
@@ -47,40 +86,42 @@ export const PdfViewer = ({
47
86
  const pageWidth = typeof width === "number" ? width : undefined;
48
87
 
49
88
  return (
50
- <div className="flex flex-col h-full min-w-full" style={style} {...props}>
89
+ <div
90
+ className={cn("flex min-h-0 min-w-0 flex-1 flex-col", className)}
91
+ style={style}
92
+ {...props}
93
+ >
51
94
  <div
52
- className="flex-1 overflow-auto flex flex-col items-center px-4 min-w-full"
95
+ className="flex min-h-0 min-w-0 flex-1 flex-col items-center overflow-auto px-4 pb-12 pt-2"
53
96
  style={{
54
97
  width: typeof width === "string" ? width : "100%",
55
98
  }}
56
99
  >
57
- <div className="flex flex-col w-full items-center min-h-full justify-center py-12">
100
+ <div className="flex w-full flex-col items-center pt-10">
58
101
  {pdfFile && (
59
102
  <Document
60
-
61
103
  file={pdfFile}
62
104
  onLoadSuccess={onDocumentLoadSuccess}
63
- loading={<div className="text-center p-5">Loading PDF...</div>}
105
+ loading={<PdfPageSkeleton width={width} height={height} />}
64
106
  error={
65
107
  <div className="p-5 text-center text-red-500">
66
108
  Error loading PDF
67
109
  </div>
68
110
  }
69
- className="flex flex-col items-center w-full max-h-full"
111
+ className="flex w-full flex-col items-center"
70
112
  >
71
113
  {numPages &&
72
114
  Array.from({ length: numPages }, (_, i) => i + 1).map((pageNum) => (
73
- <Page
74
- pageNumber={pageNum}
75
- width={pageWidth}
76
- height={Number(height)}
77
- scale={1}
78
- // scale={scale}
79
- renderTextLayer
80
- renderAnnotationLayer
81
- className="mb-6"
82
- key={pageNum}
83
- />
115
+ <Page
116
+ pageNumber={pageNum}
117
+ width={pageWidth}
118
+ height={Number(height)}
119
+ scale={1}
120
+ renderTextLayer
121
+ renderAnnotationLayer
122
+ className="mb-6"
123
+ key={pageNum}
124
+ />
84
125
  ))}
85
126
  </Document>
86
127
  )}
@@ -1,20 +1,32 @@
1
+ "use client";
2
+
1
3
  import { PageSize } from "@useprint/shared";
2
4
  import type * as React from "react";
5
+ import { useCallback, useEffect } from "react";
3
6
  import { toast } from "sonner";
4
7
 
8
+ function isEditableElement(target: EventTarget | null): boolean {
9
+ if (!(target instanceof HTMLElement)) {
10
+ return false;
11
+ }
12
+ if (target.isContentEditable) {
13
+ return true;
14
+ }
15
+ const tag = target.tagName;
16
+ return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT";
17
+ }
18
+
5
19
  export const Print = ({ pdfData, options }: { pdfData?: string; options?: { pageSize?: PageSize["name"], landscape?: boolean } }) => {
6
- const onFormSubmit = async (e: React.FormEvent) => {
20
+ const triggerPrint = useCallback(async () => {
7
21
  if (typeof window === "undefined") {
8
22
  return;
9
23
  }
10
- e.preventDefault();
11
24
  if (!pdfData) {
12
25
  toast.error("No PDF data available to print!");
13
26
  return;
14
27
  }
15
28
 
16
29
  try {
17
- // Convert base64 to blob
18
30
  const binaryString = atob(pdfData);
19
31
  const bytes = new Uint8Array(binaryString.length);
20
32
  for (let i = 0; i < binaryString.length; i++) {
@@ -23,12 +35,10 @@ export const Print = ({ pdfData, options }: { pdfData?: string; options?: { page
23
35
  const blob = new Blob([bytes], { type: "application/pdf" });
24
36
  const url = URL.createObjectURL(blob);
25
37
 
26
- // Open PDF in new window and trigger print
27
38
  const printWindow = window.open(url, "_blank");
28
39
  if (printWindow) {
29
40
  printWindow.onload = () => {
30
41
  printWindow.print();
31
- // Clean up the URL after a delay to allow printing
32
42
  setTimeout(() => {
33
43
  URL.revokeObjectURL(url);
34
44
  }, 1000);
@@ -41,6 +51,28 @@ export const Print = ({ pdfData, options }: { pdfData?: string; options?: { page
41
51
  console.error("Error printing PDF:", error);
42
52
  toast.error("Failed to print PDF");
43
53
  }
54
+ }, [pdfData]);
55
+
56
+ useEffect(() => {
57
+ const onKeyDown = (e: KeyboardEvent) => {
58
+ const isPrintShortcut =
59
+ (e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "p";
60
+ if (!isPrintShortcut) {
61
+ return;
62
+ }
63
+ if (isEditableElement(e.target)) {
64
+ return;
65
+ }
66
+ e.preventDefault();
67
+ void triggerPrint();
68
+ };
69
+ window.addEventListener("keydown", onKeyDown);
70
+ return () => window.removeEventListener("keydown", onKeyDown);
71
+ }, [triggerPrint]);
72
+
73
+ const onFormSubmit = async (e: React.FormEvent) => {
74
+ e.preventDefault();
75
+ await triggerPrint();
44
76
  };
45
77
 
46
78
  return (
@@ -78,11 +78,10 @@ export const Shell = ({ children, currentDocumentOpenSlug }: ShellProps) => {
78
78
  </React.Suspense>
79
79
  <main
80
80
  className={cn(
81
- 'inline-block relative overflow-hidden will-change-[width]',
81
+ 'relative flex min-h-0 flex-1 flex-col overflow-hidden will-change-[width]',
82
82
  'w-full h-full',
83
83
  '[transition:width_0.2s_ease-in-out,_transform_0.2s_ease-in-out]',
84
84
  {
85
- 'lg:w-[calc(100%-16rem)]': sidebarToggled,
86
85
  'opacity-0 lg:opacity-100': !sidebarToggled,
87
86
  },
88
87
  )}
@@ -1,185 +1,29 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
3
  exports[`getDocumentComponent() > with a demo document template 1`] = `
4
- "<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
- <html dir="ltr" lang="en">
6
- <head>
7
- <link rel="preload" as="image" href="/static/vercel-logo.png" />
8
- <link rel="preload" as="image" href="/static/vercel-user.png" />
9
- <link rel="preload" as="image" href="/static/vercel-arrow.png" />
10
- <link rel="preload" as="image" href="/static/vercel-team.png" />
11
- <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
12
- <meta name="x-apple-disable-message-reformatting" />
13
- <!--$-->
14
- </head>
15
- <body
16
- style='margin-left:auto;margin-right:auto;margin-top:auto;margin-bottom:auto;background-color:rgb(255,255,255);padding-left:0.5rem;padding-right:0.5rem;font-family:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"'>
17
- <div
18
- style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0"
19
- data-skip-in-text="true">
20
- Join Alan on Vercel
21
- <div>
22
-  ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏ ‌​‍‎‏
23
- </div>
24
- </div>
25
- <table
26
- align="center"
27
- width="100%"
28
- border="0"
29
- cellpadding="0"
30
- cellspacing="0"
31
- role="presentation"
32
- style="margin-left:auto;margin-right:auto;margin-top:40px;margin-bottom:40px;max-width:465px;border-radius:0.25rem;border-width:1px;border-color:rgb(234,234,234);border-style:solid;padding:20px">
33
- <tbody>
34
- <tr style="width:100%">
35
- <td>
36
- <table
37
- align="center"
38
- width="100%"
39
- border="0"
40
- cellpadding="0"
41
- cellspacing="0"
42
- role="presentation"
43
- style="margin-top:32px">
44
- <tbody>
45
- <tr>
46
- <td>
47
- <img
48
- alt="Vercel Logo"
49
- height="37"
50
- src="/static/vercel-logo.png"
51
- style="margin-left:auto;margin-right:auto;margin-top:0px;margin-bottom:0px;display:block;outline:none;border:none;text-decoration:none"
52
- width="40" />
53
- </td>
54
- </tr>
55
- </tbody>
56
- </table>
57
- <h1
58
- style="margin-left:0px;margin-right:0px;margin-top:30px;margin-bottom:30px;padding:0px;text-align:center;font-weight:400;font-size:24px;color:rgb(0,0,0)">
59
- Join <strong>Enigma</strong> on <strong>Vercel</strong>
60
- </h1>
61
- <p
62
- style="font-size:14px;color:rgb(0,0,0);line-height:24px;margin-top:16px;margin-bottom:16px">
63
- Hello
64
- <!-- -->alanturing<!-- -->,
65
- </p>
66
- <p
67
- style="font-size:14px;color:rgb(0,0,0);line-height:24px;margin-top:16px;margin-bottom:16px">
68
- <strong>Alan</strong> (<a
69
- href="mailto:alan.turing@example.com"
70
- style="color:rgb(37,99,235);text-decoration-line:none"
71
- target="_blank"
72
- >alan.turing@example.com</a
73
- >) has invited you to the <strong>Enigma</strong> team on<!-- -->
74
- <strong>Vercel</strong>.
75
- </p>
76
- <table
77
- align="center"
78
- width="100%"
79
- border="0"
80
- cellpadding="0"
81
- cellspacing="0"
82
- role="presentation">
83
- <tbody>
84
- <tr>
85
- <td>
86
- <table
87
- align="center"
88
- width="100%"
89
- border="0"
90
- cellpadding="0"
91
- cellspacing="0"
92
- role="presentation">
93
- <tbody style="width:100%">
94
- <tr style="width:100%">
95
- <td align="right" data-id="__useprint-column">
96
- <img
97
- alt="alanturing&#x27;s profile picture"
98
- height="64"
99
- src="/static/vercel-user.png"
100
- style="border-radius:9999px;display:block;outline:none;border:none;text-decoration:none"
101
- width="64" />
102
- </td>
103
- <td align="center" data-id="__useprint-column">
104
- <img
105
- alt="Arrow indicating invitation"
106
- height="9"
107
- src="/static/vercel-arrow.png"
108
- style="display:block;outline:none;border:none;text-decoration:none"
109
- width="12" />
110
- </td>
111
- <td align="left" data-id="__useprint-column">
112
- <img
113
- alt="Enigma team logo"
114
- height="64"
115
- src="/static/vercel-team.png"
116
- style="border-radius:9999px;display:block;outline:none;border:none;text-decoration:none"
117
- width="64" />
118
- </td>
119
- </tr>
120
- </tbody>
121
- </table>
122
- </td>
123
- </tr>
124
- </tbody>
125
- </table>
126
- <table
127
- align="center"
128
- width="100%"
129
- border="0"
130
- cellpadding="0"
131
- cellspacing="0"
132
- role="presentation"
133
- style="margin-top:32px;margin-bottom:32px;text-align:center">
134
- <tbody>
135
- <tr>
136
- <td>
137
- <a
138
- href="https://vercel.com"
139
- style="border-radius:0.25rem;background-color:rgb(0,0,0);padding-left:20px;padding-right:20px;padding-top:12px;padding-bottom:12px;text-align:center;font-weight:600;font-size:12px;color:rgb(255,255,255);text-decoration-line:none;line-height:100%;text-decoration:none;display:inline-block;max-width:100%;mso-padding-alt:0px"
140
- target="_blank"
141
- ><span
142
- ><!--[if mso]><i style="mso-font-width:500%;mso-text-raise:18" hidden>&#8202;&#8202;</i><![endif]--></span
143
- ><span
144
- style="max-width:100%;display:inline-block;line-height:120%;mso-padding-alt:0px;mso-text-raise:9px"
145
- >Join the team</span
146
- ><span
147
- ><!--[if mso]><i style="mso-font-width:500%" hidden>&#8202;&#8202;&#8203;</i><![endif]--></span
148
- ></a
149
- >
150
- </td>
151
- </tr>
152
- </tbody>
153
- </table>
154
- <p
155
- style="font-size:14px;color:rgb(0,0,0);line-height:24px;margin-top:16px;margin-bottom:16px">
156
- or copy and paste this URL into your browser:<!-- -->
157
- <a
158
- href="https://vercel.com"
159
- style="color:rgb(37,99,235);text-decoration-line:none"
160
- target="_blank"
161
- >https://vercel.com</a
162
- >
163
- </p>
164
- <hr
165
- style="margin-left:0px;margin-right:0px;margin-top:26px;margin-bottom:26px;width:100%;border-width:1px;border-color:rgb(234,234,234);border-style:solid;border:none;border-top:1px solid #eaeaea" />
166
- <p
167
- style="color:rgb(102,102,102);font-size:12px;line-height:24px;margin-top:16px;margin-bottom:16px">
168
- This invitation was intended for<!-- -->
169
- <span style="color:rgb(0,0,0)">alanturing</span>. This invite was
170
- sent from <span style="color:rgb(0,0,0)">204.13.186.218</span>
171
- <!-- -->located in<!-- -->
172
- <span style="color:rgb(0,0,0)">São Paulo, Brazil</span>. If you
173
- were not expecting this invitation, you can ignore this document. If
174
- you are concerned about your account&#x27;s safety, please reply
175
- to this document to get in touch with us.
176
- </p>
177
- </td>
178
- </tr>
179
- </tbody>
180
- </table>
181
- <!--/$-->
182
- </body>
183
- </html>
184
- "
4
+ "<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html style="margin:0;padding:0" lang="en"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/><meta name="x-apple-disable-message-reformatting"/><!--$--><style>
5
+ html {
6
+ background-color: rgb(229 231 235);
7
+ }
8
+ @media print {
9
+ background-color: white;
10
+ }
11
+ div[title="end of content"] {
12
+ display: none !important;
13
+ }
14
+ </style></head><body style="background-color:#09090b;margin:0;padding:0"><div class="useprint-unbreakable useprint-page" style="background-color:rgb(9,9,11);padding-left:2.5rem;padding-right:2.5rem;padding-top:3rem;padding-bottom:3rem;color:rgb(250,250,250);break-inside:avoid;break-after:auto;break-before:auto;page-break-inside:avoid;width:794px;height:1123px" data-unbreakable="true"><p style="margin:0px;font-size:0.75rem;line-height:1rem;text-transform:uppercase;letter-spacing:0.3em;color:rgb(113,113,122)">Proposal ready</p><h1 style="margin-bottom:2rem;margin-top:0.75rem;text-align:center;font-size:34px;font-weight:600">Project proposal</h1><p>Hello <!-- -->Northwind Studio<!-- -->,</p><p>We prepared a printable proposal for <strong>Summer product launch</strong>. Use this version for review, approval, or export to PDF.</p><div style="border-radius:0.75rem;border-width:1px;border-color:rgb(39,39,42);background-color:rgb(24,24,27);padding-left:1.25rem;padding-right:1.25rem;padding-top:1rem;padding-bottom:1rem">A concise scope, timeline, and delivery plan for a multi-page printable proposal.</div><div style="margin-top:2rem;margin-bottom:2rem;text-align:center"><a href="https://useprint.dev/docs/getting-started/your-first-document" style="display:inline-block;border-radius:0.5rem;background-color:rgb(255,255,255);padding-left:1.25rem;padding-right:1.25rem;padding-top:0.75rem;padding-bottom:0.75rem;font-size:0.875rem;line-height:1.25rem;font-weight:500;color:rgb(9,9,11);text-decoration-line:none">Open proposal</a></div><p style="font-size:0.875rem;line-height:1.25rem;color:rgb(161,161,170)">Tip: this document is designed to preview well in the browser and render cleanly through Chromium-based PDF generation.</p></div><!--/$--></body></html>"
15
+ `;
16
+
17
+ exports[`getDocumentComponent() with a demo document template 1`] = `
18
+ "<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html style="margin:0;padding:0" lang="en"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/><meta name="x-apple-disable-message-reformatting"/><!--$--><style>
19
+ html {
20
+ background-color: rgb(229 231 235);
21
+ }
22
+ @media print {
23
+ background-color: white;
24
+ }
25
+ div[title="end of content"] {
26
+ display: none !important;
27
+ }
28
+ </style></head><body style="background-color:#09090b;margin:0;padding:0"><div class="useprint-unbreakable useprint-page" style="background-color:rgb(9,9,11);padding-left:2.5rem;padding-right:2.5rem;padding-top:3rem;padding-bottom:3rem;color:rgb(250,250,250);break-inside:avoid;break-after:auto;break-before:auto;page-break-inside:avoid;width:794px;height:1123px" data-unbreakable="true"><p style="margin:0px;font-size:0.75rem;line-height:1rem;text-transform:uppercase;letter-spacing:0.3em;color:rgb(113,113,122)">Proposal ready</p><h1 style="margin-bottom:2rem;margin-top:0.75rem;text-align:center;font-size:34px;font-weight:600">Project proposal</h1><p>Hello <!-- -->Northwind Studio<!-- -->,</p><p>We prepared a printable proposal for <strong>Summer product launch</strong>. Use this version for review, approval, or export to PDF.</p><div style="border-radius:0.75rem;border-width:1px;border-color:rgb(39,39,42);background-color:rgb(24,24,27);padding-left:1.25rem;padding-right:1.25rem;padding-top:1rem;padding-bottom:1rem">A concise scope, timeline, and delivery plan for a multi-page printable proposal.</div><div style="margin-top:2rem;margin-bottom:2rem;text-align:center"><a href="https://useprint.dev/docs/getting-started/your-first-document" style="display:inline-block;border-radius:0.5rem;background-color:rgb(255,255,255);padding-left:1.25rem;padding-right:1.25rem;padding-top:0.75rem;padding-bottom:0.75rem;font-size:0.875rem;line-height:1.25rem;font-weight:500;color:rgb(9,9,11);text-decoration-line:none">Open proposal</a></div><p style="font-size:0.875rem;line-height:1.25rem;color:rgb(161,161,170)">Tip: this document is designed to preview well in the browser and render cleanly through Chromium-based PDF generation.</p></div><!--/$--></body></html>"
185
29
  `;
@@ -1,6 +1,6 @@
1
1
  import type { Node } from '@babel/traverse';
2
2
  import traverse from '@babel/traverse';
3
- import type { AST } from '../../../actions/document-validation/check-compatibility';
3
+ import type { AST } from '../types';
4
4
 
5
5
  export interface Position {
6
6
  line: number;
@@ -1,6 +1,6 @@
1
1
  /** biome-ignore-all lint/nursery/noNestedComponentDefinitions: There are no components here, just visitor functions */
2
2
  import traverse from '@babel/traverse';
3
- import type { AST } from '../../../actions/document-validation/check-compatibility';
3
+ import type { AST } from '../types';
4
4
  import { generateTailwindCssRules } from '../tailwind/generate-tailwind-rules';
5
5
  import { getTailwindMetadata } from '../tailwind/get-tailwind-metadata';
6
6
  import type { ObjectVariables, SourceLocation } from './get-object-variables';