@pdfme/ui 5.5.3 → 5.5.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.
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import type { SidebarProps } from '../../../../types.js';
3
- declare const ListView: (props: Pick<SidebarProps, "schemas" | "onSortEnd" | "onEdit" | "size" | "hoveringSchemaId" | "onChangeHoveringSchemaId" | "changeSchemas">) => React.JSX.Element;
3
+ declare const ListView: (props: Pick<SidebarProps, "schemas" | "onSortEnd" | "onEdit" | "hoveringSchemaId" | "onChangeHoveringSchemaId" | "changeSchemas">) => React.JSX.Element;
4
4
  export default ListView;
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ export declare const SIDEBAR_H_PADDING_PX = 16;
3
+ export declare const SIDEBAR_V_PADDING_PX = 8;
4
+ export declare const SIDEBAR_HEADER_HEIGHT = 60;
5
+ type SectionProps = {
6
+ children: React.ReactNode;
7
+ };
8
+ type SidebarFrameProps = SectionProps & {
9
+ className?: string;
10
+ };
11
+ export declare const SidebarFrame: ({ children, className }: SidebarFrameProps) => React.JSX.Element;
12
+ export declare const SidebarHeader: ({ children }: SectionProps) => React.JSX.Element;
13
+ export declare const SidebarBody: ({ children }: SectionProps) => React.JSX.Element;
14
+ export declare const SidebarFooter: ({ children }: SectionProps) => React.JSX.Element;
15
+ export {};
@@ -54,7 +54,6 @@ export declare const moveCommandToChangeSchemasArg: (props: {
54
54
  schemaId: string;
55
55
  }[];
56
56
  export declare const getPagesScrollTopByIndex: (pageSizes: Size[], index: number, scale: number) => number;
57
- export declare const getSidebarContentHeight: (sidebarHeight: number) => number;
58
57
  export declare const changeSchemas: (args: {
59
58
  objs: {
60
59
  key: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pdfme/ui",
3
- "version": "5.5.3",
3
+ "version": "5.5.4",
4
4
  "sideEffects": false,
5
5
  "author": "hand-dot",
6
6
  "license": "MIT",
@@ -1,5 +1,5 @@
1
1
  import { useForm } from 'form-render';
2
- import React, { useRef, useContext, useState, useEffect } from 'react';
2
+ import React, { useRef, useContext, useState, useEffect, useCallback } from 'react';
3
3
  import type {
4
4
  Dict,
5
5
  ChangeSchemaItem,
@@ -12,13 +12,14 @@ import { isBlankPdf } from '@pdfme/common';
12
12
  import type { SidebarProps } from '../../../../types.js';
13
13
  import { Menu } from 'lucide-react';
14
14
  import { I18nContext, PluginsRegistry, OptionsContext } from '../../../../contexts.js';
15
- import { getSidebarContentHeight, debounce } from '../../../../helper.js';
15
+ import { debounce } from '../../../../helper.js';
16
16
  import { DESIGNER_CLASSNAME } from '../../../../constants.js';
17
17
  import { theme, Typography, Button, Divider } from 'antd';
18
18
  import AlignWidget from './AlignWidget.js';
19
19
  import WidgetRenderer from './WidgetRenderer.js';
20
20
  import ButtonGroupWidget from './ButtonGroupWidget.js';
21
21
  import { InternalNamePath, ValidateErrorEntity } from 'rc-field-form/es/interface.js';
22
+ import { SidebarBody, SidebarFrame, SidebarHeader, SIDEBAR_H_PADDING_PX } from '../layout.js';
22
23
 
23
24
  // Import FormRender as a default import
24
25
  import FormRenderComponent from 'form-render';
@@ -42,8 +43,7 @@ type DetailViewProps = Pick<
42
43
  const DetailView = (props: DetailViewProps) => {
43
44
  const { token } = theme.useToken();
44
45
 
45
- const { size, schemasList, changeSchemas, deselectSchema, activeSchema, pageSize, basePdf } =
46
- props;
46
+ const { schemasList, changeSchemas, deselectSchema, activeSchema, pageSize, basePdf } = props;
47
47
  const form = useForm();
48
48
 
49
49
  const i18n = useContext(I18nContext);
@@ -51,10 +51,13 @@ const DetailView = (props: DetailViewProps) => {
51
51
  const options = useContext(OptionsContext);
52
52
 
53
53
  // Define a type-safe i18n function that accepts string keys
54
- const typedI18n = (key: string): string => {
55
- // Use a type assertion to handle the union type constraint
56
- return typeof i18n === 'function' ? i18n(key as keyof Dict) : key;
57
- };
54
+ const typedI18n = useCallback(
55
+ (key: string): string => {
56
+ // Use a type assertion to handle the union type constraint
57
+ return typeof i18n === 'function' ? i18n(key as keyof Dict) : key;
58
+ },
59
+ [i18n],
60
+ );
58
61
 
59
62
  const [widgets, setWidgets] = useState<{
60
63
  [key: string]: (props: PropPanelWidgetProps) => React.JSX.Element;
@@ -84,7 +87,7 @@ const DetailView = (props: DetailViewProps) => {
84
87
  });
85
88
  }
86
89
  setWidgets(newWidgets);
87
- }, [activeSchema, pluginsRegistry, JSON.stringify(options)]);
90
+ }, [activeSchema, options, pluginsRegistry, props, token, typedI18n]);
88
91
 
89
92
  useEffect(() => {
90
93
  // Create a type-safe copy of the schema with editable property
@@ -95,7 +98,7 @@ const DetailView = (props: DetailViewProps) => {
95
98
  form.setValues(values);
96
99
  }, [activeSchema, form]);
97
100
 
98
- useEffect(() => form.resetFields(), [activeSchema.id]);
101
+ useEffect(() => form.resetFields(), [activeSchema.id, form]);
99
102
 
100
103
  useEffect(() => {
101
104
  uniqueSchemaName.current = (value: string): boolean => {
@@ -424,16 +427,20 @@ const DetailView = (props: DetailViewProps) => {
424
427
  }
425
428
 
426
429
  return (
427
- <div className={DESIGNER_CLASSNAME + 'detail-view'}>
428
- <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
430
+ <SidebarFrame className={DESIGNER_CLASSNAME + 'detail-view'}>
431
+ <SidebarHeader>
429
432
  <Button
430
433
  className={DESIGNER_CLASSNAME + 'back-button'}
431
434
  style={{
432
435
  position: 'absolute',
436
+ left: SIDEBAR_H_PADDING_PX,
433
437
  zIndex: 100,
434
438
  display: 'flex',
435
439
  alignItems: 'center',
436
440
  justifyContent: 'center',
441
+ transform: 'translateY(-50%)',
442
+ top: '50%',
443
+ paddingTop: '3px',
437
444
  }}
438
445
  onClick={deselectSchema}
439
446
  icon={<Menu strokeWidth={1.5} size={20} />}
@@ -441,15 +448,8 @@ const DetailView = (props: DetailViewProps) => {
441
448
  <Text strong style={{ textAlign: 'center', width: '100%' }}>
442
449
  {typedI18n('editField')}
443
450
  </Text>
444
- </div>
445
- <Divider style={{ marginTop: token.marginXS, marginBottom: token.marginXS }} />
446
- <div
447
- style={{
448
- height: getSidebarContentHeight(size.height),
449
- overflowY: 'auto',
450
- overflowX: 'hidden',
451
- }}
452
- >
451
+ </SidebarHeader>
452
+ <SidebarBody>
453
453
  <FormRenderComponent
454
454
  form={form}
455
455
  schema={propPanelSchema}
@@ -457,8 +457,8 @@ const DetailView = (props: DetailViewProps) => {
457
457
  watch={{ '#': handleWatch }}
458
458
  locale="en-US"
459
459
  />
460
- </div>
461
- </div>
460
+ </SidebarBody>
461
+ </SidebarFrame>
462
462
  );
463
463
  };
464
464
 
@@ -135,29 +135,27 @@ const SelectableSortableContainer = (
135
135
  }}
136
136
  >
137
137
  <>
138
- <div style={{ height: '100%', overflowY: 'auto' }}>
139
- <SortableContext items={schemas} strategy={verticalListSortingStrategy}>
140
- <ul style={{ margin: 0, padding: 0, listStyle: 'none', borderRadius: 5 }}>
141
- {schemas.map((schema) => (
142
- <SelectableSortableItem
143
- key={schema.id}
144
- style={{
145
- border: `1px solid ${
146
- schema.id === hoveringSchemaId ? token.colorPrimary : 'transparent'
147
- }`,
148
- }}
149
- schema={schema}
150
- schemas={schemas}
151
- isSelected={isItemSelected(schema.id) || activeId === schema.id}
152
- onEdit={onEdit}
153
- onSelect={onSelectionChanged}
154
- onMouseEnter={() => onChangeHoveringSchemaId(schema.id)}
155
- onMouseLeave={() => onChangeHoveringSchemaId(null)}
156
- />
157
- ))}
158
- </ul>
159
- </SortableContext>
160
- </div>
138
+ <SortableContext items={schemas} strategy={verticalListSortingStrategy}>
139
+ <ul style={{ margin: 0, padding: 0, listStyle: 'none', borderRadius: 5 }}>
140
+ {schemas.map((schema) => (
141
+ <SelectableSortableItem
142
+ key={schema.id}
143
+ style={{
144
+ border: `1px solid ${
145
+ schema.id === hoveringSchemaId ? token.colorPrimary : 'transparent'
146
+ }`,
147
+ }}
148
+ schema={schema}
149
+ schemas={schemas}
150
+ isSelected={isItemSelected(schema.id) || activeId === schema.id}
151
+ onEdit={onEdit}
152
+ onSelect={onSelectionChanged}
153
+ onMouseEnter={() => onChangeHoveringSchemaId(schema.id)}
154
+ onMouseLeave={() => onChangeHoveringSchemaId(null)}
155
+ />
156
+ ))}
157
+ </ul>
158
+ </SortableContext>
161
159
  {createPortal(
162
160
  <DragOverlay adjustScale>
163
161
  {activeId
@@ -1,42 +1,30 @@
1
1
  import React, { useContext, useState } from 'react';
2
2
  import type { SidebarProps } from '../../../../types.js';
3
- import { RIGHT_SIDEBAR_WIDTH, DESIGNER_CLASSNAME } from '../../../../constants.js';
3
+ import { DESIGNER_CLASSNAME } from '../../../../constants.js';
4
4
  import { I18nContext } from '../../../../contexts.js';
5
- import { getSidebarContentHeight } from '../../../../helper.js';
6
- import { theme, Input, Typography, Divider, Button } from 'antd';
5
+ import { Input, Typography, Button } from 'antd';
7
6
  import SelectableSortableContainer from './SelectableSortableContainer.js';
7
+ import { SidebarBody, SidebarFooter, SidebarFrame, SidebarHeader } from '../layout.js';
8
8
 
9
9
  const { Text } = Typography;
10
10
  const { TextArea } = Input;
11
11
 
12
- const headHeight = 40;
13
-
14
12
  const ListView = (
15
13
  props: Pick<
16
14
  SidebarProps,
17
15
  | 'schemas'
18
16
  | 'onSortEnd'
19
17
  | 'onEdit'
20
- | 'size'
21
18
  | 'hoveringSchemaId'
22
19
  | 'onChangeHoveringSchemaId'
23
20
  | 'changeSchemas'
24
21
  >,
25
22
  ) => {
26
- const {
27
- schemas,
28
- onSortEnd,
29
- onEdit,
30
- size,
31
- hoveringSchemaId,
32
- onChangeHoveringSchemaId,
33
- changeSchemas,
34
- } = props;
35
- const { token } = theme.useToken();
23
+ const { schemas, onSortEnd, onEdit, hoveringSchemaId, onChangeHoveringSchemaId, changeSchemas } =
24
+ props;
36
25
  const i18n = useContext(I18nContext);
37
26
  const [isBulkUpdateFieldNamesMode, setIsBulkUpdateFieldNamesMode] = useState(false);
38
27
  const [fieldNamesValue, setFieldNamesValue] = useState('');
39
- const height = getSidebarContentHeight(size.height);
40
28
 
41
29
  const commitBulk = () => {
42
30
  const names = fieldNamesValue.split('\n');
@@ -60,23 +48,22 @@ const ListView = (
60
48
  };
61
49
 
62
50
  return (
63
- <div className={DESIGNER_CLASSNAME + 'list-view'}>
64
- <div style={{ height: headHeight, display: 'flex', alignItems: 'center' }}>
51
+ <SidebarFrame className={DESIGNER_CLASSNAME + 'list-view'}>
52
+ <SidebarHeader>
65
53
  <Text strong style={{ textAlign: 'center', width: '100%' }}>
66
54
  {i18n('fieldsList')}
67
55
  </Text>
68
- </div>
69
- <Divider style={{ marginTop: token.marginXS, marginBottom: token.marginXS }} />
70
- <div style={{ height: height - headHeight }}>
56
+ </SidebarHeader>
57
+ <SidebarBody>
71
58
  {isBulkUpdateFieldNamesMode ? (
72
59
  <TextArea
73
60
  wrap="off"
74
61
  value={fieldNamesValue}
75
62
  onChange={(e) => setFieldNamesValue(e.target.value)}
76
63
  style={{
77
- paddingLeft: 30,
78
- height: height - headHeight,
79
- width: RIGHT_SIDEBAR_WIDTH - 35,
64
+ height: '100%',
65
+ width: '100%',
66
+ resize: 'none',
80
67
  lineHeight: '2.75rem',
81
68
  }}
82
69
  />
@@ -89,32 +76,40 @@ const ListView = (
89
76
  onEdit={onEdit}
90
77
  />
91
78
  )}
92
- <div
93
- style={{
94
- paddingTop: '0.5rem',
95
- display: 'flex',
96
- alignItems: 'center',
97
- justifyContent: 'flex-end',
98
- }}
99
- >
100
- {isBulkUpdateFieldNamesMode ? (
101
- <>
102
- <Button className={DESIGNER_CLASSNAME + 'bulk-commit'} size="small" type="text" onClick={commitBulk}>
103
- <u> {i18n('commitBulkUpdateFieldName')}</u>
104
- </Button>
105
- <span style={{ margin: '0 1rem' }}>/</span>
106
- <Button className={DESIGNER_CLASSNAME + 'bulk-cancel'} size="small" type="text" onClick={() => setIsBulkUpdateFieldNamesMode(false)}>
107
- <u> {i18n('cancel')}</u>
108
- </Button>
109
- </>
110
- ) : (
111
- <Button className={DESIGNER_CLASSNAME + 'bulk-update'} size="small" type="text" onClick={startBulk}>
112
- <u> {i18n('bulkUpdateFieldName')}</u>
79
+ </SidebarBody>
80
+ <SidebarFooter>
81
+ {isBulkUpdateFieldNamesMode ? (
82
+ <>
83
+ <Button
84
+ className={DESIGNER_CLASSNAME + 'bulk-commit'}
85
+ size="small"
86
+ type="text"
87
+ onClick={commitBulk}
88
+ >
89
+ <u> {i18n('commitBulkUpdateFieldName')}</u>
90
+ </Button>
91
+ <span>/</span>
92
+ <Button
93
+ className={DESIGNER_CLASSNAME + 'bulk-cancel'}
94
+ size="small"
95
+ type="text"
96
+ onClick={() => setIsBulkUpdateFieldNamesMode(false)}
97
+ >
98
+ <u> {i18n('cancel')}</u>
113
99
  </Button>
114
- )}
115
- </div>
116
- </div>
117
- </div>
100
+ </>
101
+ ) : (
102
+ <Button
103
+ className={DESIGNER_CLASSNAME + 'bulk-update'}
104
+ size="small"
105
+ type="text"
106
+ onClick={startBulk}
107
+ >
108
+ <u> {i18n('bulkUpdateFieldName')}</u>
109
+ </Button>
110
+ )}
111
+ </SidebarFooter>
112
+ </SidebarFrame>
118
113
  );
119
114
  };
120
115
 
@@ -30,44 +30,40 @@ const Sidebar = (props: SidebarProps) => {
30
30
  width: sidebarOpen ? RIGHT_SIDEBAR_WIDTH : 0,
31
31
  }}
32
32
  >
33
- <div>
34
- <Button
35
- className={DESIGNER_CLASSNAME + 'sidebar-toggle'}
36
- style={{
37
- position: 'absolute',
38
- display: 'flex',
39
- alignItems: 'center',
40
- justifyContent: 'center',
41
- top: '1rem',
42
- right: '1rem',
43
- zIndex: 100,
44
- }}
45
- icon={sidebarOpen ? <ArrowRight {...iconProps} /> : <ArrowLeft {...iconProps} />}
46
- onClick={() => setSidebarOpen(!sidebarOpen)}
47
- />
48
- <div
49
- style={{
50
- width: RIGHT_SIDEBAR_WIDTH,
51
- height: '100%',
52
- display: sidebarOpen ? 'block' : 'none',
53
- top: 0,
54
- right: 0,
55
- position: 'absolute',
56
- padding: '0.7rem 1rem',
57
- overflowY: 'auto',
58
- fontFamily: "'Open Sans', sans-serif",
59
- boxSizing: 'border-box',
60
- background: token.colorBgLayout,
61
- }}
62
- >
63
- <div>
64
- {getActiveSchemas().length === 0 ? (
65
- <ListView {...props} />
66
- ) : (
67
- <DetailView {...props} activeSchema={getLastActiveSchema()} />
68
- )}
69
- </div>
70
- </div>
33
+ <Button
34
+ className={DESIGNER_CLASSNAME + 'sidebar-toggle'}
35
+ style={{
36
+ position: 'absolute',
37
+ display: 'flex',
38
+ alignItems: 'center',
39
+ justifyContent: 'center',
40
+ top: '14px',
41
+ right: '16px',
42
+ paddingTop: '2px',
43
+ zIndex: 100,
44
+ }}
45
+ icon={sidebarOpen ? <ArrowRight {...iconProps} /> : <ArrowLeft {...iconProps} />}
46
+ onClick={() => setSidebarOpen(!sidebarOpen)}
47
+ />
48
+ <div
49
+ style={{
50
+ width: RIGHT_SIDEBAR_WIDTH,
51
+ height: '100%',
52
+ display: sidebarOpen ? 'flex' : 'none',
53
+ top: 0,
54
+ right: 0,
55
+ position: 'absolute',
56
+ fontFamily: "'Open Sans', sans-serif",
57
+ boxSizing: 'border-box',
58
+ background: token.colorBgLayout,
59
+ borderLeft: `1px solid ${token.colorSplit}`,
60
+ }}
61
+ >
62
+ {getActiveSchemas().length === 0 ? (
63
+ <ListView {...props} />
64
+ ) : (
65
+ <DetailView {...props} activeSchema={getLastActiveSchema()} />
66
+ )}
71
67
  </div>
72
68
  </div>
73
69
  );
@@ -0,0 +1,75 @@
1
+ import React from 'react';
2
+ import { Divider } from 'antd';
3
+
4
+ export const SIDEBAR_H_PADDING_PX = 16;
5
+ export const SIDEBAR_V_PADDING_PX = 8;
6
+ export const SIDEBAR_HEADER_HEIGHT = 60;
7
+
8
+ type SectionProps = {
9
+ children: React.ReactNode;
10
+ };
11
+ type SidebarFrameProps = SectionProps & {
12
+ className?: string;
13
+ };
14
+
15
+ export const SidebarFrame = ({ children, className }: SidebarFrameProps) => (
16
+ <div
17
+ className={className}
18
+ style={{
19
+ height: '100%',
20
+ display: 'flex',
21
+ flex: 1,
22
+ flexDirection: 'column',
23
+ }}
24
+ >
25
+ {children}
26
+ </div>
27
+ );
28
+
29
+ export const SidebarHeader = ({ children }: SectionProps) => (
30
+ <div
31
+ style={{
32
+ position: 'relative',
33
+ minHeight: SIDEBAR_HEADER_HEIGHT,
34
+ display: 'flex',
35
+ flexShrink: 0,
36
+ flexDirection: 'column',
37
+ justifyContent: 'center',
38
+ padding: `${SIDEBAR_V_PADDING_PX}px ${SIDEBAR_H_PADDING_PX}px 0`,
39
+ }}
40
+ >
41
+ <div style={{ minHeight: 40, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
42
+ {children}
43
+ </div>
44
+ <Divider style={{ marginTop: `${SIDEBAR_V_PADDING_PX}px`, marginBottom: 0 }} />
45
+ </div>
46
+ );
47
+
48
+ export const SidebarBody = ({ children }: SectionProps) => (
49
+ <div
50
+ style={{
51
+ flex: 1,
52
+ minHeight: 0,
53
+ overflowY: 'auto',
54
+ overflowX: 'hidden',
55
+ padding: `${SIDEBAR_V_PADDING_PX}px ${SIDEBAR_H_PADDING_PX}px`,
56
+ }}
57
+ >
58
+ {children}
59
+ </div>
60
+ );
61
+
62
+ export const SidebarFooter = ({ children }: SectionProps) => (
63
+ <div
64
+ style={{
65
+ display: 'flex',
66
+ flexShrink: 0,
67
+ alignItems: 'center',
68
+ justifyContent: 'flex-end',
69
+ gap: `${SIDEBAR_V_PADDING_PX}px`,
70
+ padding: `${SIDEBAR_H_PADDING_PX}px`,
71
+ }}
72
+ >
73
+ {children}
74
+ </div>
75
+ );
package/src/helper.ts CHANGED
@@ -420,9 +420,6 @@ export const getPagesScrollTopByIndex = (pageSizes: Size[], index: number, scale
420
420
  .reduce((acc, cur) => acc + (cur.height * ZOOM + RULER_HEIGHT * scale) * scale, 0);
421
421
  };
422
422
 
423
- export const getSidebarContentHeight = (sidebarHeight: number) =>
424
- sidebarHeight - RULER_HEIGHT - RULER_HEIGHT / 2 - 30;
425
-
426
423
  const handlePositionSizeChange = (
427
424
  schema: SchemaForUI,
428
425
  key: string,