Last active
          March 1, 2025 09:44 
        
      - 
      
- 
        Save kyasu1/0def72d6f0826b0a9571b6e13f3c9065 to your computer and use it in GitHub Desktop. 
Revisions
- 
        kyasu1 revised this gist Mar 1, 2025 . No changes.There are no files selected for viewing
- 
        kyasu1 renamed this gist Mar 1, 2025 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewingFile renamed without changes.
- 
        kyasu1 created this gist Mar 1, 2025 .There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,178 @@ import type * as CSS from 'csstype'; import { createSvgStr, convertForPdfLayoutProps, isEditable, addAlphaToHex, createErrorElm} from '@pdfme/schemas/utils'; import { Plugin, UIRenderProps } from '@pdfme/common'; import type { PDFRenderProps, Schema } from '@pdfme/common'; import * as Lucide from 'lucide'; import QRCode from 'qrcode'; const DEFAULT_OPACITY = 1; const HEX_COLOR_PATTERN = '^#(?:[A-Fa-f0-9]{6})$'; const DEFAULT_BARCODE_BG_COLOR = '#ffffff'; const DEFAULT_BARCODE_COLOR = '#000000'; interface QRCodeSchema extends Schema { backgroundColor: string; barColor: string; } /* uiRender */ const fullSize = { width: '100%', height: '100%' }; const createQRCodeImageElm = async (value: string) => { const qrCodeDataURL: string = await QRCode.toDataURL(value); const img: HTMLImageElement = document.createElement('img'); img.src = qrCodeDataURL; const imgStyle: CSS.Properties = { ...fullSize, borderRadius: 0 }; Object.assign(img.style, imgStyle); return img; }; // const uiRender = async (arg: UIRenderProps<QRCodeSchema>) => { const { value, rootElement, mode, onChange, stopEditing, tabIndex, placeholder, schema, theme } = arg; const container = document.createElement('div'); const containerStyle: CSS.Properties = { ...fullSize, display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: "'Open Sans', sans-serif", }; Object.assign(container.style, containerStyle); rootElement.appendChild(container); const editable = isEditable(mode, schema); if (editable) { const input = document.createElement('input'); const inputStyle: CSS.Properties = { width: '100%', position: 'absolute', textAlign: 'center', fontSize: '12pt', fontWeight: 'bold', color: theme.colorWhite, backgroundColor: editable || value ? addAlphaToHex('#000000', 80) : 'none', border: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'auto', }; Object.assign(input.style, inputStyle); input.value = value; input.placeholder = placeholder || ''; input.tabIndex = tabIndex || 0; input.addEventListener('change', (e: Event) => { onChange && onChange({ key: 'content', value: (e.target as HTMLInputElement).value }); }); input.addEventListener('blur', () => { stopEditing && stopEditing(); }); container.appendChild(input); input.setSelectionRange(value.length, value.length); if (mode === 'designer') { input.focus(); } } if (!value) return; try { // if (!validateBarcodeInput(schema.type, value)) // throw new Error('[@pdfme/schemas/barcodes] Invalid barcode input'); const imgElm = await createQRCodeImageElm(value); container.appendChild(imgElm); } catch (err) { console.error(`[@pdfme/ui] ${err}`); container.appendChild(createErrorElm()); } }; /* pdfRender */ const getBarcodeCacheKey = (schema: QRCodeSchema & Schema, value: string) => { return `${schema.type}${schema.backgroundColor}${schema.barColor}${value}`; }; const pdfRender = async (arg: PDFRenderProps<QRCodeSchema>) => { const { value, schema, pdfDoc, page, _cache } = arg; if (!value) return; const inputBarcodeCacheKey = getBarcodeCacheKey(schema, value); let image = _cache.get(inputBarcodeCacheKey); if (!image) { const dataURL: string = await QRCode.toDataURL(value); const base64 = dataURL.split(',')[1]; if (base64) { image = await pdfDoc.embedPng(base64); _cache.set(inputBarcodeCacheKey, image); } else { console.error("Failed to generate QRCode"); } } const pageHeight = page.getHeight(); const { width, height, rotate, position: { x, y }, opacity, } = convertForPdfLayoutProps({ schema, pageHeight }); page.drawImage(image, { x, y, rotate, width, height, opacity }); }; const qrCodeSchema: Plugin<QRCodeSchema> = { pdf: pdfRender, ui: uiRender, propPanel: { schema: ({ i18n }: { i18n: (key: string) => string }) => ({ barColor: { title: i18n('schemas.barcodes.barColor'), type: 'string', widget: 'color', props: { disabledAlpha: true, }, rules: [ { pattern: HEX_COLOR_PATTERN, message: i18n('validation.hexColor'), }, ], }, backgroundColor: { title: i18n('schemas.bgColor'), type: 'string', widget: 'color', props: { disabledAlpha: true, }, rules: [ { pattern: HEX_COLOR_PATTERN, message: i18n('validation.hexColor'), }, ], }, }), defaultSchema: { name: '', type: 'node-qrCode', content: 'https://pdfme.com/', position: { x: 0, y: 0 }, width: 20, height: 20, backgroundColor: DEFAULT_BARCODE_BG_COLOR, barColor: DEFAULT_BARCODE_COLOR, rotate: 0, opacity: DEFAULT_OPACITY, }, }, icon: createSvgStr(Lucide.QrCode), };