pdfx-cli 0.4.1 → 0.4.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.
package/dist/index.js CHANGED
@@ -2386,8 +2386,21 @@ async function getAuditChecklist() {
2386
2386
  \`\`\`
2387
2387
 
2388
2388
  ### "Invalid hook call"
2389
- PDFx components render to PDF, not to the DOM — React hooks are not supported inside them.
2390
- Move hook calls to the parent component and pass data down as props.
2389
+ \`@react-pdf/renderer\` renders synchronously. Hooks that depend on browser APIs or
2390
+ async side effects do not work in the PDF render path.
2391
+
2392
+ **Do NOT use inside a PDFx component:**
2393
+ - \`useEffect\` / \`useLayoutEffect\` — no browser lifecycle in PDF rendering
2394
+ - \`useRef\` for DOM nodes — no DOM exists in the PDF render tree
2395
+ - Any hook that calls browser globals (\`window\`, \`document\`, \`navigator\`)
2396
+
2397
+ **These ARE valid inside PDFx components:**
2398
+ - PDFx framework hooks: \`usePdfxTheme()\`, \`useSafeMemo()\`
2399
+ - Custom hooks that are pure functions with no browser-API dependencies
2400
+ - Data passed down as props from a parent client component
2401
+
2402
+ If you see this error in a wrapper component you wrote, move the browser hook
2403
+ to the nearest client component and pass the result down as a prop.
2391
2404
 
2392
2405
  ### "Text strings must be rendered inside \`<Text>\` component"
2393
2406
  Wrap all string literals in \`<Text>\` from \`@react-pdf/renderer\`:
@@ -2587,7 +2600,7 @@ async function getComponent(args) {
2587
2600
  const primaryContent = item.files[0]?.content ?? "";
2588
2601
  const primaryPath = item.files[0]?.path ?? "";
2589
2602
  const exportNames = extractAllExportNames(primaryContent);
2590
- const mainExport = extractExportName(primaryContent);
2603
+ const mainExport = extractExportName(primaryContent, args.component);
2591
2604
  const exportSection = exportNames.length > 0 ? dedent4`
2592
2605
  ## Exports
2593
2606
  **Main component export:** \`${mainExport ?? exportNames[0]}\`
@@ -2632,11 +2645,18 @@ async function getComponent(args) {
2632
2645
  ${fileSources}
2633
2646
  `);
2634
2647
  }
