@pdfme/ui 4.2.3 → 4.2.4

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.
@@ -21,7 +21,6 @@ export declare abstract class BaseUIClass {
21
21
  getTemplate(): import("zod").objectOutputType<{
22
22
  schemas: import("zod").ZodArray<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodObject<{
23
23
  type: import("zod").ZodString;
24
- icon: import("zod").ZodOptional<import("zod").ZodString>;
25
24
  content: import("zod").ZodOptional<import("zod").ZodString>;
26
25
  position: import("zod").ZodObject<{
27
26
  x: import("zod").ZodNumber;
@@ -40,7 +39,6 @@ export declare abstract class BaseUIClass {
40
39
  readOnly: import("zod").ZodOptional<import("zod").ZodBoolean>;
41
40
  }, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
42
41
  type: import("zod").ZodString;
43
- icon: import("zod").ZodOptional<import("zod").ZodString>;
44
42
  content: import("zod").ZodOptional<import("zod").ZodString>;
45
43
  position: import("zod").ZodObject<{
46
44
  x: import("zod").ZodNumber;
@@ -59,7 +57,6 @@ export declare abstract class BaseUIClass {
59
57
  readOnly: import("zod").ZodOptional<import("zod").ZodBoolean>;
60
58
  }, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
61
59
  type: import("zod").ZodString;
62
- icon: import("zod").ZodOptional<import("zod").ZodString>;
63
60
  content: import("zod").ZodOptional<import("zod").ZodString>;
64
61
  position: import("zod").ZodObject<{
65
62
  x: import("zod").ZodNumber;
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
2
  import type { SchemaForUI } from '@pdfme/common';
3
3
  import type { SidebarProps } from '../../../../types';
4
- declare const DetailView: (props: Pick<SidebarProps, 'size' | 'schemas' | 'pageSize' | 'changeSchemas' | 'activeElements' | 'deselectSchema'> & {
4
+ type DetailViewProps = Pick<SidebarProps, 'size' | 'schemas' | 'pageSize' | 'changeSchemas' | 'activeElements' | 'deselectSchema'> & {
5
5
  activeSchema: SchemaForUI;
6
- }) => React.JSX.Element;
7
- export default DetailView;
6
+ };
7
+ declare const _default: React.MemoExoticComponent<(props: DetailViewProps) => React.JSX.Element>;
8
+ export default _default;
@@ -36,7 +36,6 @@ export declare const template2SchemasList: (_template: Template) => Promise<{
36
36
  key: string;
37
37
  opacity?: number | undefined;
38
38
  rotate?: number | undefined;
39
- icon?: string | undefined;
40
39
  content?: string | undefined;
41
40
  readOnly?: boolean | undefined;
42
41
  }[][]>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pdfme/ui",
3
- "version": "4.2.3",
3
+ "version": "4.2.4",
4
4
  "sideEffects": false,
5
5
  "author": "hand-dot",
6
6
  "license": "MIT",
@@ -8,7 +8,7 @@ import { theme, Button } from 'antd';
8
8
  import { useDraggable } from '@dnd-kit/core';
9
9
  import { CSS } from "@dnd-kit/utilities";
10
10
  import Renderer from '../Renderer';
11
- import { PluginsRegistry } from '../../contexts';
11
+ import { PluginsRegistry, OptionsContext } from '../../contexts';
12
12
 
13
13
  const Draggable = (props: { plugin: Plugin<any>, scale: number, basePdf: BasePdf, children: React.ReactNode }) => {
14
14
  const { scale, basePdf, plugin } = props;
@@ -44,6 +44,7 @@ const Draggable = (props: { plugin: Plugin<any>, scale: number, basePdf: BasePdf
44
44
  const LeftSidebar = ({ height, scale, basePdf }: { height: number, scale: number, basePdf: BasePdf }) => {
45
45
  const { token } = theme.useToken();
46
46
  const pluginsRegistry = useContext(PluginsRegistry);
47
+ const options = useContext(OptionsContext);
47
48
 
48
49
  const [isDragging, setIsDragging] = useState(false);
49
50
 
@@ -76,6 +77,8 @@ const LeftSidebar = ({ height, scale, basePdf }: { height: number, scale: number
76
77
  >
77
78
  {Object.entries(pluginsRegistry).map(([label, plugin]) => {
78
79
  if (!plugin?.propPanel.defaultSchema) return null;
80
+ const icon = options.icons?.[plugin.propPanel.defaultSchema.type] ?? plugin.icon;
81
+
79
82
  return <Draggable
80
83
  key={label}
81
84
  scale={scale}
@@ -87,8 +90,8 @@ const LeftSidebar = ({ height, scale, basePdf }: { height: number, scale: number
87
90
  setIsDragging(true);
88
91
  }}
89
92
  style={{ width: 35, height: 35, marginTop: '0.25rem', padding: '0.25rem' }}>
90
- {plugin.propPanel.defaultSchema.icon ?
91
- <div dangerouslySetInnerHTML={{ __html: plugin.propPanel.defaultSchema.icon }} />
93
+ {icon ?
94
+ <div dangerouslySetInnerHTML={{ __html: icon }} />
92
95
  :
93
96
  <div style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>{label}</div>
94
97
  }
@@ -1,5 +1,5 @@
1
1
  import FormRender, { useForm } from 'form-render';
2
- import React, { useContext, useEffect, useState } from 'react';
2
+ import React, { useContext, useEffect } from 'react';
3
3
  import type { ChangeSchemaItem, Dict, SchemaForUI, PropPanelWidgetProps, PropPanelSchema } from '@pdfme/common';
4
4
  import type { SidebarProps } from '../../../../types';
5
5
  import { MenuOutlined } from '@ant-design/icons';
@@ -13,67 +13,32 @@ import { InternalNamePath, ValidateErrorEntity } from "rc-field-form/es/interfac
13
13
 
14
14
  const { Text } = Typography;
15
15
 
16
- const DetailView = (
17
- props: Pick<
18
- SidebarProps,
19
- 'size' | 'schemas' | 'pageSize' | 'changeSchemas' | 'activeElements' | 'deselectSchema'
20
- > & {
21
- activeSchema: SchemaForUI;
22
- }
23
- ) => {
16
+ type DetailViewProps = Pick<SidebarProps,
17
+ 'size' | 'schemas' | 'pageSize' | 'changeSchemas' | 'activeElements' | 'deselectSchema'
18
+ > & {
19
+ activeSchema: SchemaForUI;
20
+ };
21
+
22
+ const DetailView = (props: DetailViewProps) => {
24
23
  const { token } = theme.useToken();
25
24
 
26
- const { size, changeSchemas, deselectSchema, activeSchema, activeElements } = props;
25
+ const { size, changeSchemas, deselectSchema, activeSchema } = props;
27
26
  const form = useForm();
28
27
 
29
28
  const i18n = useContext(I18nContext);
30
29
  const pluginsRegistry = useContext(PluginsRegistry);
31
30
  const options = useContext(OptionsContext);
32
31
 
33
- const [widgets, setWidgets] = useState<{
34
- [key: string]: (props: PropPanelWidgetProps) => React.JSX.Element;
35
- }>({});
36
-
37
- useEffect(() => {
38
- const newWidgets: typeof widgets = {
39
- AlignWidget: (p) => <AlignWidget {...p} {...props} options={options} />,
40
- Divider: () => (
41
- <Divider style={{ marginTop: token.marginXS, marginBottom: token.marginXS }} />
42
- ),
43
- ButtonGroup: (p) => <ButtonGroupWidget {...p} {...props} options={options} />,
44
- };
45
- for (const plugin of Object.values(pluginsRegistry)) {
46
- const widgets = plugin?.propPanel.widgets || {};
47
- Object.entries(widgets).forEach(([widgetKey, widgetValue]) => {
48
- newWidgets[widgetKey] = (p) => (
49
- <WidgetRenderer
50
- {...p}
51
- {...props}
52
- options={options}
53
- theme={token}
54
- i18n={i18n as (key: keyof Dict | string) => string}
55
- widget={widgetValue}
56
- />
57
- );
58
- });
59
- }
60
- setWidgets(newWidgets);
61
- }, [activeSchema, activeElements, pluginsRegistry, JSON.stringify(options)]);
62
-
63
32
  useEffect(() => {
64
33
  const values: any = { ...activeSchema };
65
-
66
34
  // [position] Change the nested position object into a flat, as a three-column layout is difficult to implement
67
35
  values.x = values.position.x;
68
36
  values.y = values.position.y;
69
37
  delete values.position;
38
+ form.setValues(values);
70
39
 
71
- if (values.key !== (form.getValues() || {}).key) {
72
- form.resetFields();
73
- }
40
+ }, [activeSchema, form]);
74
41
 
75
- form.setValues(values);
76
- }, [form, activeSchema]);
77
42
 
78
43
  const handleWatch = (formSchema: any) => {
79
44
  const formAndSchemaValuesDiffer = (formValue: any, schemaValue: any): boolean => {
@@ -102,7 +67,7 @@ const DetailView = (
102
67
  // FIXME memo: https://github.com/pdfme/pdfme/pull/367#issuecomment-1857468274
103
68
  if (value === null && ['rotate', 'opacity'].includes(key)) value = undefined;
104
69
 
105
- changes.push({key, value, schemaId: activeSchema.id});
70
+ changes.push({ key, value, schemaId: activeSchema.id });
106
71
  }
107
72
  }
108
73
 
@@ -111,11 +76,11 @@ const DetailView = (
111
76
  form.validateFields()
112
77
  .then(() => changeSchemas(changes))
113
78
  .catch((reason: ValidateErrorEntity) => {
114
- if (reason.errorFields.length) {
79
+ if (reason.errorFields.length) {
115
80
  changes = changes.filter((change: ChangeSchemaItem) => !reason.errorFields.find((field: {
116
- name: InternalNamePath;
117
- errors: string[];
118
- }) => field.name.includes(change.key)
81
+ name: InternalNamePath;
82
+ errors: string[];
83
+ }) => field.name.includes(change.key)
119
84
  ));
120
85
  }
121
86
  if (changes.length) {
@@ -216,6 +181,31 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
216
181
  };
217
182
  }
218
183
 
184
+ const allWidgets: {
185
+ [key: string]: (props: PropPanelWidgetProps) => React.JSX.Element;
186
+ } = {
187
+ AlignWidget: (p) => <AlignWidget {...p} {...props} options={options} />,
188
+ Divider: () => (
189
+ <Divider style={{ marginTop: token.marginXS, marginBottom: token.marginXS }} />
190
+ ),
191
+ ButtonGroup: (p) => <ButtonGroupWidget {...p} {...props} options={options} />,
192
+ };
193
+ for (const plugin of Object.values(pluginsRegistry)) {
194
+ const widgets = plugin?.propPanel.widgets || {};
195
+ Object.entries(widgets).forEach(([widgetKey, widgetValue]) => {
196
+ allWidgets[widgetKey] = (p) => (
197
+ <WidgetRenderer
198
+ {...p}
199
+ {...props}
200
+ options={options}
201
+ theme={token}
202
+ i18n={i18n as (key: keyof Dict | string) => string}
203
+ widget={widgetValue}
204
+ />
205
+ );
206
+ });
207
+ }
208
+
219
209
  return (
220
210
  <div>
221
211
  <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
@@ -245,7 +235,7 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
245
235
  <FormRender
246
236
  form={form}
247
237
  schema={propPanelSchema}
248
- widgets={widgets}
238
+ widgets={allWidgets}
249
239
  watch={{ '#': handleWatch }}
250
240
  locale="en-US"
251
241
  />
@@ -254,4 +244,8 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
254
244
  );
255
245
  };
256
246
 
257
- export default DetailView;
247
+ const propsAreUnchanged = (prevProps: DetailViewProps, nextProps: DetailViewProps) => {
248
+ return JSON.stringify(prevProps.activeSchema) == JSON.stringify(nextProps.activeSchema)
249
+ };
250
+
251
+ export default React.memo(DetailView, propsAreUnchanged);
@@ -19,6 +19,7 @@ import { I18nContext, PluginsRegistry } from '../../contexts';
19
19
  import {
20
20
  schemasList2template,
21
21
  uuid,
22
+ round,
22
23
  cloneDeep,
23
24
  template2SchemasList,
24
25
  getPagesScrollTopByIndex,
@@ -51,7 +52,7 @@ const TemplateEditor = ({
51
52
  onSaveTemplate: (t: Template) => void;
52
53
  onChangeTemplate: (t: Template) => void;
53
54
  } & {
54
- onChangeTemplate: (t: Template) => void
55
+ onChangeTemplate: (t: Template) => void
55
56
  onPageCursorChange: (newPageCursor: number) => void
56
57
  }) => {
57
58
  const past = useRef<SchemaForUI[][]>([]);
@@ -253,7 +254,7 @@ const TemplateEditor = ({
253
254
  const moveY = (event.delta.y - canvasTopOffsetFromPageCorner) / scale;
254
255
  const moveX = (event.delta.x - canvasLeftOffsetFromPageCorner) / scale;
255
256
 
256
- const position = { x: px2mm(Math.max(0, moveX)), y: px2mm(Math.max(0, moveY)) }
257
+ const position = { x: round(px2mm(Math.max(0, moveX)), 2), y: round(px2mm(Math.max(0, moveY)), 2) }
257
258
 
258
259
  addSchema({ ...(active.data.current as Schema), position });
259
260
  }}
package/src/helper.ts CHANGED
@@ -489,4 +489,4 @@ export const changeSchemas = (args: {
489
489
  return acc;
490
490
  }, cloneDeep(schemas));
491
491
  commitSchemas(newSchemas);
492
- };
492
+ };