@pdfme/ui 5.2.16 → 5.3.0-dev.1
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.es.js +121523 -87842
- package/dist/index.umd.js +523 -477
- package/dist/types/class.d.ts +1 -1
- package/dist/types/components/Renderer.d.ts +1 -1
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/helper.d.ts +1 -6
- package/package.json +4 -5
- package/src/components/CtlBar.tsx +2 -1
- package/src/components/Designer/RightSidebar/DetailView/ButtonGroupWidget.tsx +8 -3
- package/src/components/Renderer.tsx +1 -3
- package/src/constants.ts +2 -0
- package/src/helper.ts +47 -53
- package/src/hooks.ts +29 -11
- package/vite.config.ts +1 -1
- package/__mocks__/pdfjs-dist.js +0 -15
- package/dist/__vite-browser-external-DYxpcVy9.mjs +0 -4
package/dist/types/class.d.ts
CHANGED
@@ -10,7 +10,7 @@ export declare abstract class BaseUIClass {
|
|
10
10
|
private readonly setSize;
|
11
11
|
resizeObserver: ResizeObserver;
|
12
12
|
constructor(props: UIProps);
|
13
|
-
protected getLang(): "en" | "
|
13
|
+
protected getLang(): "en" | "pl" | "zh" | "ja" | "ko" | "ar" | "th" | "it" | "de" | "es" | "fr";
|
14
14
|
protected getFont(): Record<string, {
|
15
15
|
data: string | ArrayBuffer | Uint8Array;
|
16
16
|
fallback?: boolean | undefined;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { Mode, UIRenderProps, SchemaForUI, BasePdf, Schema, Plugin, UIOptions } from '@pdfme/common';
|
3
|
-
type RendererProps = Omit<UIRenderProps<Schema>, 'schema' | 'rootElement' | 'options' | 'theme' | 'i18n' | '
|
3
|
+
type RendererProps = Omit<UIRenderProps<Schema>, 'schema' | 'rootElement' | 'options' | 'theme' | 'i18n' | '_cache'> & {
|
4
4
|
basePdf: BasePdf;
|
5
5
|
schema: SchemaForUI;
|
6
6
|
value: string;
|
package/dist/types/helper.d.ts
CHANGED
@@ -17,12 +17,7 @@ export declare const initShortCuts: (arg: {
|
|
17
17
|
selectAll: () => void;
|
18
18
|
}) => void;
|
19
19
|
export declare const destroyShortCuts: () => void;
|
20
|
-
export declare const
|
21
|
-
height: number;
|
22
|
-
width: number;
|
23
|
-
}[]>;
|
24
|
-
export declare const pdf2Pngs: (pdfBlob: Blob, width: number) => Promise<string[]>;
|
25
|
-
export declare const b64toBlob: (base64: string) => Blob;
|
20
|
+
export declare const arrayBufferToBase64: (arrayBuffer: ArrayBuffer) => string;
|
26
21
|
export declare const template2SchemasList: (_template: Template) => Promise<{
|
27
22
|
width: number;
|
28
23
|
height: number;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@pdfme/ui",
|
3
|
-
"version": "5.
|
3
|
+
"version": "5.3.0-dev.1",
|
4
4
|
"sideEffects": false,
|
5
5
|
"author": "hand-dot",
|
6
6
|
"license": "MIT",
|
@@ -38,12 +38,12 @@
|
|
38
38
|
"dependencies": {
|
39
39
|
"@dnd-kit/core": "^6.0.8",
|
40
40
|
"@dnd-kit/sortable": "^7.0.2",
|
41
|
+
"@pdfme/converter": "file:../converter",
|
41
42
|
"@scena/react-guides": "^0.16.0",
|
42
43
|
"antd": "^5.9.4",
|
43
44
|
"form-render": "^2.2.16",
|
44
45
|
"hotkeys-js": "^3.8.7",
|
45
46
|
"lucide-react": "^0.460.0",
|
46
|
-
"pdfjs-dist": "^4.8.69",
|
47
47
|
"react": "^16.14.0",
|
48
48
|
"react-dom": "^16.14.0",
|
49
49
|
"react-moveable": "^0.30.3",
|
@@ -83,13 +83,12 @@
|
|
83
83
|
],
|
84
84
|
"moduleNameMapper": {
|
85
85
|
"\\.(png|css)$": "<rootDir>/__mocks__/assetsTransformer.js",
|
86
|
+
"^@pdfme/converter$": "<rootDir>/../converter/src/index.node.ts",
|
86
87
|
"^@pdfme/schemas/utils$": "<rootDir>/../schemas/src/utils.ts",
|
87
88
|
"^antd/es/": "antd/lib/",
|
88
89
|
"^form-render/es/": "form-render/lib/",
|
89
90
|
"^rc-picker/es/": "rc-picker/lib/",
|
90
|
-
"^lodash-es$": "lodash"
|
91
|
-
"^pdfjs-dist/legacy/build/pdf.js$": "<rootDir>/__mocks__/pdfjs-dist.js",
|
92
|
-
"^pdfjs-dist/legacy/build/pdf.worker.entry.js$": "<rootDir>/__mocks__/pdfjs-dist.js"
|
91
|
+
"^lodash-es$": "lodash"
|
93
92
|
},
|
94
93
|
"resolver": "ts-jest-resolver",
|
95
94
|
"moduleFileExtensions": [
|
@@ -5,6 +5,7 @@ import { Plus, Minus, ChevronLeft, ChevronRight, Ellipsis } from 'lucide-react';
|
|
5
5
|
import type { MenuProps } from 'antd';
|
6
6
|
import { theme, Typography, Button, Dropdown } from 'antd';
|
7
7
|
import { I18nContext } from '../contexts';
|
8
|
+
import { MAX_ZOOM } from '../constants';
|
8
9
|
|
9
10
|
const { Text } = Typography;
|
10
11
|
|
@@ -17,7 +18,7 @@ type ZoomProps = {
|
|
17
18
|
|
18
19
|
const Zoom = ({ zoomLevel, setZoomLevel, style }: ZoomProps) => {
|
19
20
|
const zoomStep = 0.25;
|
20
|
-
const maxZoom =
|
21
|
+
const maxZoom = MAX_ZOOM;
|
21
22
|
const minZoom = 0.25;
|
22
23
|
|
23
24
|
const nextZoomOut = zoomLevel - zoomStep;
|
@@ -1,7 +1,6 @@
|
|
1
|
-
import { Button, Form } from 'antd';
|
1
|
+
import { Button, Form, theme } from 'antd';
|
2
2
|
import React from 'react';
|
3
3
|
import type { PropPanelWidgetProps, SchemaForUI } from '@pdfme/common';
|
4
|
-
|
5
4
|
interface ButtonConfig {
|
6
5
|
key: string;
|
7
6
|
icon: string;
|
@@ -11,6 +10,7 @@ interface ButtonConfig {
|
|
11
10
|
|
12
11
|
const ButtonGroupWidget = (props: PropPanelWidgetProps) => {
|
13
12
|
const { activeElements, changeSchemas, schemas, schema } = props;
|
13
|
+
const { token } = theme.useToken();
|
14
14
|
|
15
15
|
const apply = (btn: ButtonConfig) => {
|
16
16
|
const key = btn.key;
|
@@ -38,8 +38,13 @@ const ButtonGroupWidget = (props: PropPanelWidgetProps) => {
|
|
38
38
|
return active;
|
39
39
|
};
|
40
40
|
|
41
|
+
const replaceCurrentColor = (svgString: string, color?: string) =>
|
42
|
+
color ? svgString.replace(/="currentColor"/g, `="${color}"`) : svgString;
|
43
|
+
|
41
44
|
const svgIcon = (svgString: string) => {
|
42
|
-
const svgDataUrl = `data:image/svg+xml;utf8,${encodeURIComponent(
|
45
|
+
const svgDataUrl = `data:image/svg+xml;utf8,${encodeURIComponent(
|
46
|
+
replaceCurrentColor(svgString, token.colorText)
|
47
|
+
)}`;
|
43
48
|
return <img width={17} height={17} src={svgDataUrl} />;
|
44
49
|
};
|
45
50
|
|
@@ -3,11 +3,10 @@ import { Dict, Mode, ZOOM, UIRenderProps, SchemaForUI, BasePdf, Schema, Plugin,
|
|
3
3
|
import { theme as antdTheme } from 'antd';
|
4
4
|
import { SELECTABLE_CLASSNAME } from '../constants';
|
5
5
|
import { PluginsRegistry, OptionsContext, I18nContext } from '../contexts';
|
6
|
-
import * as pdfJs from 'pdfjs-dist';
|
7
6
|
|
8
7
|
type RendererProps = Omit<
|
9
8
|
UIRenderProps<Schema>,
|
10
|
-
'schema' | 'rootElement' | 'options' | 'theme' | 'i18n' | '
|
9
|
+
'schema' | 'rootElement' | 'options' | 'theme' | 'i18n' | '_cache'
|
11
10
|
> & {
|
12
11
|
basePdf: BasePdf;
|
13
12
|
schema: SchemaForUI;
|
@@ -128,7 +127,6 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
|
|
128
127
|
options,
|
129
128
|
theme,
|
130
129
|
i18n,
|
131
|
-
pdfJs,
|
132
130
|
_cache: _cache.current,
|
133
131
|
});
|
134
132
|
}
|
package/src/constants.ts
CHANGED
package/src/helper.ts
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
import { getDocument, GlobalWorkerOptions, version } from 'pdfjs-dist';
|
2
1
|
import hotkeys from 'hotkeys-js';
|
3
2
|
import {
|
4
3
|
cloneDeep,
|
5
4
|
ZOOM,
|
6
5
|
getB64BasePdf,
|
7
6
|
b64toUint8Array,
|
8
|
-
pt2mm,
|
9
7
|
Template,
|
10
8
|
BasePdf,
|
11
9
|
SchemaForUI,
|
@@ -13,10 +11,9 @@ import {
|
|
13
11
|
isBlankPdf,
|
14
12
|
Plugins,
|
15
13
|
} from '@pdfme/common';
|
14
|
+
import { pdf2size } from '@pdfme/converter';
|
16
15
|
import { RULER_HEIGHT } from './constants.js';
|
17
16
|
|
18
|
-
GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${version}/build/pdf.worker.min.mjs`;
|
19
|
-
|
20
17
|
export const uuid = () =>
|
21
18
|
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
22
19
|
const r = (Math.random() * 16) | 0;
|
@@ -191,61 +188,59 @@ export const destroyShortCuts = () => {
|
|
191
188
|
hotkeys.unbind(keys.join());
|
192
189
|
};
|
193
190
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
return promises;
|
211
|
-
};
|
191
|
+
/**
|
192
|
+
* Guess the MIME type by checking the first few bytes of the ArrayBuffer.
|
193
|
+
* Currently checks for PNG, JPEG, and GIF signatures.
|
194
|
+
*/
|
195
|
+
function detectMimeType(arrayBuffer: ArrayBuffer): string {
|
196
|
+
const dataView = new DataView(arrayBuffer);
|
197
|
+
|
198
|
+
// Check for PNG signature: 0x89 0x50 0x4E 0x47
|
199
|
+
if (
|
200
|
+
dataView.getUint8(0) === 0x89 &&
|
201
|
+
dataView.getUint8(1) === 0x50 &&
|
202
|
+
dataView.getUint8(2) === 0x4e &&
|
203
|
+
dataView.getUint8(3) === 0x47
|
204
|
+
) {
|
205
|
+
return 'image/png';
|
206
|
+
}
|
212
207
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
canvas.width = width * 2;
|
222
|
-
const canvasContext = canvas.getContext('2d')!;
|
223
|
-
const scaleRequired = canvas.width / page.getViewport({ scale: 1, rotation: 0 }).width;
|
224
|
-
const viewport = page.getViewport({ scale: scaleRequired, rotation: 0 });
|
225
|
-
canvas.height = viewport.height;
|
226
|
-
|
227
|
-
return page
|
228
|
-
.render({ canvasContext, viewport })
|
229
|
-
.promise.then(() => canvas.toDataURL(`image/${imageType}`));
|
230
|
-
});
|
231
|
-
})
|
232
|
-
);
|
233
|
-
URL.revokeObjectURL(url);
|
208
|
+
// Check for JPEG signature: 0xFF 0xD8 0xFF
|
209
|
+
if (
|
210
|
+
dataView.getUint8(0) === 0xff &&
|
211
|
+
dataView.getUint8(1) === 0xd8 &&
|
212
|
+
dataView.getUint8(2) === 0xff
|
213
|
+
) {
|
214
|
+
return 'image/jpeg';
|
215
|
+
}
|
234
216
|
|
235
|
-
return
|
236
|
-
}
|
217
|
+
return ''; // Unknown type
|
218
|
+
}
|
237
219
|
|
238
|
-
export const
|
220
|
+
export const arrayBufferToBase64 = (arrayBuffer: ArrayBuffer): string => {
|
221
|
+
// Detect the MIME type
|
222
|
+
const mimeType = detectMimeType(arrayBuffer);
|
239
223
|
|
240
|
-
|
241
|
-
const
|
242
|
-
|
224
|
+
// Convert ArrayBuffer to raw Base64
|
225
|
+
const bytes = new Uint8Array(arrayBuffer);
|
226
|
+
let binary = '';
|
227
|
+
for (let i = 0; i < bytes.length; i++) {
|
228
|
+
binary += String.fromCharCode(bytes[i]);
|
229
|
+
}
|
230
|
+
const base64String = btoa(binary);
|
243
231
|
|
244
|
-
|
232
|
+
// Optionally prepend a data: URL if a known MIME type is found;
|
233
|
+
// otherwise just return the raw Base64.
|
234
|
+
if (mimeType) {
|
235
|
+
return `data:${mimeType};base64,${base64String}`;
|
236
|
+
} else {
|
237
|
+
// or you can default to `application/octet-stream` if unknown
|
238
|
+
return `data:application/octet-stream;base64,${base64String}`;
|
239
|
+
}
|
245
240
|
};
|
246
241
|
|
247
242
|
const convertSchemasForUI = (template: Template): SchemaForUI[][] => {
|
248
|
-
template.schemas.forEach((page
|
243
|
+
template.schemas.forEach((page) => {
|
249
244
|
page.forEach((schema) => {
|
250
245
|
schema.id = uuid();
|
251
246
|
schema.content = schema.content || '';
|
@@ -268,8 +263,7 @@ export const template2SchemasList = async (_template: Template) => {
|
|
268
263
|
}));
|
269
264
|
} else {
|
270
265
|
const b64BasePdf = await getB64BasePdf(basePdf);
|
271
|
-
|
272
|
-
pageSizes = await getPdfPageSizes(pdfBlob);
|
266
|
+
pageSizes = await pdf2size(b64toUint8Array(b64BasePdf));
|
273
267
|
}
|
274
268
|
|
275
269
|
const ssl = schemasForUI.length;
|
package/src/hooks.ts
CHANGED
@@ -5,23 +5,23 @@ import {
|
|
5
5
|
Template,
|
6
6
|
Size,
|
7
7
|
getB64BasePdf,
|
8
|
+
b64toUint8Array,
|
8
9
|
SchemaForUI,
|
9
10
|
ChangeSchemas,
|
10
11
|
isBlankPdf,
|
11
12
|
} from '@pdfme/common';
|
13
|
+
import { pdf2img, pdf2size } from '@pdfme/converter';
|
12
14
|
|
13
15
|
import {
|
14
16
|
schemasList2template,
|
15
17
|
uuid,
|
16
18
|
getUniqueSchemaName,
|
17
19
|
moveCommandToChangeSchemasArg,
|
18
|
-
|
19
|
-
getPdfPageSizes,
|
20
|
-
b64toBlob,
|
20
|
+
arrayBufferToBase64,
|
21
21
|
initShortCuts,
|
22
22
|
destroyShortCuts,
|
23
23
|
} from './helper.js';
|
24
|
-
import { RULER_HEIGHT } from './constants.js';
|
24
|
+
import { RULER_HEIGHT, MAX_ZOOM } from './constants.js';
|
25
25
|
|
26
26
|
export const usePrevious = <T>(value: T) => {
|
27
27
|
const ref = useRef<T | null>(null);
|
@@ -48,7 +48,11 @@ export const useUIPreProcessor = ({ template, size, zoomLevel }: UIPreProcessorP
|
|
48
48
|
template: { basePdf, schemas },
|
49
49
|
size,
|
50
50
|
} = prop;
|
51
|
-
|
51
|
+
|
52
|
+
let paperWidth: number;
|
53
|
+
let paperHeight: number;
|
54
|
+
let _backgrounds: string[];
|
55
|
+
let _pageSizes: { width: number; height: number }[];
|
52
56
|
|
53
57
|
if (isBlankPdf(basePdf)) {
|
54
58
|
const { width, height } = basePdf;
|
@@ -61,18 +65,28 @@ export const useUIPreProcessor = ({ template, size, zoomLevel }: UIPreProcessorP
|
|
61
65
|
_pageSizes = schemas.map(() => ({ width, height }));
|
62
66
|
} else {
|
63
67
|
const _basePdf = await getB64BasePdf(basePdf);
|
64
|
-
|
65
|
-
|
68
|
+
|
69
|
+
const [_pages, imgBuffers] = await Promise.all([
|
70
|
+
pdf2size(b64toUint8Array(_basePdf)),
|
71
|
+
pdf2img(b64toUint8Array(_basePdf), { scale: MAX_ZOOM }),
|
72
|
+
]);
|
73
|
+
|
74
|
+
_pageSizes = _pages;
|
66
75
|
paperWidth = _pageSizes[0].width * ZOOM;
|
67
76
|
paperHeight = _pageSizes[0].height * ZOOM;
|
68
|
-
_backgrounds =
|
77
|
+
_backgrounds = imgBuffers.map(arrayBufferToBase64);
|
69
78
|
}
|
79
|
+
|
70
80
|
const _scale = Math.min(
|
71
81
|
getScale(size.width, paperWidth),
|
72
82
|
getScale(size.height - RULER_HEIGHT, paperHeight)
|
73
83
|
);
|
74
84
|
|
75
|
-
return {
|
85
|
+
return {
|
86
|
+
backgrounds: _backgrounds,
|
87
|
+
pageSizes: _pageSizes,
|
88
|
+
scale: _scale,
|
89
|
+
};
|
76
90
|
};
|
77
91
|
|
78
92
|
useEffect(() => {
|
@@ -82,7 +96,7 @@ export const useUIPreProcessor = ({ template, size, zoomLevel }: UIPreProcessorP
|
|
82
96
|
})
|
83
97
|
.catch((err: Error) => {
|
84
98
|
setError(err);
|
85
|
-
console.error(
|
99
|
+
console.error('[@pdfme/ui]', err);
|
86
100
|
});
|
87
101
|
}, [template, size]);
|
88
102
|
|
@@ -230,7 +244,11 @@ export const useInitEvents = ({
|
|
230
244
|
const stackUniqueSchemaNames: string[] = [];
|
231
245
|
const pasteSchemas = copiedSchemas.current.map((cs) => {
|
232
246
|
const id = uuid();
|
233
|
-
const name = getUniqueSchemaName({
|
247
|
+
const name = getUniqueSchemaName({
|
248
|
+
copiedSchemaName: cs.name,
|
249
|
+
schema,
|
250
|
+
stackUniqueSchemaNames,
|
251
|
+
});
|
234
252
|
const { height, width, position: p } = cs;
|
235
253
|
const ps = pageSizes[pageCursor];
|
236
254
|
const position = {
|
package/vite.config.ts
CHANGED
@@ -16,7 +16,7 @@ export default defineConfig(({ mode }) => {
|
|
16
16
|
},
|
17
17
|
optimizeDeps: {
|
18
18
|
include: ['react', 'react-dom', 'pdfjs-dist', 'antd'],
|
19
|
-
exclude: ['@pdfme/common', '@pdfme/schemas'],
|
19
|
+
exclude: ['@pdfme/common', '@pdfme/schemas', '@pdfme/converter'],
|
20
20
|
},
|
21
21
|
};
|
22
22
|
});
|
package/__mocks__/pdfjs-dist.js
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
const getDocument = jest.fn().mockImplementation(() => {
|
2
|
-
return {
|
3
|
-
promise: Promise.resolve({
|
4
|
-
}),
|
5
|
-
};
|
6
|
-
});
|
7
|
-
|
8
|
-
const GlobalWorkerOptions = {
|
9
|
-
workerSrc: 'mock-worker-src.js',
|
10
|
-
};
|
11
|
-
|
12
|
-
module.exports = {
|
13
|
-
getDocument,
|
14
|
-
GlobalWorkerOptions,
|
15
|
-
};
|