pdfx-cli 0.4.1 → 0.4.3

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';
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';
2974
2996
 
2975
- interface Props {
2976
- theme: PdfxTheme;
2977
- }
2978
-
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 }}>
@@ -3262,8 +3281,35 @@ async function initMcpConfig(opts) {
3262
3281
  await mkdir(configDir, { recursive: true });
3263
3282
  }
3264
3283
  const merged = mergeDeep(existing, client.config);
3265
- await writeFile2(configPath, `${JSON.stringify(merged, null, 2)}
3266
- `, "utf-8");
3284
+ const configJson = `${JSON.stringify(merged, null, 2)}
3285
+ `;
3286
+ try {
3287
+ const parsed = JSON.parse(configJson);
3288
+ if (!isPdfxAlreadyConfigured(parsed)) {
3289
+ console.error(
3290
+ chalk8.red(
3291
+ "\n Config merge failed \u2014 pdfx entry not found in merged output. Please report this bug.\n"
3292
+ )
3293
+ );
3294
+ process.exit(1);
3295
+ }
3296
+ } catch {
3297
+ console.error(chalk8.red("\n Config merge produced invalid JSON. Please report this bug.\n"));
3298
+ process.exit(1);
3299
+ }
3300
+ await writeFile2(configPath, configJson, "utf-8");
3301
+ try {
3302
+ const written = await readFile(configPath, "utf-8");
3303
+ JSON.parse(written);
3304
+ } catch {
3305
+ console.error(
3306
+ chalk8.red(
3307
+ `
3308
+ Warning: ${client.configPath} was written but could not be read back as valid JSON.
3309
+ `
3310
+ )
3311
+ );
3312
+ }
3267
3313
  process.stdout.write(`
3268
3314
  \u2713 Wrote MCP configuration to ${client.configPath}
3269
3315
  `);
@@ -3309,7 +3355,7 @@ import prompts6 from "prompts";
3309
3355
 
3310
3356
  // src/skills-content.ts
