@tonzxz/government-forms 0.1.0 → 0.2.0
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/FORM_CATALOG.md +4 -0
- package/README.md +52 -2
- package/dist/document-preview.d.ts +32 -0
- package/dist/document-preview.js +55 -0
- package/dist/gam/utils/export-preview-pdf.js +54 -43
- package/dist/gam/utils/print-element.js +41 -61
- package/dist/government-form.d.ts +6 -1
- package/dist/government-form.js +4 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/inventory/iar.d.ts +5 -0
- package/dist/inventory/iar.js +5 -0
- package/dist/inventory/ics.d.ts +5 -0
- package/dist/inventory/ics.js +5 -0
- package/dist/inventory/iirup.d.ts +5 -0
- package/dist/inventory/iirup.js +5 -0
- package/dist/inventory/iirusp.d.ts +5 -0
- package/dist/inventory/iirusp.js +5 -0
- package/dist/inventory/item.d.ts +5 -0
- package/dist/inventory/item.js +5 -0
- package/dist/inventory/itr.d.ts +5 -0
- package/dist/inventory/itr.js +5 -0
- package/dist/inventory/par.d.ts +5 -0
- package/dist/inventory/par.js +5 -0
- package/dist/inventory/po.d.ts +5 -0
- package/dist/inventory/po.js +5 -0
- package/dist/inventory/ppelc.d.ts +5 -0
- package/dist/inventory/ppelc.js +5 -0
- package/dist/inventory/pr.d.ts +5 -0
- package/dist/inventory/pr.js +6 -0
- package/dist/inventory/property-card.d.ts +5 -0
- package/dist/inventory/property-card.js +5 -0
- package/dist/inventory/ptr.d.ts +5 -0
- package/dist/inventory/ptr.js +5 -0
- package/dist/inventory/regspi.d.ts +5 -0
- package/dist/inventory/regspi.js +5 -0
- package/dist/inventory/ris.d.ts +5 -0
- package/dist/inventory/ris.js +5 -0
- package/dist/inventory/rlsddp.d.ts +5 -0
- package/dist/inventory/rlsddp.js +5 -0
- package/dist/inventory/rlsddsp.d.ts +5 -0
- package/dist/inventory/rlsddsp.js +5 -0
- package/dist/inventory/rpci.d.ts +5 -0
- package/dist/inventory/rpci.js +5 -0
- package/dist/inventory/rpcppe.d.ts +5 -0
- package/dist/inventory/rpcppe.js +5 -0
- package/dist/inventory/rpcsp.d.ts +5 -0
- package/dist/inventory/rpcsp.js +5 -0
- package/dist/inventory/rrsp.d.ts +5 -0
- package/dist/inventory/rrsp.js +5 -0
- package/dist/inventory/rsmi.d.ts +5 -0
- package/dist/inventory/rsmi.js +5 -0
- package/dist/inventory/rsmp.d.ts +5 -0
- package/dist/inventory/rsmp.js +5 -0
- package/dist/inventory/rspi.d.ts +5 -0
- package/dist/inventory/rspi.js +5 -0
- package/dist/inventory/spc.d.ts +5 -0
- package/dist/inventory/spc.js +5 -0
- package/dist/inventory/splc.d.ts +5 -0
- package/dist/inventory/splc.js +5 -0
- package/dist/inventory/stock-card.d.ts +5 -0
- package/dist/inventory/stock-card.js +5 -0
- package/dist/inventory/wmr.d.ts +5 -0
- package/dist/inventory/wmr.js +5 -0
- package/dist/reports/pr/_components/document-preview.js +5 -2
- package/dist/styles.css +148 -0
- package/package.json +5 -1
package/FORM_CATALOG.md
CHANGED
|
@@ -42,3 +42,7 @@ Additional extracted components outside the reports directory:
|
|
|
42
42
|
Purchase Order receives eligible purchase requests, approver display data and the generated PO number from the host. It does not query or authorize those records itself. Inventory item types are exported as `Inventory` and `InventoryStatus`.
|
|
43
43
|
|
|
44
44
|
`extraction-manifest.json` records original source paths and SHA-256 hashes for traceability. Most source components are copied with import rewrites; the PO and RSMP forms were separated from their page/modal shells. Agency branding and remote font loading were removed where found. These are extracted application templates, not a guarantee that every agency accepts an identical document layout.
|
|
45
|
+
|
|
46
|
+
## Document viewers
|
|
47
|
+
|
|
48
|
+
Every inventory entry exports `PreviewDialog` and `PreviewPanel` in addition to the existing `Preview`. Pass that preview’s typed props in `previewProps`. Both include PDF download and print controls; PR includes its XLSX exporter automatically. Other forms accept an optional `onExportXlsx` callback. Import `inventory/styles.css` once. See README for integration.
|
package/README.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
An installable React 19 library extracted from BCS IMS. The npm package is `@tonzxz/government-forms`; its inventory entry point is `@tonzxz/government-forms/inventory`. The package is configured for public npm distribution.
|
|
4
4
|
|
|
5
|
+
## Document preview with PDF, XLSX, and print (0.2.0)
|
|
6
|
+
|
|
7
|
+
`Preview` is the printable document layout. `PreviewDialog` adds the scrollable modal and export toolbar shown in the original system. `PreviewPanel` embeds the same viewer directly on a page. All `/inventory/<code>` paths expose these components, including `/inventory/pplc`.
|
|
8
|
+
|
|
9
|
+
Import the package CSS once as described below. In Next.js, use the viewer from a client component:
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
"use client";
|
|
13
|
+
import { useState } from "react";
|
|
14
|
+
import {
|
|
15
|
+
PreviewDialog,
|
|
16
|
+
type PrRecord,
|
|
17
|
+
type PrSignatories,
|
|
18
|
+
} from "@tonzxz/government-forms/inventory/pr";
|
|
19
|
+
|
|
20
|
+
export function PurchaseRequestDetails({
|
|
21
|
+
record,
|
|
22
|
+
signatories,
|
|
23
|
+
}: {
|
|
24
|
+
record: PrRecord;
|
|
25
|
+
signatories?: PrSignatories;
|
|
26
|
+
}) {
|
|
27
|
+
const [open, setOpen] = useState(false);
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
<button type="button" onClick={() => setOpen(true)}>
|
|
31
|
+
View purchase request
|
|
32
|
+
</button>
|
|
33
|
+
<PreviewDialog
|
|
34
|
+
open={open}
|
|
35
|
+
onOpenChange={setOpen}
|
|
36
|
+
filename={record.prNo}
|
|
37
|
+
previewProps={{ record, signatories }}
|
|
38
|
+
/>
|
|
39
|
+
</>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Pass your API record to `record`; document numbers, agency details, line items, and signatories come from your ERP. The viewer does not fetch or save data. PR includes **Download XLSX**, **Download PDF**, **Print**, and **Close**. Other viewers include PDF and print; supply `onExportXlsx` to enable your spreadsheet exporter. The on-screen preview is the original HTML paper layout; PDF download renders that layout in the browser. PR documents automatically split after 12 items per page so later items remain visible and exportable.
|
|
45
|
+
|
|
46
|
+
For an embedded viewer, use `PreviewPanel` from the same import path with `previewProps={{ record, signatories }}`. Each form retains its own preview props; TypeScript shows the required fields. `pplc` uses its ledger preview props, not `PrRecord`.
|
|
47
|
+
|
|
48
|
+
To show a **Preview document** button beside the generic form's submit button, pass `preview={<Preview record={record} signatories={signatories} />}` and `previewFilename={record.prNo}` to `PRForm`, importing `Preview` from the PR path. Update that record from your controlled form values for a live draft preview. Supply `onExportXlsx` on `PRForm` if you also want its spreadsheet button; the PR `PreviewDialog` and `PreviewPanel` wire the exporter automatically.
|
|
49
|
+
|
|
50
|
+
The generic six-field PR payload is not a complete `PrRecord`. Map your draft or saved ERP data explicitly, or use the dedicated `PurchaseRequestCreateForm` for the fuller entry layout. Installing the update alone does not add a preview to an existing ERP page: render one of these viewer components.
|
|
51
|
+
|
|
52
|
+
Custom document layouts can use `DocumentPreviewDialog` or `DocumentPreviewPanel` from `@tonzxz/government-forms/inventory/preview` and pass the printable layout as `children`.
|
|
53
|
+
|
|
54
|
+
|
|
5
55
|
## Included
|
|
6
56
|
|
|
7
57
|
- 25 configurable report definitions, available through `GovernmentForm`.
|
|
@@ -22,7 +72,7 @@ npm install @tonzxz/government-forms react@^19 react-dom@^19
|
|
|
22
72
|
Before publishing, install the generated archive in a different repository:
|
|
23
73
|
|
|
24
74
|
```sh
|
|
25
|
-
npm install /absolute/path/to/tonzxz-government-forms-0.
|
|
75
|
+
npm install /absolute/path/to/tonzxz-government-forms-0.2.0.tgz
|
|
26
76
|
```
|
|
27
77
|
|
|
28
78
|
The public package can be installed without npm authentication. Consumers use the exact same package version independently; deployments and databases stay separate.
|
|
@@ -43,7 +93,7 @@ const [value, setValue] = useState(() => createFormValues(definition));
|
|
|
43
93
|
<PRForm value={value} onChange={setValue} onSubmit={savePurchaseRequest} />;
|
|
44
94
|
```
|
|
45
95
|
|
|
46
|
-
Every report code in the catalog has an `/inventory/<code>` entry. Each exports its configurable form as both `default` and `Form`, plus `definition`, `Preview`, and the original named preview. Dedicated entry components are also exported where available. `Preview` and dedicated entry components retain their own typed props; their data models differ from the generic form payload.
|
|
96
|
+
Every report code in the catalog has an `/inventory/<code>` entry. Each exports its configurable form as both `default` and `Form`, plus `definition`, `Preview`, `PreviewDialog`, `PreviewPanel`, and the original named preview. Dedicated entry components are also exported where available. `Preview` and dedicated entry components retain their own typed props; their data models differ from the generic form payload.
|
|
47
97
|
|
|
48
98
|
`/inventory/pplc` is an alias for the existing PPELC form (`/inventory/ppelc`); its document code stays `ppelc`. Additional paths `/inventory/po` and `/inventory/item` export their dedicated entry components as `default`/`Form` and their previews as `Preview`; these two do not have a generic `definition`. Existing root and `/forms/<code>` imports remain supported.
|
|
49
99
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ComponentType, type ReactNode } from 'react';
|
|
2
|
+
export type DocumentPreviewProps = {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
title?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
filename?: string;
|
|
7
|
+
/** Optional spreadsheet exporter supplied by the form or ERP integration. */
|
|
8
|
+
onExportXlsx?: () => void | Promise<void>;
|
|
9
|
+
className?: string;
|
|
10
|
+
};
|
|
11
|
+
export type DocumentPreviewDialogProps = DocumentPreviewProps & {
|
|
12
|
+
open: boolean;
|
|
13
|
+
onOpenChange: (open: boolean) => void;
|
|
14
|
+
};
|
|
15
|
+
/** Embedded paper preview with PDF/print actions. This displays the document layout, not a PDF iframe. */
|
|
16
|
+
export declare function DocumentPreviewPanel({ title, description, className, ...props }: DocumentPreviewProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
/** Accessible modal equivalent of the application's document-details viewer. */
|
|
18
|
+
export declare function DocumentPreviewDialog({ open, onOpenChange, title, description, className, ...props }: DocumentPreviewDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export type FormPreviewPanelProps<P extends object> = Omit<DocumentPreviewProps, 'children'> & {
|
|
20
|
+
previewProps: P;
|
|
21
|
+
};
|
|
22
|
+
export type FormPreviewDialogProps<P extends object> = Omit<DocumentPreviewDialogProps, 'children'> & {
|
|
23
|
+
previewProps: P;
|
|
24
|
+
};
|
|
25
|
+
/** Bind a viewer to each existing document's exact typed props. No record data is fabricated. */
|
|
26
|
+
export declare function createDocumentPreviewComponents<P extends object>(Preview: ComponentType<P>, defaults: {
|
|
27
|
+
title: string;
|
|
28
|
+
filename: string;
|
|
29
|
+
}, exportXlsx?: (props: P) => void | Promise<void>): {
|
|
30
|
+
PreviewPanel: ({ previewProps, ...props }: FormPreviewPanelProps<P>) => import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
PreviewDialog: ({ previewProps, ...props }: FormPreviewDialogProps<P>) => import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useRef, useState } from 'react';
|
|
4
|
+
import { Dialog } from '@base-ui/react/dialog';
|
|
5
|
+
function PreviewBody({ children, filename = 'document', onExportXlsx, close }) {
|
|
6
|
+
const paper = useRef(null);
|
|
7
|
+
const lock = useRef(false);
|
|
8
|
+
const [busy, setBusy] = useState(null);
|
|
9
|
+
const [error, setError] = useState('');
|
|
10
|
+
async function perform(action) {
|
|
11
|
+
if (lock.current || !paper.current)
|
|
12
|
+
return;
|
|
13
|
+
lock.current = true;
|
|
14
|
+
setBusy(action);
|
|
15
|
+
setError('');
|
|
16
|
+
try {
|
|
17
|
+
if (action === 'xlsx')
|
|
18
|
+
await onExportXlsx?.();
|
|
19
|
+
else if (action === 'pdf') {
|
|
20
|
+
const { exportPreviewElementToPdf } = await import('./gam/utils/export-preview-pdf.js');
|
|
21
|
+
await exportPreviewElementToPdf(paper.current, filename.replace(/\.pdf$/i, '') + '.pdf');
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const { printElement } = await import('./gam/utils/print-element.js');
|
|
25
|
+
await printElement(paper.current, filename);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (cause) {
|
|
29
|
+
setError(cause instanceof Error ? cause.message : 'Unable to prepare the document. Please try again.');
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
lock.current = false;
|
|
33
|
+
setBusy(null);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return _jsxs(_Fragment, { children: [_jsx("div", { className: "qforms-preview-viewport", tabIndex: 0, "aria-label": "Document pages", children: _jsx("div", { ref: paper, className: "qforms-preview-paper", children: children }) }), error && _jsx("p", { role: "alert", className: "qforms-preview-error", children: error }), _jsxs("footer", { className: "qforms-preview-actions", "aria-busy": busy !== null, children: [_jsx("span", { role: "status", className: "qforms-preview-status", children: busy ? 'Preparing document…' : '' }), onExportXlsx && _jsx("button", { type: "button", disabled: busy !== null, onClick: () => void perform('xlsx'), children: "Download XLSX" }), _jsx("button", { type: "button", disabled: busy !== null, onClick: () => void perform('pdf'), children: "Download PDF" }), _jsx("button", { type: "button", disabled: busy !== null, onClick: () => void perform('print'), children: "Print" }), close] })] });
|
|
37
|
+
}
|
|
38
|
+
/** Embedded paper preview with PDF/print actions. This displays the document layout, not a PDF iframe. */
|
|
39
|
+
export function DocumentPreviewPanel({ title = 'Document preview', description = 'Preview the document before downloading or printing.', className = '', ...props }) {
|
|
40
|
+
return _jsxs("section", { className: `qforms-preview-panel ${className}`, "aria-label": title, children: [_jsxs("header", { className: "qforms-preview-header", children: [_jsx("h2", { children: title }), _jsx("p", { children: description })] }), _jsx(PreviewBody, { ...props })] });
|
|
41
|
+
}
|
|
42
|
+
/** Accessible modal equivalent of the application's document-details viewer. */
|
|
43
|
+
export function DocumentPreviewDialog({ open, onOpenChange, title = 'Document preview', description = 'Read-only view of the document.', className = '', ...props }) {
|
|
44
|
+
return _jsx(Dialog.Root, { open: open, onOpenChange: onOpenChange, children: _jsxs(Dialog.Portal, { children: [_jsx(Dialog.Backdrop, { className: "qforms-preview-backdrop" }), _jsxs(Dialog.Popup, { className: `qforms-preview-dialog ${className}`, children: [_jsxs("header", { className: "qforms-preview-header", children: [_jsx(Dialog.Title, { children: title }), _jsx(Dialog.Description, { children: description }), _jsx(Dialog.Close, { className: "qforms-preview-dismiss", "aria-label": "Close document preview", children: "\u00D7" })] }), _jsx(PreviewBody, { ...props, close: _jsx(Dialog.Close, { className: "qforms-preview-close", children: "Close" }) })] })] }) });
|
|
45
|
+
}
|
|
46
|
+
/** Bind a viewer to each existing document's exact typed props. No record data is fabricated. */
|
|
47
|
+
export function createDocumentPreviewComponents(Preview, defaults, exportXlsx) {
|
|
48
|
+
function PreviewPanel({ previewProps, ...props }) {
|
|
49
|
+
return _jsx(DocumentPreviewPanel, { ...defaults, onExportXlsx: exportXlsx ? () => exportXlsx(previewProps) : undefined, ...props, children: _jsx(Preview, { ...previewProps }) });
|
|
50
|
+
}
|
|
51
|
+
function PreviewDialog({ previewProps, ...props }) {
|
|
52
|
+
return _jsx(DocumentPreviewDialog, { ...defaults, onExportXlsx: exportXlsx ? () => exportXlsx(previewProps) : undefined, ...props, children: _jsx(Preview, { ...previewProps }) });
|
|
53
|
+
}
|
|
54
|
+
return { PreviewPanel, PreviewDialog };
|
|
55
|
+
}
|
|
@@ -129,46 +129,53 @@ export async function renderPreviewToCanvas(root) {
|
|
|
129
129
|
// html2canvas's cloned iframe and can crop wrapped table text.
|
|
130
130
|
const pageWidth = Math.ceil(Math.max(pageRect.width, page.scrollWidth));
|
|
131
131
|
const pageHeight = Math.ceil(Math.max(pageRect.height, page.scrollHeight));
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
// an opaque header or cell layer over labels and values. Both PDF export
|
|
159
|
-
// and printing use this capture path.
|
|
160
|
-
const clonedIcsPage = clonedPage.matches('[data-ics-preview="true"]')
|
|
161
|
-
? clonedPage
|
|
162
|
-
: clonedPage.querySelector('[data-ics-preview="true"]');
|
|
163
|
-
if (clonedIcsPage) {
|
|
164
|
-
const tableLayers = clonedIcsPage.querySelectorAll("table, thead, tbody, tr, th, td");
|
|
165
|
-
for (const layer of tableLayers) {
|
|
166
|
-
layer.style.setProperty("background", "transparent", "important");
|
|
167
|
-
layer.style.setProperty("background-color", "transparent", "important");
|
|
132
|
+
// html2canvas measures font baselines with a hidden 1px image in the live
|
|
133
|
+
// document. Tailwind's block-image reset breaks that inline baseline probe.
|
|
134
|
+
// Restrict this temporary override to the probe, preserving document images.
|
|
135
|
+
const metricsStyle = document.createElement('style');
|
|
136
|
+
metricsStyle.textContent = 'body > div[style*="visibility: hidden"] > img[width="1"][height="1"] { display: inline !important; }';
|
|
137
|
+
document.head.appendChild(metricsStyle);
|
|
138
|
+
try {
|
|
139
|
+
const canvas = await html2canvas(page, {
|
|
140
|
+
backgroundColor: "#fff",
|
|
141
|
+
scale: Math.min(Math.max(window.devicePixelRatio || 2, 2), 3),
|
|
142
|
+
useCORS: true,
|
|
143
|
+
scrollX: 0,
|
|
144
|
+
scrollY: -window.scrollY,
|
|
145
|
+
width: pageWidth,
|
|
146
|
+
height: pageHeight,
|
|
147
|
+
windowWidth: pageWidth,
|
|
148
|
+
windowHeight: pageHeight,
|
|
149
|
+
onclone: (clonedDocument, clonedPage) => {
|
|
150
|
+
// Preview ancestors carry screen-only scaling and clipping. Remove those
|
|
151
|
+
// from the capture so text and borders use the same natural coordinates.
|
|
152
|
+
let ancestor = clonedPage;
|
|
153
|
+
while (ancestor) {
|
|
154
|
+
ancestor.style.setProperty("transform", "none", "important");
|
|
155
|
+
ancestor.style.setProperty("zoom", "1", "important");
|
|
156
|
+
ancestor.style.setProperty("overflow", "visible", "important");
|
|
157
|
+
ancestor = ancestor.parentElement;
|
|
168
158
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
159
|
+
// html2canvas 1.4.1 can't parse lab()/oklch()/lch() — Tailwind v4 uses them
|
|
160
|
+
// inside generated stylesheets. Resolve them to rgb() in the clone before
|
|
161
|
+
// html2canvas reads computed styles.
|
|
162
|
+
sanitizeUnsupportedColorFunctions(clonedDocument, createUnsupportedColorNormalizer());
|
|
163
|
+
// ICS uses the page itself as its white paper background. Clear every
|
|
164
|
+
// structural table fill in the capture clone so html2canvas cannot paint
|
|
165
|
+
// an opaque header or cell layer over labels and values. Both PDF export
|
|
166
|
+
// and printing use this capture path.
|
|
167
|
+
const clonedIcsPage = clonedPage.matches('[data-ics-preview="true"]')
|
|
168
|
+
? clonedPage
|
|
169
|
+
: clonedPage.querySelector('[data-ics-preview="true"]');
|
|
170
|
+
if (clonedIcsPage) {
|
|
171
|
+
const tableLayers = clonedIcsPage.querySelectorAll("table, thead, tbody, tr, th, td");
|
|
172
|
+
for (const layer of tableLayers) {
|
|
173
|
+
layer.style.setProperty("background", "transparent", "important");
|
|
174
|
+
layer.style.setProperty("background-color", "transparent", "important");
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const style = clonedDocument.createElement("style");
|
|
178
|
+
style.textContent = `
|
|
172
179
|
html, body {
|
|
173
180
|
background: #fff !important;
|
|
174
181
|
}
|
|
@@ -183,10 +190,14 @@ export async function renderPreviewToCanvas(root) {
|
|
|
183
190
|
transform: none !important;
|
|
184
191
|
}
|
|
185
192
|
`;
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
193
|
+
clonedDocument.head.appendChild(style);
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
return { canvas, orientation, fitOnePage };
|
|
197
|
+
}
|
|
198
|
+
finally {
|
|
199
|
+
metricsStyle.remove();
|
|
200
|
+
}
|
|
190
201
|
}
|
|
191
202
|
export async function exportPreviewElementToPdf(root, filename) {
|
|
192
203
|
const pages = Array.from(root.querySelectorAll(PDF_PAGE_SELECTOR));
|
|
@@ -6,7 +6,7 @@ import { createRoot } from "react-dom/client";
|
|
|
6
6
|
* Opens the browser print dialog so the DOCUMENT FORM itself is printed —
|
|
7
7
|
* never the screen, the modal, or anything else on the page.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* Rendering approach:
|
|
10
10
|
* - The preview is rendered with the SAME html2canvas pipeline the
|
|
11
11
|
* "Download PDF" buttons use. html2canvas captures ONLY the target element,
|
|
12
12
|
* so the modal/backdrop/app chrome are never part of the rendered output.
|
|
@@ -20,65 +20,45 @@ import { createRoot } from "react-dom/client";
|
|
|
20
20
|
* size or a letterboxed/whitespace layout.
|
|
21
21
|
*/
|
|
22
22
|
import { renderPreviewToCanvas } from "./export-preview-pdf.js";
|
|
23
|
-
|
|
24
|
-
const A4_PORTRAIT_MM = { width: 210, height: 297 };
|
|
25
|
-
const A4_LANDSCAPE_MM = { width: 297, height: 210 };
|
|
26
|
-
function buildPrintHtml({ imageSrc, title, landscape, }) {
|
|
23
|
+
function buildPrintHtml({ pages, title }) {
|
|
27
24
|
const safeTitle = title.replace(/[<>&"']/g, "");
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
margin: 0;
|
|
38
|
-
}
|
|
39
|
-
html, body {
|
|
40
|
-
margin: 0;
|
|
41
|
-
padding: 0;
|
|
42
|
-
background: #fff;
|
|
43
|
-
}
|
|
44
|
-
/* The print sheet is exactly A4, so the form fills the sheet with no
|
|
45
|
-
browser-default paper size (e.g. Letter) or letterboxing involved. */
|
|
46
|
-
.print-stage {
|
|
47
|
-
display: flex;
|
|
48
|
-
align-items: center;
|
|
49
|
-
justify-content: center;
|
|
50
|
-
width: ${pageMm.width}mm;
|
|
51
|
-
height: ${pageMm.height}mm;
|
|
52
|
-
background: #fff;
|
|
53
|
-
}
|
|
54
|
-
.print-stage img {
|
|
55
|
-
display: block;
|
|
56
|
-
width: 100%;
|
|
57
|
-
height: 100%;
|
|
58
|
-
object-fit: contain;
|
|
59
|
-
}
|
|
60
|
-
</style>
|
|
61
|
-
</head>
|
|
62
|
-
<body>
|
|
63
|
-
<div class="print-stage">
|
|
64
|
-
<img src="${imageSrc}" alt="" />
|
|
65
|
-
</div>
|
|
66
|
-
</body>
|
|
67
|
-
</html>`;
|
|
25
|
+
return `<!doctype html><html><head><meta charset="utf-8"><title>${safeTitle}</title><style>
|
|
26
|
+
@page portrait { size: A4 portrait; margin: 0; }
|
|
27
|
+
@page landscape { size: A4 landscape; margin: 0; }
|
|
28
|
+
html, body { margin: 0; padding: 0; background: white; }
|
|
29
|
+
.print-stage { width: 210mm; height: 297mm; page: portrait; break-after: page; }
|
|
30
|
+
.print-stage.landscape { width: 297mm; height: 210mm; page: landscape; }
|
|
31
|
+
.print-stage:last-child { break-after: auto; }
|
|
32
|
+
img { display: block; width: 100%; height: 100%; object-fit: contain; }
|
|
33
|
+
</style></head><body>${pages.map(page => `<div class="print-stage${page.landscape ? ' landscape' : ''}"><img src="${page.imageSrc}" alt=""></div>`).join('')}</body></html>`;
|
|
68
34
|
}
|
|
69
35
|
export async function printElement(root, title = "Document") {
|
|
70
36
|
const cleanTitle = title.replace(/\.pdf$/i, "").trim() || "Document";
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
37
|
+
const explicitPages = Array.from(root.querySelectorAll('[data-pdf-page="true"], .iar-a4-page, .itr-a4-page, .regspi-a4-page, .splc-a4-page, .spc-a4-page'));
|
|
38
|
+
const pages = [];
|
|
39
|
+
for (const element of explicitPages.length > 0 ? explicitPages : [root]) {
|
|
40
|
+
const { canvas, orientation, fitOnePage } = await renderPreviewToCanvas(element);
|
|
41
|
+
const landscape = orientation === 'landscape';
|
|
42
|
+
const pageHeight = fitOnePage ? canvas.height : canvas.width * (landscape ? 210 / 297 : 297 / 210);
|
|
43
|
+
for (let y = 0; y < canvas.height; y += pageHeight) {
|
|
44
|
+
const slice = document.createElement('canvas');
|
|
45
|
+
slice.width = canvas.width;
|
|
46
|
+
slice.height = Math.ceil(fitOnePage ? canvas.height : pageHeight);
|
|
47
|
+
const ctx = slice.getContext('2d');
|
|
48
|
+
if (!ctx)
|
|
49
|
+
throw new Error('Unable to prepare the print page.');
|
|
50
|
+
ctx.fillStyle = '#fff';
|
|
51
|
+
ctx.fillRect(0, 0, slice.width, slice.height);
|
|
52
|
+
const height = Math.min(pageHeight, canvas.height - y);
|
|
53
|
+
ctx.drawImage(canvas, 0, y, canvas.width, height, 0, 0, canvas.width, height);
|
|
54
|
+
pages.push({ imageSrc: slice.toDataURL('image/png'), landscape });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
77
57
|
const iframe = document.createElement("iframe");
|
|
78
58
|
// Off-screen but not display:none — some browsers refuse to print
|
|
79
59
|
// display:none iframes. Sized to A4 proportions so layout is computed.
|
|
80
60
|
iframe.style.cssText = "position:fixed;top:0;left:-10000px;width:794px;height:1123px;border:0;";
|
|
81
|
-
iframe.srcdoc = buildPrintHtml({
|
|
61
|
+
iframe.srcdoc = buildPrintHtml({ pages, title: cleanTitle });
|
|
82
62
|
iframe.setAttribute("aria-hidden", "true");
|
|
83
63
|
document.body.appendChild(iframe);
|
|
84
64
|
return new Promise(resolve => {
|
|
@@ -104,26 +84,26 @@ export async function printElement(root, title = "Document") {
|
|
|
104
84
|
cleanup();
|
|
105
85
|
return;
|
|
106
86
|
}
|
|
107
|
-
const
|
|
87
|
+
const images = Array.from(frameDocument.querySelectorAll("img"));
|
|
108
88
|
const firePrint = () => {
|
|
109
89
|
if (printTriggered)
|
|
110
90
|
return;
|
|
111
91
|
printTriggered = true;
|
|
112
92
|
frameWindow.focus();
|
|
93
|
+
frameWindow.addEventListener("afterprint", () => cleanup(), { once: true });
|
|
113
94
|
frameWindow.print();
|
|
114
95
|
// Chrome fires "afterprint" on the printed window once the dialog
|
|
115
96
|
// closes. Listen there so cleanup happens right after.
|
|
116
|
-
frameWindow.addEventListener("afterprint", () => cleanup());
|
|
117
97
|
};
|
|
118
|
-
if (image
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
98
|
+
if (images.some(image => !image.complete)) {
|
|
99
|
+
void Promise.all(images.map(image => image.complete ? Promise.resolve() : new Promise(resolve => {
|
|
100
|
+
image.addEventListener('load', () => resolve(), { once: true });
|
|
101
|
+
image.addEventListener('error', () => resolve(), { once: true });
|
|
102
|
+
}))).then(firePrint);
|
|
103
|
+
fallbackTimer = window.setTimeout(firePrint, 3000);
|
|
123
104
|
}
|
|
124
|
-
else
|
|
105
|
+
else
|
|
125
106
|
firePrint();
|
|
126
|
-
}
|
|
127
107
|
});
|
|
128
108
|
iframe.addEventListener("error", () => cleanup());
|
|
129
109
|
});
|
|
@@ -11,6 +11,11 @@ export type GovernmentFormProps = {
|
|
|
11
11
|
submitLabel?: string;
|
|
12
12
|
disabled?: boolean;
|
|
13
13
|
children?: ReactNode;
|
|
14
|
+
/** Supply the actual document preview and map the form data to its typed props. */
|
|
15
|
+
preview?: ReactNode;
|
|
16
|
+
previewTitle?: string;
|
|
17
|
+
previewFilename?: string;
|
|
18
|
+
onExportXlsx?: () => void | Promise<void>;
|
|
14
19
|
};
|
|
15
20
|
/** A controlled entry form for the repository's configurable report definitions. */
|
|
16
|
-
export declare function GovernmentForm({ code, definition, value, onChange, onSubmit, validate, submitLabel, disabled, children }: GovernmentFormProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export declare function GovernmentForm({ code, definition, value, onChange, onSubmit, validate, submitLabel, disabled, children, preview, previewTitle, previewFilename, onExportXlsx }: GovernmentFormProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/government-form.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useId, useRef, useState } from 'react';
|
|
4
|
+
import { DocumentPreviewDialog } from './document-preview.js';
|
|
4
5
|
import { formDefinitions, validateFormValues } from './definitions.js';
|
|
5
6
|
/** A controlled entry form for the repository's configurable report definitions. */
|
|
6
|
-
export function GovernmentForm({ code, definition = formDefinitions[code], value, onChange, onSubmit, validate, submitLabel = 'Save document', disabled = false, children }) {
|
|
7
|
+
export function GovernmentForm({ code, definition = formDefinitions[code], value, onChange, onSubmit, validate, submitLabel = 'Save document', disabled = false, children, preview, previewTitle, previewFilename, onExportXlsx }) {
|
|
7
8
|
const prefix = useId();
|
|
9
|
+
const [previewOpen, setPreviewOpen] = useState(false);
|
|
8
10
|
const saving = useRef(false);
|
|
9
11
|
const [pending, setPending] = useState(false);
|
|
10
12
|
const [errors, setErrors] = useState({});
|
|
@@ -41,5 +43,5 @@ export function GovernmentForm({ code, definition = formDefinitions[code], value
|
|
|
41
43
|
saving.current = false;
|
|
42
44
|
setPending(false);
|
|
43
45
|
}
|
|
44
|
-
}, children: [_jsxs("header", { className: "qforms-header", children: [_jsx("p", { className: "qforms-code", children: definition.reportCode }), _jsx("h2", { children: definition.title }), _jsx("p", { children: definition.description })] }), Object.keys(errors).length > 0 && _jsxs("div", { ref: summaryRef, tabIndex: -1, role: "alert", className: "qforms-errors", children: [_jsx("strong", { children: "Review the form before saving." }), _jsx("ul", { children: Object.entries(errors).map(([key, error]) => _jsx("li", { children: _jsx("a", { href: `#${prefix}-${key}`, children: error }) }, key)) })] }), _jsx("div", { className: "qforms-grid", children: definition.fields.map(field => input(field, value.values[field.id] ?? '', `values.${field.id}`, next => onChange({ ...value, values: { ...value.values, [field.id]: next } }))) }), !!definition.tableFields?.length && _jsxs("section", { className: "qforms-lines", "aria-label": "Line items", children: [_jsxs("div", { className: "qforms-line-heading", children: [_jsx("h3", { children: "Line items" }), _jsx("button", { type: "button", disabled: locked, onClick: () => onChange({ ...value, rows: [...value.rows, Object.fromEntries(definition.tableFields.map(field => [field.id, '']))] }), children: "Add item" })] }), value.rows.map((row, index) => _jsxs("fieldset", { className: "qforms-row", children: [_jsxs("legend", { children: ["Item ", index + 1] }), _jsx("div", { className: "qforms-grid", children: definition.tableFields.map(field => input(field, row[field.id] ?? '', `rows.${index}.${field.id}`, next => onChange({ ...value, rows: value.rows.map((item, i) => i === index ? { ...item, [field.id]: next } : item) }))) }), _jsx("button", { type: "button", disabled: locked, "aria-label": `Remove item ${index + 1}`, onClick: () => { setErrors({}); onChange({ ...value, rows: value.rows.filter((_, i) => i !== index) }); }, children: "Remove item" })] }, index))] }), children, saveError && _jsx("p", { role: "alert", className: "qforms-error", children: saveError }),
|
|
46
|
+
}, children: [_jsxs("header", { className: "qforms-header", children: [_jsx("p", { className: "qforms-code", children: definition.reportCode }), _jsx("h2", { children: definition.title }), _jsx("p", { children: definition.description })] }), Object.keys(errors).length > 0 && _jsxs("div", { ref: summaryRef, tabIndex: -1, role: "alert", className: "qforms-errors", children: [_jsx("strong", { children: "Review the form before saving." }), _jsx("ul", { children: Object.entries(errors).map(([key, error]) => _jsx("li", { children: _jsx("a", { href: `#${prefix}-${key}`, children: error }) }, key)) })] }), _jsx("div", { className: "qforms-grid", children: definition.fields.map(field => input(field, value.values[field.id] ?? '', `values.${field.id}`, next => onChange({ ...value, values: { ...value.values, [field.id]: next } }))) }), !!definition.tableFields?.length && _jsxs("section", { className: "qforms-lines", "aria-label": "Line items", children: [_jsxs("div", { className: "qforms-line-heading", children: [_jsx("h3", { children: "Line items" }), _jsx("button", { type: "button", disabled: locked, onClick: () => onChange({ ...value, rows: [...value.rows, Object.fromEntries(definition.tableFields.map(field => [field.id, '']))] }), children: "Add item" })] }), value.rows.map((row, index) => _jsxs("fieldset", { className: "qforms-row", children: [_jsxs("legend", { children: ["Item ", index + 1] }), _jsx("div", { className: "qforms-grid", children: definition.tableFields.map(field => input(field, row[field.id] ?? '', `rows.${index}.${field.id}`, next => onChange({ ...value, rows: value.rows.map((item, i) => i === index ? { ...item, [field.id]: next } : item) }))) }), _jsx("button", { type: "button", disabled: locked, "aria-label": `Remove item ${index + 1}`, onClick: () => { setErrors({}); onChange({ ...value, rows: value.rows.filter((_, i) => i !== index) }); }, children: "Remove item" })] }, index))] }), children, saveError && _jsx("p", { role: "alert", className: "qforms-error", children: saveError }), _jsxs("footer", { children: [preview != null && _jsx("button", { type: "button", onClick: () => setPreviewOpen(true), children: "Preview document" }), _jsx("button", { type: "submit", disabled: locked, children: pending ? 'Saving…' : submitLabel })] }), preview != null && _jsx(DocumentPreviewDialog, { open: previewOpen, onOpenChange: setPreviewOpen, title: previewTitle ?? `${definition.title} — Document preview`, filename: previewFilename ?? definition.reportCode, onExportXlsx: onExportXlsx, children: preview })] });
|
|
45
47
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -47,3 +47,5 @@ export * from './inventory/components/inventory-item-form.js';
|
|
|
47
47
|
export * from './inventory/components/inventory-item-preview.js';
|
|
48
48
|
export * from './inventory/types.js';
|
|
49
49
|
export * from './gam/components/purchase-order-page-client.js';
|
|
50
|
+
export { DocumentPreviewDialog, DocumentPreviewPanel } from './document-preview.js';
|
|
51
|
+
export type { DocumentPreviewProps, DocumentPreviewDialogProps, FormPreviewDialogProps, FormPreviewPanelProps } from './document-preview.js';
|
package/dist/index.js
CHANGED
|
@@ -48,3 +48,4 @@ export * from './inventory/components/inventory-item-form.js';
|
|
|
48
48
|
export * from './inventory/components/inventory-item-preview.js';
|
|
49
49
|
export * from './inventory/types.js';
|
|
50
50
|
export * from './gam/components/purchase-order-page-client.js';
|
|
51
|
+
export { DocumentPreviewDialog, DocumentPreviewPanel } from './document-preview.js';
|
package/dist/inventory/iar.d.ts
CHANGED
|
@@ -2,3 +2,8 @@ export { Form, Form as default, definition } from '../forms/iar.js';
|
|
|
2
2
|
export { IarDocumentPreview, IarDocumentPreview as Preview } from '../reports/iar/_components/document-preview.js';
|
|
3
3
|
export { IarCreateForm } from '../reports/iar/_components/create-form.js';
|
|
4
4
|
export type * from '../reports/iar/types.js';
|
|
5
|
+
import { IarDocumentPreview as PreviewComponent } from '../reports/iar/_components/document-preview.js';
|
|
6
|
+
import type { ComponentType, ComponentProps } from 'react';
|
|
7
|
+
import type { FormPreviewDialogProps, FormPreviewPanelProps } from '../document-preview.js';
|
|
8
|
+
export declare const PreviewDialog: ComponentType<FormPreviewDialogProps<ComponentProps<typeof PreviewComponent>>>;
|
|
9
|
+
export declare const PreviewPanel: ComponentType<FormPreviewPanelProps<ComponentProps<typeof PreviewComponent>>>;
|
package/dist/inventory/iar.js
CHANGED
|
@@ -2,3 +2,8 @@
|
|
|
2
2
|
export { Form, Form as default, definition } from '../forms/iar.js';
|
|
3
3
|
export { IarDocumentPreview, IarDocumentPreview as Preview } from '../reports/iar/_components/document-preview.js';
|
|
4
4
|
export { IarCreateForm } from '../reports/iar/_components/create-form.js';
|
|
5
|
+
import { IarDocumentPreview as PreviewComponent } from '../reports/iar/_components/document-preview.js';
|
|
6
|
+
import { createDocumentPreviewComponents } from '../document-preview.js';
|
|
7
|
+
const previewComponents = createDocumentPreviewComponents(PreviewComponent, { title: 'IAR document preview', filename: 'iar' });
|
|
8
|
+
export const PreviewDialog = previewComponents.PreviewDialog;
|
|
9
|
+
export const PreviewPanel = previewComponents.PreviewPanel;
|
package/dist/inventory/ics.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
export { Form, Form as default, definition } from '../forms/ics.js';
|
|
2
2
|
export { IcsPreview, IcsPreview as Preview } from '../gam/components/ics-preview.js';
|
|
3
|
+
import { IcsPreview as PreviewComponent } from '../gam/components/ics-preview.js';
|
|
4
|
+
import type { ComponentType, ComponentProps } from 'react';
|
|
5
|
+
import type { FormPreviewDialogProps, FormPreviewPanelProps } from '../document-preview.js';
|
|
6
|
+
export declare const PreviewDialog: ComponentType<FormPreviewDialogProps<ComponentProps<typeof PreviewComponent>>>;
|
|
7
|
+
export declare const PreviewPanel: ComponentType<FormPreviewPanelProps<ComponentProps<typeof PreviewComponent>>>;
|
package/dist/inventory/ics.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
export { Form, Form as default, definition } from '../forms/ics.js';
|
|
3
3
|
export { IcsPreview, IcsPreview as Preview } from '../gam/components/ics-preview.js';
|
|
4
|
+
import { IcsPreview as PreviewComponent } from '../gam/components/ics-preview.js';
|
|
5
|
+
import { createDocumentPreviewComponents } from '../document-preview.js';
|
|
6
|
+
const previewComponents = createDocumentPreviewComponents(PreviewComponent, { title: 'ICS document preview', filename: 'ics' });
|
|
7
|
+
export const PreviewDialog = previewComponents.PreviewDialog;
|
|
8
|
+
export const PreviewPanel = previewComponents.PreviewPanel;
|
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
export { Form, Form as default, definition } from '../forms/iirup.js';
|
|
2
2
|
export { IirupPreview, IirupPreview as Preview } from '../gam/components/iirup-preview.js';
|
|
3
|
+
import { IirupPreview as PreviewComponent } from '../gam/components/iirup-preview.js';
|
|
4
|
+
import type { ComponentType, ComponentProps } from 'react';
|
|
5
|
+
import type { FormPreviewDialogProps, FormPreviewPanelProps } from '../document-preview.js';
|
|
6
|
+
export declare const PreviewDialog: ComponentType<FormPreviewDialogProps<ComponentProps<typeof PreviewComponent>>>;
|
|
7
|
+
export declare const PreviewPanel: ComponentType<FormPreviewPanelProps<ComponentProps<typeof PreviewComponent>>>;
|
package/dist/inventory/iirup.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
export { Form, Form as default, definition } from '../forms/iirup.js';
|
|
3
3
|
export { IirupPreview, IirupPreview as Preview } from '../gam/components/iirup-preview.js';
|
|
4
|
+
import { IirupPreview as PreviewComponent } from '../gam/components/iirup-preview.js';
|
|
5
|
+
import { createDocumentPreviewComponents } from '../document-preview.js';
|
|
6
|
+
const previewComponents = createDocumentPreviewComponents(PreviewComponent, { title: 'IIRUP document preview', filename: 'iirup' });
|
|
7
|
+
export const PreviewDialog = previewComponents.PreviewDialog;
|
|
8
|
+
export const PreviewPanel = previewComponents.PreviewPanel;
|
|
@@ -2,3 +2,8 @@ export { Form, Form as default, definition } from '../forms/iirusp.js';
|
|
|
2
2
|
export { IiruspDocumentPreview, IiruspDocumentPreview as Preview } from '../reports/iirusp/_components/document-preview.js';
|
|
3
3
|
export { IiruspCreateForm } from '../reports/iirusp/_components/create-form.js';
|
|
4
4
|
export type * from '../reports/iirusp/types.js';
|
|
5
|
+
import { IiruspDocumentPreview as PreviewComponent } from '../reports/iirusp/_components/document-preview.js';
|
|
6
|
+
import type { ComponentType, ComponentProps } from 'react';
|
|
7
|
+
import type { FormPreviewDialogProps, FormPreviewPanelProps } from '../document-preview.js';
|
|
8
|
+
export declare const PreviewDialog: ComponentType<FormPreviewDialogProps<ComponentProps<typeof PreviewComponent>>>;
|
|
9
|
+
export declare const PreviewPanel: ComponentType<FormPreviewPanelProps<ComponentProps<typeof PreviewComponent>>>;
|
package/dist/inventory/iirusp.js
CHANGED
|
@@ -2,3 +2,8 @@
|
|
|
2
2
|
export { Form, Form as default, definition } from '../forms/iirusp.js';
|
|
3
3
|
export { IiruspDocumentPreview, IiruspDocumentPreview as Preview } from '../reports/iirusp/_components/document-preview.js';
|
|
4
4
|
export { IiruspCreateForm } from '../reports/iirusp/_components/create-form.js';
|
|
5
|
+
import { IiruspDocumentPreview as PreviewComponent } from '../reports/iirusp/_components/document-preview.js';
|
|
6
|
+
import { createDocumentPreviewComponents } from '../document-preview.js';
|
|
7
|
+
const previewComponents = createDocumentPreviewComponents(PreviewComponent, { title: 'IIRUSP document preview', filename: 'iirusp' });
|
|
8
|
+
export const PreviewDialog = previewComponents.PreviewDialog;
|
|
9
|
+
export const PreviewPanel = previewComponents.PreviewPanel;
|
package/dist/inventory/item.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
export { InventoryItemForm as default, InventoryItemForm as Form, InventoryItemForm } from './components/inventory-item-form.js';
|
|
2
2
|
export { InventoryItemPreview as Preview, InventoryItemPreview } from './components/inventory-item-preview.js';
|
|
3
3
|
export type * from './types.js';
|
|
4
|
+
import { InventoryItemPreview as PreviewComponent } from './components/inventory-item-preview.js';
|
|
5
|
+
import type { ComponentType, ComponentProps } from 'react';
|
|
6
|
+
import type { FormPreviewDialogProps, FormPreviewPanelProps } from '../document-preview.js';
|
|
7
|
+
export declare const PreviewDialog: ComponentType<FormPreviewDialogProps<ComponentProps<typeof PreviewComponent>>>;
|
|
8
|
+
export declare const PreviewPanel: ComponentType<FormPreviewPanelProps<ComponentProps<typeof PreviewComponent>>>;
|
package/dist/inventory/item.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
export { InventoryItemForm as default, InventoryItemForm as Form, InventoryItemForm } from './components/inventory-item-form.js';
|
|
3
3
|
export { InventoryItemPreview as Preview, InventoryItemPreview } from './components/inventory-item-preview.js';
|
|
4
|
+
import { InventoryItemPreview as PreviewComponent } from './components/inventory-item-preview.js';
|
|
5
|
+
import { createDocumentPreviewComponents } from '../document-preview.js';
|
|
6
|
+
const previewComponents = createDocumentPreviewComponents(PreviewComponent, { title: 'ITEM document preview', filename: 'item' });
|
|
7
|
+
export const PreviewDialog = previewComponents.PreviewDialog;
|
|
8
|
+
export const PreviewPanel = previewComponents.PreviewPanel;
|
package/dist/inventory/itr.d.ts
CHANGED
|
@@ -2,3 +2,8 @@ export { Form, Form as default, definition } from '../forms/itr.js';
|
|
|
2
2
|
export { ItrPreview, ItrPreview as Preview } from '../gam/components/itr-preview.js';
|
|
3
3
|
export { CreateForm as ItrCreateForm } from '../reports/itr/_components/create-form.js';
|
|
4
4
|
export type * from '../reports/itr/types.js';
|
|
5
|
+
import { ItrPreview as PreviewComponent } from '../gam/components/itr-preview.js';
|
|
6
|
+
import type { ComponentType, ComponentProps } from 'react';
|
|
7
|
+
import type { FormPreviewDialogProps, FormPreviewPanelProps } from '../document-preview.js';
|
|
8
|
+
export declare const PreviewDialog: ComponentType<FormPreviewDialogProps<ComponentProps<typeof PreviewComponent>>>;
|
|
9
|
+
export declare const PreviewPanel: ComponentType<FormPreviewPanelProps<ComponentProps<typeof PreviewComponent>>>;
|
package/dist/inventory/itr.js
CHANGED
|
@@ -2,3 +2,8 @@
|
|
|
2
2
|
export { Form, Form as default, definition } from '../forms/itr.js';
|
|
3
3
|
export { ItrPreview, ItrPreview as Preview } from '../gam/components/itr-preview.js';
|
|
4
4
|
export { CreateForm as ItrCreateForm } from '../reports/itr/_components/create-form.js';
|
|
5
|
+
import { ItrPreview as PreviewComponent } from '../gam/components/itr-preview.js';
|
|
6
|
+
import { createDocumentPreviewComponents } from '../document-preview.js';
|
|
7
|
+
const previewComponents = createDocumentPreviewComponents(PreviewComponent, { title: 'ITR document preview', filename: 'itr' });
|
|
8
|
+
export const PreviewDialog = previewComponents.PreviewDialog;
|
|
9
|
+
export const PreviewPanel = previewComponents.PreviewPanel;
|