medical-form-printer 0.1.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/LICENSE +21 -0
- package/README.md +548 -0
- package/README.zh-CN.md +548 -0
- package/dist/index.cjs +4485 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3188 -0
- package/dist/index.d.ts +3188 -0
- package/dist/index.js +4349 -0
- package/dist/index.js.map +1 -0
- package/dist/node.cjs +4555 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +3219 -0
- package/dist/node.d.ts +3219 -0
- package/dist/node.js +4417 -0
- package/dist/node.js.map +1 -0
- package/package.json +107 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 wangchengshi-ship-it
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
# medical-form-printer
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/medical-form-printer)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
|
|
7
|
+
A schema-driven medical form print renderer that transforms structured form data into printable HTML and PDF documents. Designed for healthcare applications requiring professional document generation with support for complex layouts, smart pagination, and cross-environment consistency.
|
|
8
|
+
|
|
9
|
+
[δΈζζζ‘£](./README.zh-CN.md)
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- π¨οΈ **Dual Environment** - Works seamlessly in both browser and Node.js
|
|
14
|
+
- π **Rich Section Types** - Info grids, data tables, checkbox grids, signature areas, notes, and more
|
|
15
|
+
- π¨ **Theme Customization** - Fully customizable fonts, colors, spacing, and sizing
|
|
16
|
+
- π **PDF Generation** - High-fidelity PDF output via Puppeteer (Node.js)
|
|
17
|
+
- π **PDF Merging** - Combine multiple documents into a single PDF
|
|
18
|
+
- π **Smart Pagination** - Automatic page breaks with header repetition and overflow handling
|
|
19
|
+
- π **CSS Isolation** - Embedded fonts and namespaced styles for consistent rendering
|
|
20
|
+
- π **Extensible** - Register custom section renderers for specialized content
|
|
21
|
+
- π¦ **TypeScript First** - Full type definitions with comprehensive JSDoc documentation
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# npm
|
|
27
|
+
npm install medical-form-printer
|
|
28
|
+
|
|
29
|
+
# yarn
|
|
30
|
+
yarn add medical-form-printer
|
|
31
|
+
|
|
32
|
+
# pnpm
|
|
33
|
+
pnpm add medical-form-printer
|
|
34
|
+
|
|
35
|
+
# bun
|
|
36
|
+
bun add medical-form-printer
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
For PDF generation in Node.js, install Puppeteer as a peer dependency:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install puppeteer
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
### Browser Usage
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { renderToHtml } from 'medical-form-printer'
|
|
51
|
+
|
|
52
|
+
const printSchema = {
|
|
53
|
+
pageSize: 'A4',
|
|
54
|
+
orientation: 'portrait',
|
|
55
|
+
header: {
|
|
56
|
+
hospital: 'Sample Hospital',
|
|
57
|
+
department: 'Postpartum Care Center',
|
|
58
|
+
title: 'Patient Assessment Form',
|
|
59
|
+
},
|
|
60
|
+
sections: [
|
|
61
|
+
{
|
|
62
|
+
type: 'info-grid',
|
|
63
|
+
config: {
|
|
64
|
+
columns: 4,
|
|
65
|
+
rows: [
|
|
66
|
+
{
|
|
67
|
+
cells: [
|
|
68
|
+
{ label: 'Name', field: 'name', type: 'text' },
|
|
69
|
+
{ label: 'Age', field: 'age', type: 'number' },
|
|
70
|
+
{ label: 'Date', field: 'admissionDate', type: 'date' },
|
|
71
|
+
{ label: 'Room', field: 'roomNumber', type: 'text' },
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
footer: {
|
|
79
|
+
showPageNumber: true
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const formData = {
|
|
84
|
+
name: 'Jane Doe',
|
|
85
|
+
age: 28,
|
|
86
|
+
admissionDate: '2024-01-15',
|
|
87
|
+
roomNumber: 'A-101'
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Render to HTML
|
|
91
|
+
const html = renderToHtml(printSchema, formData, {
|
|
92
|
+
watermark: 'Internal Use Only'
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
// Display in iframe or div
|
|
96
|
+
document.getElementById('preview').innerHTML = html
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Node.js Usage (PDF Generation)
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { renderToPdf, mergePdfs } from 'medical-form-printer/node'
|
|
103
|
+
import fs from 'fs'
|
|
104
|
+
|
|
105
|
+
// Generate single PDF
|
|
106
|
+
const pdfBuffer = await renderToPdf(printSchema, formData, {
|
|
107
|
+
watermark: 'Confidential'
|
|
108
|
+
})
|
|
109
|
+
fs.writeFileSync('assessment.pdf', pdfBuffer)
|
|
110
|
+
|
|
111
|
+
// Merge multiple forms into one PDF
|
|
112
|
+
const mergedPdf = await mergePdfs([
|
|
113
|
+
{ schema: maternalSchema, data: maternalData },
|
|
114
|
+
{ schema: newbornSchema, data: newbornData },
|
|
115
|
+
])
|
|
116
|
+
fs.writeFileSync('complete-record.pdf', mergedPdf)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## API Reference
|
|
120
|
+
|
|
121
|
+
### Core Rendering
|
|
122
|
+
|
|
123
|
+
#### `renderToHtml(schema, data, options?)`
|
|
124
|
+
|
|
125
|
+
Renders a print schema with form data to an HTML string.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { renderToHtml } from 'medical-form-printer'
|
|
129
|
+
|
|
130
|
+
const html = renderToHtml(printSchema, formData, {
|
|
131
|
+
theme: customTheme,
|
|
132
|
+
watermark: 'Draft',
|
|
133
|
+
watermarkOpacity: 0.1
|
|
134
|
+
})
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Parameters:**
|
|
138
|
+
- `schema: PrintSchema` - The print schema defining layout and sections
|
|
139
|
+
- `data: FormData` - The form data to render
|
|
140
|
+
- `options?: RenderOptions` - Optional rendering configuration
|
|
141
|
+
|
|
142
|
+
**Returns:** `string` - Complete HTML document
|
|
143
|
+
|
|
144
|
+
#### `renderToIsolatedHtml(schema, data, options?)`
|
|
145
|
+
|
|
146
|
+
Renders with CSS isolation for consistent cross-environment styling.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
import { renderToIsolatedHtml } from 'medical-form-printer'
|
|
150
|
+
|
|
151
|
+
const html = renderToIsolatedHtml(printSchema, formData, {
|
|
152
|
+
watermark: 'Internal Use Only'
|
|
153
|
+
})
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
All content is wrapped in an isolation container with:
|
|
157
|
+
- Namespaced CSS classes (prefixed with `mpr-`)
|
|
158
|
+
- Embedded Source Han Serif SC font
|
|
159
|
+
- Style containment for predictable rendering
|
|
160
|
+
|
|
161
|
+
#### `renderToIsolatedFragment(schema, data, options?)`
|
|
162
|
+
|
|
163
|
+
Renders an isolated HTML fragment for embedding in existing pages.
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { renderToIsolatedFragment } from 'medical-form-printer'
|
|
167
|
+
|
|
168
|
+
const fragment = renderToIsolatedFragment(printSchema, formData)
|
|
169
|
+
document.getElementById('preview').innerHTML = fragment
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### PDF Generation (Node.js)
|
|
173
|
+
|
|
174
|
+
#### `renderToPdf(schema, data, options?)`
|
|
175
|
+
|
|
176
|
+
Generates a PDF buffer from a print schema.
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { renderToPdf } from 'medical-form-printer/node'
|
|
180
|
+
|
|
181
|
+
const pdfBuffer = await renderToPdf(printSchema, formData, {
|
|
182
|
+
watermark: 'Confidential',
|
|
183
|
+
pdfOptions: {
|
|
184
|
+
format: 'A4',
|
|
185
|
+
printBackground: true
|
|
186
|
+
}
|
|
187
|
+
})
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Parameters:**
|
|
191
|
+
- `schema: PrintSchema` - The print schema
|
|
192
|
+
- `data: FormData` - The form data
|
|
193
|
+
- `options?: RenderOptions & { pdfOptions?: PdfOptions }` - Rendering and PDF options
|
|
194
|
+
|
|
195
|
+
**Returns:** `Promise<Buffer>` - PDF file buffer
|
|
196
|
+
|
|
197
|
+
#### `mergePdfs(documents, options?)`
|
|
198
|
+
|
|
199
|
+
Merges multiple documents into a single PDF.
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { mergePdfs } from 'medical-form-printer/node'
|
|
203
|
+
|
|
204
|
+
const mergedPdf = await mergePdfs([
|
|
205
|
+
{ schema: schema1, data: data1 },
|
|
206
|
+
{ schema: schema2, data: data2 },
|
|
207
|
+
], {
|
|
208
|
+
watermark: 'Complete Record'
|
|
209
|
+
})
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Custom Section Renderers
|
|
213
|
+
|
|
214
|
+
#### `registerSectionRenderer(type, renderer)`
|
|
215
|
+
|
|
216
|
+
Registers a custom section renderer for specialized content.
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
import { registerSectionRenderer } from 'medical-form-printer'
|
|
220
|
+
|
|
221
|
+
registerSectionRenderer('vital-signs-chart', (config, data, options) => {
|
|
222
|
+
const values = data[config.dataField] || []
|
|
223
|
+
return `
|
|
224
|
+
<div class="vital-signs-chart">
|
|
225
|
+
<h3>${config.title}</h3>
|
|
226
|
+
<!-- Custom chart rendering -->
|
|
227
|
+
</div>
|
|
228
|
+
`
|
|
229
|
+
})
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### `getSectionRenderer(type)`
|
|
233
|
+
|
|
234
|
+
Retrieves a registered section renderer.
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { getSectionRenderer } from 'medical-form-printer'
|
|
238
|
+
|
|
239
|
+
const renderer = getSectionRenderer('info-grid')
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Pagination
|
|
243
|
+
|
|
244
|
+
#### `renderPaginatedHtml(config)`
|
|
245
|
+
|
|
246
|
+
Renders multi-page content with smart pagination.
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
import {
|
|
250
|
+
renderPaginatedHtml,
|
|
251
|
+
calculatePageBreaks,
|
|
252
|
+
PAGE_A4
|
|
253
|
+
} from 'medical-form-printer'
|
|
254
|
+
|
|
255
|
+
const pageBreaks = calculatePageBreaks(measuredItems, {
|
|
256
|
+
pageHeight: PAGE_A4.height,
|
|
257
|
+
headerHeight: 60,
|
|
258
|
+
footerHeight: 40,
|
|
259
|
+
repeatTableHeaders: true
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
const html = renderPaginatedHtml({
|
|
263
|
+
schema: printSchema,
|
|
264
|
+
data: formData,
|
|
265
|
+
pageBreakResult: pageBreaks,
|
|
266
|
+
measuredItems: items,
|
|
267
|
+
config: {
|
|
268
|
+
isolated: true,
|
|
269
|
+
showHeaderOnEachPage: true,
|
|
270
|
+
continuationSuffix: '(continued)'
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
#### Page Size Presets
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
import { PAGE_A4, PAGE_A5, PAGE_16K, PAGE_PRESETS } from 'medical-form-printer'
|
|
279
|
+
|
|
280
|
+
// PAGE_A4: { width: 210, height: 297 } (mm)
|
|
281
|
+
// PAGE_A5: { width: 148, height: 210 } (mm)
|
|
282
|
+
// PAGE_16K: { width: 185, height: 260 } (mm)
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### Unit Conversion
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
import { mmToPx, pxToMm, mmToPt, ptToMm } from 'medical-form-printer'
|
|
289
|
+
|
|
290
|
+
const heightPx = mmToPx(297) // 297mm β pixels
|
|
291
|
+
const heightMm = pxToMm(1123) // pixels β mm
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Styling
|
|
295
|
+
|
|
296
|
+
#### `generateCss(theme?)`
|
|
297
|
+
|
|
298
|
+
Generates CSS styles for print rendering.
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
import { generateCss, defaultTheme } from 'medical-form-printer'
|
|
302
|
+
|
|
303
|
+
const css = generateCss(defaultTheme)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
#### `generateIsolatedCss(theme?)`
|
|
307
|
+
|
|
308
|
+
Generates isolated CSS with embedded fonts and namespaced classes.
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { generateIsolatedCss } from 'medical-form-printer'
|
|
312
|
+
|
|
313
|
+
const css = generateIsolatedCss()
|
|
314
|
+
// Includes @font-face, isolation container, and all component styles
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
#### Theme Customization
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
import { renderToHtml, mergeTheme, defaultTheme } from 'medical-form-printer'
|
|
321
|
+
|
|
322
|
+
const customTheme = mergeTheme(defaultTheme, {
|
|
323
|
+
fonts: {
|
|
324
|
+
body: '"Microsoft YaHei", "PingFang SC", sans-serif',
|
|
325
|
+
heading: '"Microsoft YaHei", "PingFang SC", sans-serif'
|
|
326
|
+
},
|
|
327
|
+
colors: {
|
|
328
|
+
primary: '#1a1a1a',
|
|
329
|
+
border: '#333333',
|
|
330
|
+
background: '#ffffff'
|
|
331
|
+
},
|
|
332
|
+
fontSize: {
|
|
333
|
+
body: '10pt',
|
|
334
|
+
heading: '14pt',
|
|
335
|
+
small: '8pt'
|
|
336
|
+
},
|
|
337
|
+
spacing: {
|
|
338
|
+
section: '12pt',
|
|
339
|
+
cell: '4pt'
|
|
340
|
+
}
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
const html = renderToHtml(schema, data, { theme: customTheme })
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Formatters
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
import {
|
|
350
|
+
formatDate,
|
|
351
|
+
formatBoolean,
|
|
352
|
+
formatNumber,
|
|
353
|
+
formatValue,
|
|
354
|
+
isChecked
|
|
355
|
+
} from 'medical-form-printer'
|
|
356
|
+
|
|
357
|
+
formatDate('2024-01-15') // '2024-01-15'
|
|
358
|
+
formatDate('2024-01-15', { format: 'YYYYεΉ΄MMζDDζ₯' }) // '2024εΉ΄01ζ15ζ₯'
|
|
359
|
+
formatBoolean(true) // 'β'
|
|
360
|
+
formatBoolean(false) // 'β'
|
|
361
|
+
formatNumber(1234.5, { decimals: 2 }) // '1234.50'
|
|
362
|
+
isChecked('yes', ['yes', 'true']) // true
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### HTML Builder Utilities
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
import {
|
|
369
|
+
HtmlBuilder,
|
|
370
|
+
h,
|
|
371
|
+
fragment,
|
|
372
|
+
when,
|
|
373
|
+
each,
|
|
374
|
+
escapeHtml
|
|
375
|
+
} from 'medical-form-printer'
|
|
376
|
+
|
|
377
|
+
// Fluent HTML building
|
|
378
|
+
const html = h('div', { class: 'container' },
|
|
379
|
+
h('h1', {}, 'Title'),
|
|
380
|
+
when(showContent, () => h('p', {}, 'Content')),
|
|
381
|
+
each(items, (item) => h('li', {}, item.name))
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
// Safe HTML escaping
|
|
385
|
+
const safe = escapeHtml('<script>alert("xss")</script>')
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## PrintSchema Structure
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
interface PrintSchema {
|
|
392
|
+
pageSize: 'A4' | 'A5' | '16K'
|
|
393
|
+
orientation: 'portrait' | 'landscape'
|
|
394
|
+
header: {
|
|
395
|
+
hospital: string
|
|
396
|
+
department?: string
|
|
397
|
+
title: string
|
|
398
|
+
subtitle?: string
|
|
399
|
+
}
|
|
400
|
+
sections: PrintSection[]
|
|
401
|
+
footer?: {
|
|
402
|
+
showPageNumber?: boolean
|
|
403
|
+
pageNumberFormat?: string
|
|
404
|
+
notes?: string
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## Section Types
|
|
410
|
+
|
|
411
|
+
| Type | Description | Use Case |
|
|
412
|
+
|------|-------------|----------|
|
|
413
|
+
| `info-grid` | Grid layout for key-value pairs | Patient demographics, basic info |
|
|
414
|
+
| `table` | Data table with columns | Nursing records, medication logs |
|
|
415
|
+
| `checkbox-grid` | Grid of checkbox options | Assessment checklists, symptoms |
|
|
416
|
+
| `signature-area` | Signature fields with labels | Approvals, acknowledgments |
|
|
417
|
+
| `notes` | Static text content | Instructions, disclaimers |
|
|
418
|
+
| `free-text` | Multi-line text input | Comments, observations |
|
|
419
|
+
|
|
420
|
+
### Info Grid Section
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
{
|
|
424
|
+
type: 'info-grid',
|
|
425
|
+
config: {
|
|
426
|
+
columns: 4,
|
|
427
|
+
rows: [
|
|
428
|
+
{
|
|
429
|
+
cells: [
|
|
430
|
+
{ label: 'Name', field: 'name', type: 'text' },
|
|
431
|
+
{ label: 'Age', field: 'age', type: 'number', span: 1 },
|
|
432
|
+
{ label: 'Date', field: 'date', type: 'date' },
|
|
433
|
+
{ label: 'Status', field: 'status', type: 'checkbox', options: ['Active'] }
|
|
434
|
+
]
|
|
435
|
+
}
|
|
436
|
+
]
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Table Section
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
{
|
|
445
|
+
type: 'table',
|
|
446
|
+
title: 'Nursing Records',
|
|
447
|
+
config: {
|
|
448
|
+
dataField: 'nursingRecords',
|
|
449
|
+
columns: [
|
|
450
|
+
{ header: 'Date', field: 'date', type: 'date', width: '15%' },
|
|
451
|
+
{ header: 'Time', field: 'time', type: 'text', width: '10%' },
|
|
452
|
+
{ header: 'Temperature', field: 'temperature', type: 'number', width: '15%' },
|
|
453
|
+
{ header: 'Notes', field: 'notes', type: 'text' }
|
|
454
|
+
]
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Checkbox Grid Section
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
{
|
|
463
|
+
type: 'checkbox-grid',
|
|
464
|
+
title: 'Symptoms Assessment',
|
|
465
|
+
config: {
|
|
466
|
+
field: 'symptoms',
|
|
467
|
+
columns: 4,
|
|
468
|
+
options: [
|
|
469
|
+
{ value: 'fever', label: 'Fever' },
|
|
470
|
+
{ value: 'headache', label: 'Headache' },
|
|
471
|
+
{ value: 'fatigue', label: 'Fatigue' },
|
|
472
|
+
{ value: 'nausea', label: 'Nausea' }
|
|
473
|
+
]
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### Signature Area Section
|
|
479
|
+
|
|
480
|
+
```typescript
|
|
481
|
+
{
|
|
482
|
+
type: 'signature-area',
|
|
483
|
+
config: {
|
|
484
|
+
fields: [
|
|
485
|
+
{ label: 'Patient Signature', field: 'patientSignature' },
|
|
486
|
+
{ label: 'Nurse Signature', field: 'nurseSignature' },
|
|
487
|
+
{ label: 'Date', field: 'signatureDate', type: 'date' }
|
|
488
|
+
]
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
## CSS Isolation
|
|
494
|
+
|
|
495
|
+
For consistent rendering across different environments, use isolation mode:
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
import {
|
|
499
|
+
renderToIsolatedHtml,
|
|
500
|
+
CSS_NAMESPACE,
|
|
501
|
+
ISOLATION_ROOT_CLASS,
|
|
502
|
+
namespaceClass,
|
|
503
|
+
namespaceClasses
|
|
504
|
+
} from 'medical-form-printer'
|
|
505
|
+
|
|
506
|
+
// CSS_NAMESPACE = 'mpr'
|
|
507
|
+
// ISOLATION_ROOT_CLASS = 'mpr-root'
|
|
508
|
+
|
|
509
|
+
// Namespace utilities
|
|
510
|
+
namespaceClass('header') // 'mpr-header'
|
|
511
|
+
namespaceClasses(['header', 'footer']) // ['mpr-header', 'mpr-footer']
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
Isolation mode provides:
|
|
515
|
+
- All classes prefixed with `mpr-` namespace
|
|
516
|
+
- Embedded Source Han Serif SC font (subset for CJK support)
|
|
517
|
+
- CSS containment (`contain: layout style`)
|
|
518
|
+
- Consistent rendering regardless of host page styles
|
|
519
|
+
|
|
520
|
+
## Examples
|
|
521
|
+
|
|
522
|
+
See the [examples](./examples) directory for complete working examples:
|
|
523
|
+
|
|
524
|
+
- [Browser Example](./examples/browser) - Vanilla HTML/JS usage
|
|
525
|
+
- [Node.js Example](./examples/node) - PDF generation with file output
|
|
526
|
+
|
|
527
|
+
## Storybook
|
|
528
|
+
|
|
529
|
+
Interactive component documentation is available via Storybook:
|
|
530
|
+
|
|
531
|
+
```bash
|
|
532
|
+
npm run storybook
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
## Contributing
|
|
536
|
+
|
|
537
|
+
Contributions are welcome! Please read our [Contributing Guide](./CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
|
|
538
|
+
|
|
539
|
+
## License
|
|
540
|
+
|
|
541
|
+
[MIT](./LICENSE) Β© 2024
|
|
542
|
+
|
|
543
|
+
## Links
|
|
544
|
+
|
|
545
|
+
- [GitHub Repository](https://github.com/wangchengshi-ship-it/medical-form-printer)
|
|
546
|
+
- [npm Package](https://www.npmjs.com/package/medical-form-printer)
|
|
547
|
+
- [Issue Tracker](https://github.com/wangchengshi-ship-it/medical-form-printer/issues)
|
|
548
|
+
- [Changelog](./CHANGELOG.md)
|