3311
3357
  var PDFX_SKILLS_CONTENT = `# PDFx \u2014 AI Context Guide
3312
- # Version: 1.0 | Updated: 2026 | License: MIT
3358
+ # Version: 1.1 | Updated: 2026 | License: MIT
3313
3359
  # Or run: npx pdfx-cli@latest skills init (handles editor-specific paths & frontmatter)
3314
3360
 
3315
3361
  ## What is PDFx?
@@ -3364,10 +3410,14 @@ export function MyDocument() {
3364
3410
  <Page size="A4" style={{ padding: 40 }}>
3365
3411
  <Heading level={1}>Invoice #001</Heading>
3366
3412
  <Text>Thank you for your business.</Text>
3367
- <Table
3368
- headers={['Item', 'Qty', 'Price']}
3369
- rows={[['Design work', '1', '$4,800']]}
3370
- />
3413
+ <Table variant="grid" zebraStripe>
3414
+ <TableHeader>
3415
+ <TableRow><TableCell header>Item</TableCell><TableCell header>Price</TableCell></TableRow>
3416
+ </TableHeader>
3417
+ <TableBody>
3418
+ <TableRow><TableCell>Design</TableCell><TableCell>$4,800</TableCell></TableRow>
3419
+ </TableBody>
3420
+ </Table>
3371
3421
  </Page>
3372
3422
  </Document>
3373
3423
  );
@@ -3403,11 +3453,14 @@ CRITICAL: These are the EXACT props. Do not invent additional props.
3403
3453
  import { Heading } from '@/components/pdfx/heading/pdfx-heading';
3404
3454
  <Heading
3405
3455
  level={1} // 1 | 2 | 3 | 4 | 5 | 6 \u2014 default: 1
3406
- align="left" // 'left' | 'center' | 'right' \u2014 default: 'left'
3407
- weight="bold" // 'normal' | 'bold' \u2014 default: 'bold'
3408
- tracking="normal" // 'tight' | 'normal' | 'wide' \u2014 default: 'normal'
3409
- color="#000" // string \u2014 default: theme.colors.foreground
3410
- gutterBottom // boolean \u2014 adds bottom margin
3456
+ align="left" // 'left' | 'center' | 'right'
3457
+ weight="bold" // 'normal' | 'medium' | 'semibold' | 'bold' \u2014 default: 'bold'
3458
+ tracking="normal" // 'tighter' | 'tight' | 'normal' | 'wide' | 'wider' \u2014 default: 'normal'
3459
+ color="#000" // string \u2014 default: theme foreground. Supports theme color keys.
3460
+ transform="uppercase" // 'uppercase' | 'lowercase' | 'capitalize'
3461
+ noMargin // boolean \u2014 removes top/bottom margin
3462
+ keepWithNext // boolean \u2014 default: true, prevents orphaned heading
3463
+ style={...} // Style override
3411
3464
  >
3412
3465
  My Heading
3413
3466
  </Heading>
@@ -3417,13 +3470,15 @@ import { Heading } from '@/components/pdfx/heading/pdfx-heading';
3417
3470
  \`\`\`tsx
3418
3471
  import { Text } from '@/components/pdfx/text/pdfx-text';
3419
3472
  <Text
3420
- size="md" // 'xs' | 'sm' | 'md' | 'lg' | 'xl' \u2014 default: 'md'
3473
+ variant="base" // 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl' \u2014 default: 'base'
3421
3474
  weight="normal" // 'normal' | 'medium' | 'semibold' | 'bold' \u2014 default: 'normal'
3422
- color="#000" // string
3475
+ color="#000" // string \u2014 supports theme color keys
3423
3476
  align="left" // 'left' | 'center' | 'right' | 'justify'
3424
3477
  italic // boolean
3425
- muted // boolean \u2014 applies theme.colors.mutedForeground
3426
- gutterBottom // boolean
3478
+ decoration="none" // 'underline' | 'line-through' | 'none'
3479
+ transform="uppercase" // 'uppercase' | 'lowercase' | 'capitalize'
3480
+ noMargin // boolean \u2014 removes bottom margin
3481
+ style={...} // Style override
3427
3482
  >
3428
3483
  Paragraph text here.
3429
3484
  </Text>
@@ -3434,8 +3489,11 @@ import { Text } from '@/components/pdfx/text/pdfx-text';
3434
3489
  import { Link } from '@/components/pdfx/link/pdfx-link';
3435
3490
  <Link
3436
3491
  href="https://example.com" // string \u2014 required
3437
- size="md" // same as Text size
3438
- color="#0000ff" // default: theme.colors.accent
3492
+ variant="default" // 'default' | 'muted' | 'primary' \u2014 default: 'default'
3493
+ underline="always" // 'always' | 'none' \u2014 default: 'always'
3494
+ align="left" // 'left' | 'center' | 'right'
3495
+ color="#0000ff" // string \u2014 overrides variant color
3496
+ style={...} // Style override
3439
3497
  >
3440
3498
  Click here
3441
3499
  </Link>
@@ -3445,10 +3503,12 @@ import { Link } from '@/components/pdfx/link/pdfx-link';
3445
3503
  \`\`\`tsx
3446
3504
  import { Divider } from '@/components/pdfx/divider/pdfx-divider';
3447
3505
  <Divider
3448
- thickness={1} // number in pt \u2014 default: 1
3449
- color="#e4e4e7" // string \u2014 default: theme.colors.border
3450
- spacing="md" // 'sm' | 'md' | 'lg' \u2014 vertical margin
3451
- style="solid" // 'solid' | 'dashed' | 'dotted'
3506
+ spacing="md" // 'none' | 'sm' | 'md' | 'lg' \u2014 default: 'md'
3507
+ variant="solid" // 'solid' | 'dashed' | 'dotted' \u2014 default: 'solid'
3508
+ thickness="thin" // 'thin' | 'medium' | 'thick' \u2014 default: 'thin'
3509
+ color="#e4e4e7" // string \u2014 default: theme border color
3510
+ label="or" // string \u2014 text centered in divider line
3511
+ width="80%" // string | number \u2014 constrain width
3452
3512
  />
3453
3513
  \`\`\`
3454
3514
 
@@ -3462,11 +3522,12 @@ import { PageBreak } from '@/components/pdfx/page-break/pdfx-page-break';
3462
3522
  \`\`\`tsx
3463
3523
  import { Stack } from '@/components/pdfx/stack/pdfx-stack';
3464
3524
  <Stack
3465
- direction="column" // 'row' | 'column' \u2014 default: 'column'
3466
- gap={8} // number in pt \u2014 default: 0
3467
- align="flex-start" // flexbox align-items
3468
- justify="flex-start"// flexbox justify-content
3469
- wrap // boolean \u2014 flex-wrap
3525
+ direction="vertical" // 'vertical' | 'horizontal' \u2014 default: 'vertical'
3526
+ gap="md" // 'none' | 'sm' | 'md' | 'lg' | 'xl' \u2014 default: 'md'
3527
+ align="start" // 'start' | 'center' | 'end' | 'stretch'
3528
+ justify="start" // 'start' | 'center' | 'end' | 'between' | 'around'
3529
+ wrap // boolean \u2014 flex-wrap
3530
+ noWrap // boolean \u2014 prevent page split
3470
3531
  >
3471
3532
  {children}
3472
3533
  </Stack>
@@ -3476,33 +3537,43 @@ import { Stack } from '@/components/pdfx/stack/pdfx-stack';
3476
3537
  \`\`\`tsx
3477
3538
  import { Section } from '@/components/pdfx/section/pdfx-section';
3478
3539
  <Section
3479
- title="Section Title" // string \u2014 optional
3480
- titleLevel={2} // 1\u20136 \u2014 default: 2
3481
- padding={16} // number | {top,right,bottom,left} \u2014 default: 0
3482
- bordered // boolean \u2014 adds border around section
3483
- background="#f9f9f9" // string \u2014 background color
3540
+ spacing="md" // 'none' | 'sm' | 'md' | 'lg' | 'xl' \u2014 default: 'md'
3541
+ padding="md" // 'none' | 'sm' | 'md' | 'lg' \u2014 optional
3542
+ variant="default" // 'default' | 'callout' | 'highlight' | 'card'
3543
+ border // boolean \u2014 adds border (default variant only)
3544
+ background="#f9f9f9" // string \u2014 background color
3545
+ accentColor="#2563eb" // string \u2014 left border color for callout/highlight
3546
+ noWrap // boolean \u2014 prevent page split
3547
+ style={...} // Style override
3484
3548
  >
3485
3549
  {children}
3486
3550
  </Section>
3487
3551
  \`\`\`
3488
3552
 
3489
- ### Table
3553
+ ### Table (composable API)
3490
3554
  \`\`\`tsx
3491
- import { Table } from '@/components/pdfx/table/pdfx-table';
3555
+ import { Table, TableHeader, TableBody, TableFooter, TableRow, TableCell } from '@/components/pdfx/table/pdfx-table';
3492
3556
  <Table
3493
- headers={['Column A', 'Column B', 'Column C']} // string[] \u2014 required
3494
- rows={[['R1C1', 'R1C2', 'R1C3']]} // string[][] \u2014 required
3495
- striped // boolean \u2014 alternating row colors
3496
- bordered // boolean \u2014 cell borders
3497
- compact // boolean \u2014 smaller padding
3498
- headerBg="#18181b" // string \u2014 header background
3499
- headerColor="#fff" // string \u2014 header text color
3500
- columnWidths={[2, 1, 1]} // number[] \u2014 flex ratios
3501
- caption="Table 1" // string \u2014 caption below table
3502
- />
3557
+ variant="line" // 'line' | 'grid' | 'minimal' | 'striped' | 'compact' | 'bordered' | 'primary-header'
3558
+ zebraStripe // boolean \u2014 alternating row background
3559
+ noWrap // boolean \u2014 prevent page split
3560
+ >
3561
+ <TableHeader>
3562
+ <TableRow>
3563
+ <TableCell header>Column A</TableCell>
3564
+ <TableCell header>Column B</TableCell>
3565
+ </TableRow>
3566
+ </TableHeader>
3567
+ <TableBody>
3568
+ <TableRow>
3569
+ <TableCell>R1C1</TableCell>
3570
+ <TableCell align="right" width={80}>R1C2</TableCell>
3571
+ </TableRow>
3572
+ </TableBody>
3573
+ </Table>
3503
3574
  \`\`\`
3504
3575
 
3505
- ### DataTable
3576
+ ### DataTable (declarative API)
3506
3577
  \`\`\`tsx
3507
3578
  import { DataTable } from '@/components/pdfx/data-table/pdfx-data-table';
3508
3579
  <DataTable
@@ -3511,62 +3582,90 @@ import { DataTable } from '@/components/pdfx/data-table/pdfx-data-table';
3511
3582
  { key: 'amount', header: 'Amount', width: 1, align: 'right' },
3512
3583
  ]}
3513
3584
  data={[{ name: 'Item A', amount: '$100' }]}
3514
- striped
3515
- bordered
3516
- compact
3585
+ variant="grid" // 'line' | 'grid' | 'minimal' | 'striped' | 'compact' | 'bordered' | 'primary-header'
3586
+ stripe // boolean \u2014 alternating row background
3587
+ size="default" // 'default' | 'compact'
3588
+ footer={{ amount: '$100' }} // partial record for footer row
3589
+ noWrap // boolean \u2014 prevent page split
3517
3590
  />
3518
3591
  \`\`\`
3592
+ DataTable render prop: \`render\` and \`renderFooter\` must return @react-pdf/renderer elements
3593
+ (Text, View, Image) \u2014 NOT HTML elements. TypeScript accepts ReactNode but DOM elements crash.
3519
3594
 
3520
- ### List
3595
+ ### PdfList
3521
3596
  \`\`\`tsx
3522
- import { List } from '@/components/pdfx/list/pdfx-list';
3523
- <List
3524
- items={['First item', 'Second item', 'Third item']} // string[] \u2014 required
3525
- ordered // boolean \u2014 numbered list (default: bulleted)
3526
- bullet="\u2022" // string \u2014 custom bullet character
3527
- indent={16} // number \u2014 left indent in pt
3528
- spacing="sm" // 'sm' | 'md' | 'lg' \u2014 gap between items
3597
+ import { PdfList } from '@/components/pdfx/list/pdfx-list';
3598
+ <PdfList
3599
+ items={[
3600
+ { text: 'First item' },
3601
+ { text: 'Second item', description: 'Details here' },
3602
+ { text: 'Checked item', checked: true },
3603
+ { text: 'Parent', children: [{ text: 'Nested' }] },
3604
+ ]}
3605
+ variant="bullet" // 'bullet' | 'numbered' | 'checklist' | 'icon' | 'multi-level' | 'descriptive'
3606
+ gap="sm" // 'xs' | 'sm' | 'md' \u2014 default: 'sm'
3607
+ noWrap // boolean \u2014 prevent page split
3529
3608
  />
3530
3609
  \`\`\`
3531
3610
 
3532
- ### Card
3611
+ ### PdfCard
3533
3612
  \`\`\`tsx
3534
- import { Card } from '@/components/pdfx/card/pdfx-card';
3535
- <Card
3536
- padding={16} // number \u2014 default: 16
3537
- bordered // boolean \u2014 default: true
3538
- shadow // boolean
3539
- background="#fff" // string
3540
- borderColor="#e4e4e7" // string
3541
- borderRadius={4} // number in pt
3613
+ import { PdfCard } from '@/components/pdfx/card/pdfx-card';
3614
+ <PdfCard
3615
+ title="Card Title" // string \u2014 rendered with border-bottom
3616
+ variant="default" // 'default' | 'bordered' | 'muted'
3617
+ padding="md" // 'sm' | 'md' | 'lg' \u2014 default: 'md'
3618
+ wrap={false} // boolean \u2014 default: false (prevents page split)
3619
+ style={...} // Style override
3542
3620
  >
3543
3621
  {children}
3544
- </Card>
3622
+ </PdfCard>
3545
3623
  \`\`\`
3546
3624
 
3547
- ### Form (read-only form fields for PDFs)
3625
+ ### PdfForm (read-only fillable form for PDFs)
3548
3626
  \`\`\`tsx
3549
- import { Form } from '@/components/pdfx/form/pdfx-form';
3550
- <Form
3551
- fields={[
3552
- { label: 'Full Name', value: 'John Doe' },
3553
- { label: 'Email', value: 'john@example.com' },
3554
- { label: 'Notes', value: 'Some notes here', multiline: true },
3627
+ import { PdfForm } from '@/components/pdfx/form/pdfx-form';
3628
+ <PdfForm
3629
+ title="Application Form"
3630
+ subtitle="Please fill in all fields"
3631
+ groups={[
3632
+ {
3633
+ title: 'Personal Information',
3634
+ layout: 'two-column', // 'single' | 'two-column' | 'three-column'
3635
+ fields: [
3636
+ { label: 'Full Name', hint: 'As on ID', height: 24 },
3637
+ { label: 'Email' },
3638
+ ],
3639
+ },
3640
+ {
3641
+ title: 'Notes',
3642
+ fields: [{ label: 'Additional Info', height: 60 }],
3643
+ },
3555
3644
  ]}
3556
- columns={2} // 1 | 2 \u2014 default: 1
3557
- bordered // boolean
3645
+ variant="underline" // 'underline' | 'box' | 'outlined' | 'ghost'
3646
+ labelPosition="above" // 'above' | 'left' \u2014 default: 'above'
3647
+ noWrap // boolean
3558
3648
  />
3559
3649
  \`\`\`
3560
3650
 
3561
- ### Signature
3651
+ ### PdfSignatureBlock
3562
3652
  \`\`\`tsx
3563
3653
  import { PdfSignatureBlock } from '@/components/pdfx/signature/pdfx-signature';
3654
+ // Single signature
3655
+ <PdfSignatureBlock
3656
+ variant="single" // 'single' | 'double' | 'inline' \u2014 default: 'single'
3657
+ label="Signature" // string \u2014 label above line
3658
+ name="Sarah Chen" // string \u2014 printed name below line
3659
+ title="Engineering Lead" // string \u2014 title/role below name
3660
+ date="2024-12-12" // string \u2014 formatted date
3661
+ />
3662
+ // Double signature
3564
3663
  <PdfSignatureBlock
3565
- name="Sarah Chen" // string \u2014 printed name below line
3566
- title="Engineering Lead" // string \u2014 title/role below name
3567
- date="2024-12-12" // string \u2014 formatted date
3568
- lineWidth={120} // number \u2014 signature line width in pt
3569
- showDate // boolean \u2014 default: true
3664
+ variant="double"
3665
+ signers={[
3666
+ { label: 'Authorized by', name: 'John', title: 'CEO', date: '2024-12-12' },
3667
+ { label: 'Approved by', name: 'Jane', title: 'CFO', date: '2024-12-12' },
3668
+ ]}
3570
3669
  />
3571
3670
  \`\`\`
3572
3671
 
@@ -3574,10 +3673,18 @@ import { PdfSignatureBlock } from '@/components/pdfx/signature/pdfx-signature';
3574
3673
  \`\`\`tsx
3575
3674
  import { PageHeader } from '@/components/pdfx/page-header/pdfx-page-header';
3576
3675
  <PageHeader
3577
- title="Document Title"
3578
- subtitle="Subtitle or tagline"
3579
- logo={{ src: 'https://...', width: 60, height: 30 }}
3580
- bordered // boolean \u2014 adds bottom border
3676
+ title="Document Title" // string \u2014 required
3677
+ subtitle="Subtitle" // string
3678
+ rightText="INV-001" // string \u2014 right-aligned text
3679
+ rightSubText="Due: Jan 31" // string \u2014 right sub-text
3680
+ variant="simple" // 'simple' | 'centered' | 'minimal' | 'branded' | 'logo-left' | 'logo-right' | 'two-column'
3681
+ logo={<PdfImage src="..." />} // ReactNode \u2014 for logo-left/logo-right
3682
+ background="#18181b" // string \u2014 background color (branded)
3683
+ titleColor="#fff" // string \u2014 title text color
3684
+ address="123 Main St" // string \u2014 for two-column variant
3685
+ phone="+1-555-0100" // string
3686
+ email="hello@acme.com" // string
3687
+ fixed // boolean \u2014 repeat on every page
3581
3688
  />
3582
3689
  \`\`\`
3583
3690
 
@@ -3585,10 +3692,19 @@ import { PageHeader } from '@/components/pdfx/page-header/pdfx-page-header';
3585
3692
  \`\`\`tsx
3586
3693
  import { PageFooter } from '@/components/pdfx/page-footer/pdfx-page-footer';
3587
3694
  <PageFooter
3588
- left="\xA9 2024 Acme Corp"
3589
- center="Confidential"
3590
- right="Page 1 of 1"
3591
- bordered // boolean \u2014 top border
3695
+ leftText="\xA9 2024 Acme Corp" // string
3696
+ centerText="Confidential" // string
3697
+ rightText="Page 1 of 1" // string
3698
+ variant="simple" // 'simple' | 'centered' | 'branded' | 'minimal' | 'three-column' | 'detailed'
3699
+ background="#18181b" // string
3700
+ textColor="#fff" // string
3701
+ address="123 Main St" // string \u2014 for three-column/detailed
3702
+ phone="+1-555-0100" // string
3703
+ email="hello@acme.com" // string
3704
+ website="https://acme.com" // string
3705
+ fixed // boolean \u2014 repeat on every page
3706
+ sticky // boolean \u2014 absolute position at page bottom
3707
+ pagePadding={40} // number \u2014 offset for sticky positioning
3592
3708
  />
3593
3709
  \`\`\`
3594
3710
 
@@ -3598,8 +3714,10 @@ import { Badge } from '@/components/pdfx/badge/pdfx-badge';
3598
3714
  // Use label prop OR children (string only \u2014 not a React node)
3599
3715
  <Badge
3600
3716
  label="PAID" // string \u2014 preferred API
3601
- variant="success" // 'default' | 'success' | 'warning' | 'error' | 'info' | 'outline'
3717
+ variant="success" // 'default' | 'primary' | 'success' | 'warning' | 'destructive' | 'info' | 'outline'
3602
3718
  size="md" // 'sm' | 'md' | 'lg'
3719
+ background="#000" // string \u2014 override background
3720
+ color="#fff" // string \u2014 override text color
3603
3721
  />
3604
3722
  // OR
3605
3723
  <Badge variant="success">PAID</Badge>
@@ -3610,12 +3728,17 @@ import { Badge } from '@/components/pdfx/badge/pdfx-badge';
3610
3728
  import { KeyValue } from '@/components/pdfx/key-value/pdfx-key-value';
3611
3729
  <KeyValue
3612
3730
  items={[
3613
- { label: 'Invoice #', value: 'INV-001' },
3614
- { label: 'Due Date', value: 'Jan 31, 2025' },
3731
+ { key: 'Invoice #', value: 'INV-001' },
3732
+ { key: 'Due Date', value: 'Jan 31, 2025', valueColor: 'destructive' },
3615
3733
  ]}
3616
- columns={2} // 1 | 2 | 3 \u2014 default: 1
3617
- labelWidth={80} // number in pt
3618
- colon // boolean \u2014 adds colon after label
3734
+ direction="horizontal" // 'horizontal' | 'vertical' \u2014 default: 'horizontal'
3735
+ divided // boolean \u2014 dividers between rows
3736
+ size="md" // 'sm' | 'md' | 'lg' \u2014 default: 'md'
3737
+ labelFlex={1} // number \u2014 flex ratio for label column
3738
+ labelColor="#666" // string
3739
+ valueColor="#000" // string
3740
+ boldValue // boolean \u2014 bold all values
3741
+ noWrap // boolean
3619
3742
  />
3620
3743
  \`\`\`
3621
3744
 
@@ -3625,7 +3748,7 @@ import { KeepTogether } from '@/components/pdfx/keep-together/pdfx-keep-together
3625
3748
  // Prevents page breaks inside its children
3626
3749
  <KeepTogether>
3627
3750
  <Heading level={3}>Section that must not split</Heading>
3628
- <Table headers={[...]} rows={[...]} />
3751
+ <Table variant="grid">...</Table>
3629
3752
  </KeepTogether>
3630
3753
  \`\`\`
3631
3754
 
@@ -3633,74 +3756,102 @@ import { KeepTogether } from '@/components/pdfx/keep-together/pdfx-keep-together
3633
3756
  \`\`\`tsx
3634
3757
  import { PdfImage } from '@/components/pdfx/pdf-image/pdfx-pdf-image';
3635
3758
  <PdfImage
3636
- src="https://example.com/image.png" // string | base64 \u2014 required
3637
- width={200} // number in pt
3638
- height={150} // optional \u2014 maintains aspect ratio if omitted
3639
- alt="Description" // string \u2014 for accessibility
3640
- objectFit="cover" // 'cover' | 'contain' | 'fill'
3641
- borderRadius={4} // number
3759
+ src="https://example.com/image.png" // string | { uri, method?, headers?, body? } \u2014 required
3760
+ variant="default" // 'default' | 'full-width' | 'thumbnail' | 'avatar' | 'cover' | 'bordered' | 'rounded'
3761
+ width={200} // number | string in pt
3762
+ height={150} // number | string \u2014 auto from aspect ratio if omitted
3763
+ fit="contain" // 'cover' | 'contain' | 'fill' | 'none' \u2014 default varies by variant
3764
+ position="50% 50%" // string \u2014 object-position
3765
+ caption="Figure 1" // string \u2014 centered below image
3766
+ aspectRatio={16/9} // number \u2014 compute height from width
3767
+ borderRadius={4} // number
3768
+ noWrap // boolean \u2014 default: true
3642
3769
  />
3643
3770
  \`\`\`
3644
3771
 
3645
- ### Graph
3772
+ ### PdfGraph
3646
3773
  \`\`\`tsx
3647
- import { Graph } from '@/components/pdfx/graph/pdfx-graph';
3648
- <Graph
3649
- type="bar" // 'bar' | 'line' | 'pie' | 'donut'
3774
+ import { PdfGraph } from '@/components/pdfx/graph/pdfx-graph';
3775
+ <PdfGraph
3776
+ variant="bar" // 'bar' | 'horizontal-bar' | 'line' | 'area' | 'pie' | 'donut'
3650
3777
  data={[
3651
3778
  { label: 'Q1', value: 4200 },
3652
3779
  { label: 'Q2', value: 6100 },
3653
3780
  ]}
3654
- width={400} // number in pt
3655
- height={200} // number in pt
3656
- title="Revenue" // string \u2014 optional
3657
- showValues // boolean \u2014 show value labels
3658
- showLegend // boolean
3659
- colors={['#18181b', '#71717a']} // string[] \u2014 bar/slice colors
3781
+ title="Revenue" // string
3782
+ subtitle="FY2024" // string
3783
+ xLabel="Quarter" // string \u2014 x-axis label
3784
+ yLabel="Revenue ($)" // string \u2014 y-axis label
3785
+ width={420} // number \u2014 default: 420 (or auto with fullWidth)
3786
+ height={260} // number \u2014 default: 260
3787
+ fullWidth // boolean \u2014 auto-calculates width from page margins
3788
+ containerPadding={12} // number \u2014 for fullWidth: outer container padding
3789
+ wrapperPadding={12} // number \u2014 for fullWidth: wrapper padding
3790
+ colors={['#18181b', '#71717a']} // string[] \u2014 color palette
3791
+ showValues // boolean \u2014 show numeric labels on bars/points
3792
+ showGrid // boolean \u2014 default: true
3793
+ legend="bottom" // 'bottom' | 'right' | 'none' \u2014 default: 'bottom'
3794
+ centerLabel="$1.2M" // string \u2014 for donut: text in center hole
3795
+ showDots // boolean \u2014 default: true (line/area only)
3796
+ smooth // boolean \u2014 bezier curves (line/area only)
3797
+ yTicks={5} // number \u2014 Y-axis tick count
3798
+ noWrap // boolean \u2014 default: true
3660
3799
  />
3661
3800
  \`\`\`
3801
+ Multi-series data: \`data={[{ name: 'Series A', data: [...] }, { name: 'Series B', data: [...] }]}\`
3802
+ Graph width utilities: \`getGraphWidth(theme, opts?)\`, \`GRAPH_SAFE_WIDTHS\`, \`A4_WIDTH\` are exported.
3662
3803
 
3663
- ### PageNumber
3804
+ ### PdfPageNumber
3664
3805
  \`\`\`tsx
3665
- import { PageNumber } from '@/components/pdfx/page-number/pdfx-page-number';
3666
- <PageNumber
3667
- format="Page {current} of {total}" // string template
3668
- size="sm"
3669
- align="right"
3806
+ import { PdfPageNumber } from '@/components/pdfx/page-number/pdfx-page-number';
3807
+ <PdfPageNumber
3808
+ format="Page {page} of {total}" // string \u2014 use {page} and {total} placeholders
3809
+ align="center" // 'left' | 'center' | 'right' \u2014 default: 'center'
3810
+ size="sm" // 'xs' | 'sm' | 'md' \u2014 default: 'sm'
3811
+ fixed // boolean \u2014 repeats on every page
3812
+ muted // boolean \u2014 default: true, uses mutedForeground color
3670
3813
  />
3671
3814
  \`\`\`
3672
3815
 
3673
- ### Watermark
3816
+ ### PdfWatermark
3674
3817
  \`\`\`tsx
3675
3818
  import { PdfWatermark } from '@/components/pdfx/watermark/pdfx-watermark';
3676
3819
  <PdfWatermark
3677
3820
  text="CONFIDENTIAL" // string \u2014 required
3678
- opacity={0.08} // number 0\u20131 \u2014 default: 0.08
3679
- angle={-35} // number in degrees \u2014 default: -35
3680
- fontSize={72} // number \u2014 default: 72
3681
- color="#000000" // string
3821
+ opacity={0.15} // number 0\u20131 \u2014 default: 0.15
3822
+ fontSize={60} // number \u2014 default: 60
3823
+ color="mutedForeground" // string \u2014 default: 'mutedForeground' (theme key or hex)
3824
+ angle={-45} // number in degrees \u2014 default: -45
3825
+ position="center" // 'center' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
3826
+ fixed // boolean \u2014 default: true (repeats on every page)
3682
3827
  />
3683
3828
  \`\`\`
3684
3829
 
3685
- ### QRCode
3830
+ ### PdfQRCode
3686
3831
  \`\`\`tsx
3687
3832
  import { PdfQRCode } from '@/components/pdfx/qrcode/pdfx-qrcode';
3688
3833
  <PdfQRCode
3689
3834
  value="https://example.com" // string \u2014 required
3690
- size={80} // number in pt \u2014 default: 80
3691
- errorCorrectionLevel="M" // 'L' | 'M' | 'Q' | 'H'
3835
+ size={100} // number \u2014 default: 100
3836
+ color="#000000" // string \u2014 default: '#000000'
3837
+ backgroundColor="#ffffff" // string \u2014 default: '#ffffff'
3838
+ errorLevel="M" // 'L' | 'M' | 'Q' | 'H' \u2014 default: 'M'
3839
+ margin={2} // number \u2014 quiet zone modules \u2014 default: 2
3840
+ caption="Scan me" // string \u2014 text below QR code
3692
3841
  />
3693
3842
  \`\`\`
3694
3843
 
3695
- ### Alert
3844
+ ### PdfAlert
3696
3845
  \`\`\`tsx
3697
- import { Alert } from '@/components/pdfx/alert/pdfx-alert';
3698
- <Alert
3699
- variant="info" // 'info' | 'success' | 'warning' | 'error'
3700
- title="Note" // string \u2014 optional bold title
3846
+ import { PdfAlert } from '@/components/pdfx/alert/pdfx-alert';
3847
+ <PdfAlert
3848
+ variant="info" // 'info' | 'success' | 'warning' | 'error' \u2014 default: 'info'
3849
+ title="Note" // string \u2014 optional bold title
3850
+ showIcon // boolean \u2014 default: true
3851
+ showBorder // boolean \u2014 default: true (left border)
3701
3852
  >
3702
3853
  This is an informational note.
3703
- </Alert>
3854
+ </PdfAlert>
3704
3855
  \`\`\`
3705
3856
 
3706
3857
  ---
@@ -3713,20 +3864,18 @@ npx pdfx-cli@latest block add <block-name>
3713
3864
  \`\`\`
3714
3865
 
3715
3866
  ### Invoice Blocks
3716
- - invoice-modern \u2014 Clean two-column layout with totals table
3717
- - invoice-minimal \u2014 Stripped-down, typography-focused
3718
- - invoice-corporate \u2014 Header with logo area, full itemization
3719
- - invoice-creative \u2014 Accent colors, bold layout
3867
+ - invoice-classic \u2014 Professional with logo-left header and zebra-striped grid table
3868
+ - invoice-minimal \u2014 Clean stripped-down, typography-focused layout
3869
+ - invoice-modern \u2014 Full-width banner header, horizontal meta strip
3870
+ - invoice-corporate \u2014 Formal layout with purchase order fields and signatures
3871
+ - invoice-creative \u2014 Accent sidebar, vibrant color highlights
3872
+ - invoice-consultant \u2014 Hourly rate breakdown, project summary
3720
3873
 
3721
3874
  ### Report Blocks
3722
- - report-executive \u2014 KPI cards + summary table, 2-page
3723
- - report-annual \u2014 Multi-section with charts and appendix
3724
- - report-financial \u2014 P&L / balance sheet focus
3725
- - report-marketing \u2014 Campaign metrics with graphs
3726
- - report-technical \u2014 Code-friendly, monospace sections
3727
-
3728
- ### Contract Block
3729
- - contract-standard \u2014 Signature page, numbered clauses, party info
3875
+ - report-financial \u2014 KPI cards, trend chart, delivery table
3876
+ - report-marketing \u2014 Channel performance, acquisition trendline
3877
+ - report-operations \u2014 SLA health, throughput trends, risk tracking
3878
+ - report-security \u2014 Vulnerability trend tracking, remediation table
3730
3879
 
3731
3880
  Blocks are added as full React components in your project. Customize all content props.
3732
3881
 
@@ -3811,6 +3960,18 @@ npx pdfx-cli@latest skills init --platform antigravity # .antigravity/context.md
3811
3960
 
3812
3961
  ---
3813
3962
 
3963
+ ## Component Naming Convention
3964
+
3965
+ PDFx uses a \`Pdf\` prefix when the component name collides with an existing widely-used React
3966
+ or @react-pdf/renderer export:
3967
+
3968
+ Prefixed (10): PdfAlert, PdfCard, PdfForm, PdfGraph, PdfImage, PdfList, PdfPageNumber, PdfQRCode, PdfSignatureBlock, PdfWatermark
3969
+ Unprefixed (14): Badge, DataTable, Divider, Heading, KeepTogether, KeyValue, Link, PageBreak, PageFooter, PageHeader, Section, Stack, Table, Text
3970
+
3971
+ When importing, always use the exact name shown in each component section above.
3972
+
3973
+ ---
3974
+
3814
3975
  ## Common patterns
3815
3976
 
3816
3977
  ### Full invoice from scratch
@@ -3818,7 +3979,7 @@ npx pdfx-cli@latest skills init --platform antigravity # .antigravity/context.md
3818
3979
  import { Document, Page } from '@react-pdf/renderer';
3819
3980
  import { Heading } from '@/components/pdfx/heading/pdfx-heading';
3820
3981
  import { KeyValue } from '@/components/pdfx/key-value/pdfx-key-value';
3821
- import { Table } from '@/components/pdfx/table/pdfx-table';
3982
+ import { Table, TableHeader, TableBody, TableRow, TableCell } from '@/components/pdfx/table/pdfx-table';
3822
3983
  import { Divider } from '@/components/pdfx/divider/pdfx-divider';
3823
3984
  import { Badge } from '@/components/pdfx/badge/pdfx-badge';
3824
3985
  import { PageFooter } from '@/components/pdfx/page-footer/pdfx-page-footer';
@@ -3830,24 +3991,30 @@ export function InvoiceDoc() {
3830
3991
  <Heading level={1}>Invoice #INV-001</Heading>
3831
3992
  <KeyValue
3832
3993
  items={[
3833
- { label: 'Date', value: 'Jan 1, 2025' },
3834
- { label: 'Due', value: 'Jan 31, 2025' },
3994
+ { key: 'Date', value: 'Jan 1, 2025' },
3995
+ { key: 'Due', value: 'Jan 31, 2025' },
3835
3996
  ]}
3836
- columns={2}
3997
+ direction="horizontal"
3837
3998
  />
3838
3999
  <Divider spacing="md" />
3839
- <Table
3840
- headers={['Description', 'Qty', 'Total']}
3841
- rows={[
3842
- ['Design System', '1', '$4,800'],
3843
- ['Development', '2', '$9,600'],
3844
- ]}
3845
- striped
3846
- bordered
3847
- columnWidths={[3, 1, 1]}
3848
- />
4000
+ <Table variant="grid" zebraStripe>
4001
+ <TableHeader>
4002
+ <TableRow>
4003
+ <TableCell header width="60%">Description</TableCell>
4004
+ <TableCell header align="center">Qty</TableCell>
4005
+ <TableCell header align="right">Total</TableCell>
4006
+ </TableRow>
4007
+ </TableHeader>
4008
+ <TableBody>
4009
+ <TableRow>
4010
+ <TableCell>Design System</TableCell>
4011
+ <TableCell align="center">1</TableCell>
4012
+ <TableCell align="right">$4,800</TableCell>
4013
+ </TableRow>
4014
+ </TableBody>
4015
+ </Table>
3849
4016
  <Badge label="PAID" variant="success" />
3850
- <PageFooter left="Acme Corp" right="Page 1 of 1" bordered />
4017
+ <PageFooter leftText="Acme Corp" rightText="Page 1 of 1" />
3851
4018
  </Page>
3852
4019
  </Document>
3853
4020
  );
@@ -3859,7 +4026,7 @@ export function InvoiceDoc() {
3859
4026
  // Wrap anything that must stay together across page boundaries
3860
4027
  <KeepTogether>
3861
4028
  <Heading level={3}>Q3 Summary</Heading>
3862
- <Table headers={['Metric', 'Value']} rows={data} />
4029
+ <DataTable columns={columns} data={data} variant="grid" />
3863
4030
  </KeepTogether>
3864
4031
  \`\`\`
3865
4032
 
@@ -3877,7 +4044,7 @@ export async function GET(req: Request) {
3877
4044
  return new Response(buf, {
3878
4045
  headers: {
3879
4046
  'Content-Type': 'application/pdf',
3880
- 'Content-Disposition': \`inline; filename="invoice-\${id}.pdf"\`,
4047
+ 'Content-Disposition': \\\`inline; filename="invoice-\\\${id}.pdf"\\\`,
3881
4048
  },
3882
4049
  });
3883
4050
  }
@@ -3918,6 +4085,7 @@ export async function GET(req: Request) {
3918
4085
  - DO NOT install components with npm \u2014 always use the CLI: npx pdfx-cli@latest add <name>
3919
4086
  - DO NOT place raw text siblings next to View elements in a flex row (react-pdf constraint)
3920
4087
  - DO NOT pass React nodes (JSX) as Badge children \u2014 only plain strings are supported
4088
+ - DO NOT return HTML elements from DataTable render/renderFooter \u2014 PDF elements only
3921
4089
 
3922
4090
  ---
3923
4091
 
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.3",
4
4
  "description": "CLI for PDFx components",
5
5
  "type": "module",
6
6
  "bin": {