2635
- function extractExportName(source) {
2648
+ function extractExportName(source, componentName) {
2636
2649
  if (!source) return null;
2637
- const matches = [...source.matchAll(/export\s+(?:function|const)\s+([A-Z][A-Za-z0-9]*)/g)];
2638
- if (matches.length === 0) return null;
2639
- return matches[0][1] ?? null;
2650
+ const matches = [...source.matchAll(/export\s+function\s+([A-Z][A-Za-z0-9]*)/g)];
2651
+ const names = matches.map((m) => m[1]).filter(Boolean);
2652
+ if (names.length === 0) return null;
2653
+ if (!componentName) return names[0];
2654
+ const norm = componentName.replace(/-/g, "").toLowerCase();
2655
+ const exact = names.find((n) => n.toLowerCase() === norm);
2656
+ if (exact) return exact;
2657
+ const suffix = names.find((n) => n.toLowerCase().endsWith(norm));
2658
+ if (suffix) return suffix;
2659
+ return names[0];
2640
2660
  }
2641
2661
  function extractAllExportNames(source) {
2642
2662
  const seen = /* @__PURE__ */ new Set();
@@ -2845,7 +2865,7 @@ async function getInstallation(args) {
2845
2865
  | TypeScript errors on \`@react-pdf/renderer\` | \`${installCmd(pm, "@react-pdf/types", true)}\` |
2846
2866
  | "Cannot find module @/components/pdfx/..." | Run \`npx pdfx-cli@latest add <component>\` to install it |
2847
2867
  | PDF renders blank | Ensure root returns \`<Document><Page>...</Page></Document>\` |
2848
- | "Invalid hook call" | PDFx components cannot use React hooks — pass data as props |
2868
+ | "Invalid hook call" | Browser-only hooks (\`useEffect\`, \`useRef\` for DOM) don't work in the PDF render path move them to a parent client component and pass the result as a prop. PDFx framework hooks (\`usePdfxTheme\`, \`useSafeMemo\`) are valid inside PDF components. |
2849
2869
 
2850
2870
  ---
2851
2871
  Next: call \`get_audit_checklist\` to verify your setup is correct.
@@ -2969,14 +2989,13 @@ async function getTheme(args) {
2969
2989
 
2970
2990
  ## Usage in Components
2971
2991
  \`\`\`tsx
2972
- // Access theme values in a PDFx component
2973
- import type { PdfxTheme } from '@pdfx/shared';
2974
-
2975
- interface Props {
2976
- theme: PdfxTheme;
2977
- }
2992
+ // Access theme values in a PDFx component via the usePdfxTheme hook.
2993
+ // @pdfx/shared is workspace-only do NOT import from it in your components.
2994
+ import { View, Text } from '@react-pdf/renderer';
2995
+ import { usePdfxTheme } from '../lib/pdfx-theme-context';
2978
2996
 
2979
- export function MyComponent({ theme }: Props) {
2997
+ export function MyComponent() {
2998
+ const theme = usePdfxTheme();
2980
2999
  return (
2981
3000
  <View style={{ backgroundColor: theme.colors.background }}>
2982
3001
  <Text style={{ color: theme.colors.foreground, fontSize: theme.typography.body.fontSize }}>
package/dist/mcp/index.js CHANGED
@@ -570,8 +570,21 @@ async function getAuditChecklist() {
570
570
  \`\`\`
571
571
 
572
572
  ### "Invalid hook call"
573
- PDFx components render to PDF, not to the DOM — React hooks are not supported inside them.
574
- Move hook calls to the parent component and pass data down as props.
573
+ \`@react-pdf/renderer\` renders synchronously. Hooks that depend on browser APIs or
574
+ async side effects do not work in the PDF render path.
575
+
576
+ **Do NOT use inside a PDFx component:**
577
+ - \`useEffect\` / \`useLayoutEffect\` — no browser lifecycle in PDF rendering
578
+ - \`useRef\` for DOM nodes — no DOM exists in the PDF render tree
579
+ - Any hook that calls browser globals (\`window\`, \`document\`, \`navigator\`)
580
+
581
+ **These ARE valid inside PDFx components:**
582
+ - PDFx framework hooks: \`usePdfxTheme()\`, \`useSafeMemo()\`
583
+ - Custom hooks that are pure functions with no browser-API dependencies
584
+ - Data passed down as props from a parent client component
585
+
586
+ If you see this error in a wrapper component you wrote, move the browser hook
587
+ to the nearest client component and pass the result down as a prop.
575
588
 
576
589
  ### "Text strings must be rendered inside \`<Text>\` component"
577
590
  Wrap all string literals in \`<Text>\` from \`@react-pdf/renderer\`:
@@ -771,7 +784,7 @@ async function getComponent(args) {
771
784
  const primaryContent = item.files[0]?.content ?? "";
772
785
  const primaryPath = item.files[0]?.path ?? "";
773
786
  const exportNames = extractAllExportNames(primaryContent);
774
- const mainExport = extractExportName(primaryContent);
787
+ const mainExport = extractExportName(primaryContent, args.component);
775
788
  const exportSection = exportNames.length > 0 ? dedent4`
776
789
  ## Exports
777
790
  **Main component export:** \`${mainExport ?? exportNames[0]}\`
@@ -816,11 +829,18 @@ async function getComponent(args) {
816
829
  ${fileSources}
817
830
  `);
818
831
  }
819
- function extractExportName(source) {
832
+ function extractExportName(source, componentName) {
820
833
  if (!source) return null;
821
- const matches = [...source.matchAll(/export\s+(?:function|const)\s+([A-Z][A-Za-z0-9]*)/g)];
822
- if (matches.length === 0) return null;
823
- return matches[0][1] ?? null;
834
+ const matches = [...source.matchAll(/export\s+function\s+([A-Z][A-Za-z0-9]*)/g)];
835
+ const names = matches.map((m) => m[1]).filter(Boolean);
836
+ if (names.length === 0) return null;
837
+ if (!componentName) return names[0];
838
+ const norm = componentName.replace(/-/g, "").toLowerCase();
839
+ const exact = names.find((n) => n.toLowerCase() === norm);
840
+ if (exact) return exact;
841
+ const suffix = names.find((n) => n.toLowerCase().endsWith(norm));
842
+ if (suffix) return suffix;
843
+ return names[0];
824
844
  }
825
845
  function extractAllExportNames(source) {
826
846
  const seen = /* @__PURE__ */ new Set();
@@ -1029,7 +1049,7 @@ async function getInstallation(args) {
1029
1049
  | TypeScript errors on \`@react-pdf/renderer\` | \`${installCmd(pm, "@react-pdf/types", true)}\` |
1030
1050
  | "Cannot find module @/components/pdfx/..." | Run \`npx pdfx-cli@latest add <component>\` to install it |
1031
1051
  | PDF renders blank | Ensure root returns \`<Document><Page>...</Page></Document>\` |
1032
- | "Invalid hook call" | PDFx components cannot use React hooks — pass data as props |
1052
+ | "Invalid hook call" | Browser-only hooks (\`useEffect\`, \`useRef\` for DOM) don't work in the PDF render path move them to a parent client component and pass the result as a prop. PDFx framework hooks (\`usePdfxTheme\`, \`useSafeMemo\`) are valid inside PDF components. |
1033
1053
 
1034
1054
  ---
1035
1055
  Next: call \`get_audit_checklist\` to verify your setup is correct.
@@ -1153,14 +1173,13 @@ async function getTheme(args) {
1153
1173
 
1154
1174
  ## Usage in Components
1155
1175
  \`\`\`tsx
1156
- // Access theme values in a PDFx component
1157
- import type { PdfxTheme } from '@pdfx/shared';
1158
-
1159
- interface Props {
1160
- theme: PdfxTheme;
1161
- }
1176
+ // Access theme values in a PDFx component via the usePdfxTheme hook.
1177
+ // @pdfx/shared is workspace-only do NOT import from it in your components.
1178
+ import { View, Text } from '@react-pdf/renderer';
1179
+ import { usePdfxTheme } from '../lib/pdfx-theme-context';
1162
1180
 
1163
- export function MyComponent({ theme }: Props) {
1181
+ export function MyComponent() {
1182
+ const theme = usePdfxTheme();
1164
1183
  return (
1165
1184
  <View style={{ backgroundColor: theme.colors.background }}>
1166
1185
  <Text style={{ color: theme.colors.foreground, fontSize: theme.typography.body.fontSize }}>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdfx-cli",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "CLI for PDFx components",
5
5
  "type": "module",
6
6
  "bin": {