@pdfme/ui 1.0.5 → 1.0.8
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/README.md +30 -2
- package/dist/index.js +1 -1
- package/dist/index.js.LICENSE.txt +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/class.d.ts +1 -1
- package/dist/types/components/{Preview/Pager/Page.d.ts → CtlBar/Pager.d.ts} +0 -0
- package/dist/types/components/CtlBar/Zoom.d.ts +6 -0
- package/dist/types/components/CtlBar/index.d.ts +11 -0
- package/dist/types/components/Paper.d.ts +2 -2
- package/dist/types/components/{Preview/index.d.ts → Preview.d.ts} +0 -0
- package/dist/types/components/UnitPager.d.ts +9 -0
- package/dist/types/contexts.d.ts +1 -1
- package/dist/types/helper.d.ts +4 -0
- package/dist/types/hooks.d.ts +4 -4
- package/dist/types/i18n.d.ts +2 -0
- package/package.json +9 -1
- package/src/assets/icons/add.svg +3 -0
- package/src/assets/icons/remove.svg +3 -0
- package/src/components/CtlBar/Pager.tsx +60 -0
- package/src/components/CtlBar/Zoom.tsx +57 -0
- package/src/components/CtlBar/index.tsx +49 -0
- package/src/components/Designer/Main/index.tsx +2 -2
- package/src/components/Designer/Sidebar/index.tsx +9 -4
- package/src/components/Designer/index.tsx +28 -12
- package/src/components/Error.tsx +1 -1
- package/src/components/Paper.tsx +3 -2
- package/src/components/{Preview/index.tsx → Preview.tsx} +48 -38
- package/src/components/Root.tsx +1 -1
- package/src/components/UnitPager.tsx +105 -0
- package/src/helper.ts +14 -0
- package/src/hooks.ts +16 -18
- package/src/i18n.ts +4 -0
- package/dist/types/components/Preview/Pager/Unit.d.ts +0 -7
- package/src/components/Preview/Pager/Page.tsx +0 -85
- package/src/components/Preview/Pager/Unit.tsx +0 -87
@@ -0,0 +1,105 @@
|
|
1
|
+
import React, { useContext } from 'react';
|
2
|
+
import left from '../assets/icons/left.svg';
|
3
|
+
import right from '../assets/icons/right.svg';
|
4
|
+
import doubleLeft from '../assets/icons/double-left.svg';
|
5
|
+
import doubleRight from '../assets/icons/double-right.svg';
|
6
|
+
import { I18nContext } from '../contexts';
|
7
|
+
import { Size } from '@pdfme/common';
|
8
|
+
|
9
|
+
const buttonHeight = 38;
|
10
|
+
const buttonWrapStyle: React.CSSProperties = {
|
11
|
+
position: 'sticky',
|
12
|
+
zIndex: 1,
|
13
|
+
backgroundColor: '#777777bd',
|
14
|
+
borderRadius: 2,
|
15
|
+
padding: '0.5rem',
|
16
|
+
display: 'flex',
|
17
|
+
alignItems: 'center',
|
18
|
+
justifyContent: 'space-around',
|
19
|
+
boxSizing: 'border-box',
|
20
|
+
width: 110,
|
21
|
+
height: buttonHeight,
|
22
|
+
};
|
23
|
+
|
24
|
+
const btnStyle: React.CSSProperties = {
|
25
|
+
cursor: 'pointer',
|
26
|
+
border: 'none',
|
27
|
+
background: 'none',
|
28
|
+
display: 'flex',
|
29
|
+
alignItems: 'center',
|
30
|
+
};
|
31
|
+
|
32
|
+
type Props = {
|
33
|
+
size: Size;
|
34
|
+
unitCursor: number;
|
35
|
+
unitNum: number;
|
36
|
+
setUnitCursor: (page: number) => void;
|
37
|
+
};
|
38
|
+
|
39
|
+
const UnitPager = ({ size, unitCursor, unitNum, setUnitCursor }: Props) => {
|
40
|
+
const i18n = useContext(I18nContext);
|
41
|
+
|
42
|
+
if (unitNum <= 1) return <></>;
|
43
|
+
|
44
|
+
return (
|
45
|
+
<div style={{ position: 'absolute', ...size }}>
|
46
|
+
<div
|
47
|
+
style={{
|
48
|
+
position: 'sticky',
|
49
|
+
width: '100%',
|
50
|
+
zIndex: 1,
|
51
|
+
top: `calc(50% - ${buttonHeight / 2}px)`,
|
52
|
+
display: 'flex',
|
53
|
+
alignItems: 'center',
|
54
|
+
}}
|
55
|
+
>
|
56
|
+
{unitCursor > 0 && (
|
57
|
+
<div style={{ left: '1rem', marginLeft: '1rem', ...buttonWrapStyle }}>
|
58
|
+
<button
|
59
|
+
style={{ paddingLeft: '0.5rem', ...btnStyle }}
|
60
|
+
disabled={unitCursor <= 0}
|
61
|
+
onClick={() => setUnitCursor(0)}
|
62
|
+
>
|
63
|
+
<img src={doubleLeft} alt={i18n('goToFirst')} style={{ width: 20 }} />
|
64
|
+
</button>
|
65
|
+
<button
|
66
|
+
style={{ paddingLeft: '0.5rem', ...btnStyle }}
|
67
|
+
disabled={unitCursor <= 0}
|
68
|
+
onClick={() => setUnitCursor(unitCursor - 1)}
|
69
|
+
>
|
70
|
+
<img src={left} alt={i18n('goToPrevious')} style={{ width: 20 }} />
|
71
|
+
</button>
|
72
|
+
<strong style={{ color: 'white', fontSize: '0.9rem' }}>
|
73
|
+
{unitCursor + 1}/{unitNum}
|
74
|
+
</strong>
|
75
|
+
</div>
|
76
|
+
)}
|
77
|
+
{unitCursor + 1 < unitNum && (
|
78
|
+
<div
|
79
|
+
style={{ right: '1rem', marginLeft: 'auto', marginRight: '1rem', ...buttonWrapStyle }}
|
80
|
+
>
|
81
|
+
<strong style={{ color: 'white', fontSize: '0.9rem' }}>
|
82
|
+
{unitCursor + 1}/{unitNum}
|
83
|
+
</strong>
|
84
|
+
<button
|
85
|
+
style={{ paddingRight: '0.5rem', ...btnStyle }}
|
86
|
+
disabled={unitCursor + 1 >= unitNum}
|
87
|
+
onClick={() => setUnitCursor(unitCursor + 1)}
|
88
|
+
>
|
89
|
+
<img src={right} alt={i18n('goToNext')} style={{ width: 20 }} />
|
90
|
+
</button>
|
91
|
+
<button
|
92
|
+
style={{ paddingRight: '0.5rem', ...btnStyle }}
|
93
|
+
disabled={unitCursor + 1 >= unitNum}
|
94
|
+
onClick={() => setUnitCursor(unitNum - 1)}
|
95
|
+
>
|
96
|
+
<img src={doubleRight} alt={i18n('goToFirst')} style={{ width: 20 }} />
|
97
|
+
</button>
|
98
|
+
</div>
|
99
|
+
)}
|
100
|
+
</div>
|
101
|
+
</div>
|
102
|
+
);
|
103
|
+
};
|
104
|
+
|
105
|
+
export default UnitPager;
|
package/src/helper.ts
CHANGED
@@ -15,6 +15,7 @@ import {
|
|
15
15
|
DEFAULT_CHARACTER_SPACING,
|
16
16
|
DEFAULT_LINE_HEIGHT,
|
17
17
|
} from '@pdfme/common';
|
18
|
+
import { ZOOM, RULER_HEIGHT } from './constants';
|
18
19
|
|
19
20
|
export const uuid = () =>
|
20
21
|
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
@@ -527,3 +528,16 @@ export const moveCommandToChangeSchemasArg = (props: {
|
|
527
528
|
return { key: `position.${key}`, value, schemaId: as.id };
|
528
529
|
});
|
529
530
|
};
|
531
|
+
|
532
|
+
export const getPagesScrollTopByIndex = (
|
533
|
+
pageSizes: {
|
534
|
+
width: number;
|
535
|
+
height: number;
|
536
|
+
}[],
|
537
|
+
index: number,
|
538
|
+
scale: number
|
539
|
+
) => {
|
540
|
+
return pageSizes
|
541
|
+
.slice(0, index)
|
542
|
+
.reduce((acc, cur) => acc + (cur.height * ZOOM + RULER_HEIGHT * scale) * scale, 0);
|
543
|
+
};
|
package/src/hooks.ts
CHANGED
@@ -14,9 +14,9 @@ export const usePrevious = <T>(value: T) => {
|
|
14
14
|
|
15
15
|
const getScale = (n: number, paper: number) => (n / paper > 1 ? 1 : n / paper);
|
16
16
|
|
17
|
-
type UIPreProcessorProps = { template: Template; size: Size;
|
17
|
+
type UIPreProcessorProps = { template: Template; size: Size; zoomLevel: number };
|
18
18
|
|
19
|
-
export const useUIPreProcessor = ({ template, size,
|
19
|
+
export const useUIPreProcessor = ({ template, size, zoomLevel }: UIPreProcessorProps) => {
|
20
20
|
const [backgrounds, setBackgrounds] = useState<string[]>([]);
|
21
21
|
const [pageSizes, setPageSizes] = useState<Size[]>([]);
|
22
22
|
const [scale, setScale] = useState(0);
|
@@ -32,18 +32,16 @@ export const useUIPreProcessor = ({ template, size, offset = 0 }: UIPreProcessor
|
|
32
32
|
|
33
33
|
const _scale = Math.min(
|
34
34
|
getScale(size.width, paperWidth),
|
35
|
-
getScale(size.height -
|
35
|
+
getScale(size.height - RULER_HEIGHT, paperHeight)
|
36
36
|
);
|
37
37
|
|
38
38
|
return { backgrounds: _backgrounds, pageSizes: _pageSizes, scale: _scale };
|
39
|
-
}, [template, size
|
39
|
+
}, [template, size]);
|
40
40
|
|
41
41
|
useEffect(() => {
|
42
42
|
init()
|
43
|
-
.then((
|
44
|
-
setPageSizes(
|
45
|
-
setScale(data.scale);
|
46
|
-
setBackgrounds(data.backgrounds);
|
43
|
+
.then(({ pageSizes, scale, backgrounds }) => {
|
44
|
+
setPageSizes(pageSizes), setScale(scale), setBackgrounds(backgrounds);
|
47
45
|
})
|
48
46
|
.catch((e: Error) => {
|
49
47
|
console.error(e);
|
@@ -51,11 +49,11 @@ export const useUIPreProcessor = ({ template, size, offset = 0 }: UIPreProcessor
|
|
51
49
|
});
|
52
50
|
}, [init]);
|
53
51
|
|
54
|
-
return { backgrounds, pageSizes, scale, error };
|
52
|
+
return { backgrounds, pageSizes, scale: scale * zoomLevel, error };
|
55
53
|
};
|
56
54
|
|
57
55
|
type ScrollPageCursorProps = {
|
58
|
-
|
56
|
+
ref: RefObject<HTMLDivElement>;
|
59
57
|
pageSizes: Size[];
|
60
58
|
scale: number;
|
61
59
|
pageCursor: number;
|
@@ -63,19 +61,19 @@ type ScrollPageCursorProps = {
|
|
63
61
|
};
|
64
62
|
|
65
63
|
export const useScrollPageCursor = ({
|
66
|
-
|
64
|
+
ref,
|
67
65
|
pageSizes,
|
68
66
|
scale,
|
69
67
|
pageCursor,
|
70
68
|
onChangePageCursor,
|
71
69
|
}: ScrollPageCursorProps) => {
|
72
70
|
const onScroll = useCallback(() => {
|
73
|
-
if (!pageSizes[0] || !
|
71
|
+
if (!pageSizes[0] || !ref.current) {
|
74
72
|
return;
|
75
73
|
}
|
76
74
|
|
77
|
-
const scroll =
|
78
|
-
const { top } =
|
75
|
+
const scroll = ref.current.scrollTop;
|
76
|
+
const { top } = ref.current.getBoundingClientRect();
|
79
77
|
const pageHeights = pageSizes.reduce((acc, cur, i) => {
|
80
78
|
let value = (cur.height * ZOOM + RULER_HEIGHT) * scale;
|
81
79
|
if (i === 0) {
|
@@ -95,15 +93,15 @@ export const useScrollPageCursor = ({
|
|
95
93
|
if (_pageCursor !== pageCursor) {
|
96
94
|
onChangePageCursor(_pageCursor);
|
97
95
|
}
|
98
|
-
}, [onChangePageCursor, pageCursor, pageSizes,
|
96
|
+
}, [onChangePageCursor, pageCursor, pageSizes, ref, scale]);
|
99
97
|
|
100
98
|
useEffect(() => {
|
101
|
-
|
99
|
+
ref.current?.addEventListener('scroll', onScroll);
|
102
100
|
|
103
101
|
return () => {
|
104
|
-
|
102
|
+
ref.current?.removeEventListener('scroll', onScroll);
|
105
103
|
};
|
106
|
-
}, [
|
104
|
+
}, [ref, onScroll]);
|
107
105
|
};
|
108
106
|
|
109
107
|
export const useMountStatus = () => {
|
package/src/i18n.ts
CHANGED
@@ -26,6 +26,8 @@ const dictEn = {
|
|
26
26
|
goToNext: 'Next',
|
27
27
|
goToEnd: 'Go to end',
|
28
28
|
select: 'Select',
|
29
|
+
zoomIn: 'Zoom in',
|
30
|
+
zoomOut: 'Zoom out',
|
29
31
|
errorOccurred: 'An error occurred',
|
30
32
|
errorBulkUpdateFieldName:
|
31
33
|
'Cannot commit the change because the number of items has been changed.',
|
@@ -56,6 +58,8 @@ const dictJa: { [key in keyof DictEn]: string } = {
|
|
56
58
|
goToNext: '1つ進む',
|
57
59
|
goToEnd: '最後に進む',
|
58
60
|
select: '選択',
|
61
|
+
zoomIn: '拡大',
|
62
|
+
zoomOut: '縮小',
|
59
63
|
errorOccurred: 'エラーが発生しました',
|
60
64
|
errorBulkUpdateFieldName: '項目数が変更されているため変更をコミットできません。',
|
61
65
|
commitBulkUpdateFieldName: '変更を反映',
|
@@ -1,85 +0,0 @@
|
|
1
|
-
import React, { useContext } from 'react';
|
2
|
-
import left from '../../../assets/icons/left.svg';
|
3
|
-
import right from '../../../assets/icons/right.svg';
|
4
|
-
import doubleLeft from '../../../assets/icons/double-left.svg';
|
5
|
-
import doubleRight from '../../../assets/icons/double-right.svg';
|
6
|
-
import { I18nContext } from '../../../contexts';
|
7
|
-
|
8
|
-
const btnStyle: React.CSSProperties = {
|
9
|
-
cursor: 'pointer',
|
10
|
-
border: 'none',
|
11
|
-
background: 'none',
|
12
|
-
display: 'flex',
|
13
|
-
alignItems: 'center',
|
14
|
-
};
|
15
|
-
|
16
|
-
type Props = {
|
17
|
-
pageCursor: number;
|
18
|
-
pageNum: number;
|
19
|
-
setPageCursor: (page: number) => void;
|
20
|
-
};
|
21
|
-
|
22
|
-
const Pager = ({ pageCursor, pageNum, setPageCursor }: Props) => {
|
23
|
-
const i18n = useContext(I18nContext);
|
24
|
-
|
25
|
-
if (pageNum <= 1) return <></>;
|
26
|
-
|
27
|
-
return (
|
28
|
-
<div
|
29
|
-
style={{
|
30
|
-
position: 'sticky',
|
31
|
-
top: '90%',
|
32
|
-
zIndex: 1,
|
33
|
-
display: 'flex',
|
34
|
-
alignItems: 'center',
|
35
|
-
justifyContent: 'center',
|
36
|
-
width: '100%',
|
37
|
-
}}
|
38
|
-
>
|
39
|
-
<div
|
40
|
-
style={{
|
41
|
-
display: 'flex',
|
42
|
-
alignItems: 'center',
|
43
|
-
justifyContent: 'center',
|
44
|
-
background: '#777777e6',
|
45
|
-
borderRadius: 2,
|
46
|
-
padding: '0.5rem',
|
47
|
-
}}
|
48
|
-
>
|
49
|
-
<button
|
50
|
-
style={{ paddingLeft: '0.5rem', ...btnStyle }}
|
51
|
-
disabled={pageCursor <= 0}
|
52
|
-
onClick={() => setPageCursor(0)}
|
53
|
-
>
|
54
|
-
<img src={doubleLeft} alt={i18n('goToFirst')} style={{ width: 20 }} />
|
55
|
-
</button>
|
56
|
-
<button
|
57
|
-
style={{ paddingLeft: '0.5rem', ...btnStyle }}
|
58
|
-
disabled={pageCursor <= 0}
|
59
|
-
onClick={() => setPageCursor(pageCursor - 1)}
|
60
|
-
>
|
61
|
-
<img src={left} alt={i18n('goToPrevious')} style={{ width: 20 }} />
|
62
|
-
</button>
|
63
|
-
<strong style={{ color: 'white' }}>
|
64
|
-
{pageCursor + 1}/{pageNum}
|
65
|
-
</strong>
|
66
|
-
<button
|
67
|
-
style={{ paddingRight: '0.5rem', ...btnStyle }}
|
68
|
-
disabled={pageCursor + 1 >= pageNum}
|
69
|
-
onClick={() => setPageCursor(pageCursor + 1)}
|
70
|
-
>
|
71
|
-
<img src={right} alt={i18n('goToNext')} style={{ width: 20 }} />
|
72
|
-
</button>
|
73
|
-
<button
|
74
|
-
style={{ paddingRight: '0.5rem', ...btnStyle }}
|
75
|
-
disabled={pageCursor + 1 >= pageNum}
|
76
|
-
onClick={() => setPageCursor(pageNum - 1)}
|
77
|
-
>
|
78
|
-
<img src={doubleRight} alt={i18n('goToFirst')} style={{ width: 20 }} />
|
79
|
-
</button>
|
80
|
-
</div>
|
81
|
-
</div>
|
82
|
-
);
|
83
|
-
};
|
84
|
-
|
85
|
-
export default Pager;
|
@@ -1,87 +0,0 @@
|
|
1
|
-
import React, { useContext } from 'react';
|
2
|
-
import left from '../../../assets/icons/left.svg';
|
3
|
-
import right from '../../../assets/icons/right.svg';
|
4
|
-
import doubleLeft from '../../../assets/icons/double-left.svg';
|
5
|
-
import doubleRight from '../../../assets/icons/double-right.svg';
|
6
|
-
import { I18nContext } from '../../../contexts';
|
7
|
-
|
8
|
-
const buttonWrapStyle: React.CSSProperties = {
|
9
|
-
position: 'sticky',
|
10
|
-
top: '45%',
|
11
|
-
zIndex: 1,
|
12
|
-
backgroundColor: '#777777bd',
|
13
|
-
borderRadius: 2,
|
14
|
-
padding: '0.5rem',
|
15
|
-
display: 'flex',
|
16
|
-
alignItems: 'center',
|
17
|
-
width: 100,
|
18
|
-
};
|
19
|
-
|
20
|
-
const btnStyle: React.CSSProperties = {
|
21
|
-
cursor: 'pointer',
|
22
|
-
border: 'none',
|
23
|
-
background: 'none',
|
24
|
-
display: 'flex',
|
25
|
-
alignItems: 'center',
|
26
|
-
};
|
27
|
-
|
28
|
-
type Props = {
|
29
|
-
unitCursor: number;
|
30
|
-
unitNum: number;
|
31
|
-
setUnitCursor: (page: number) => void;
|
32
|
-
};
|
33
|
-
|
34
|
-
const UnitPager = ({ unitCursor, unitNum, setUnitCursor }: Props) => {
|
35
|
-
const i18n = useContext(I18nContext);
|
36
|
-
|
37
|
-
if (unitNum <= 1) return <></>;
|
38
|
-
|
39
|
-
return (
|
40
|
-
<>
|
41
|
-
{unitCursor > 0 && (
|
42
|
-
<div style={{ marginLeft: '1rem', ...buttonWrapStyle }}>
|
43
|
-
<button
|
44
|
-
style={{ paddingLeft: '0.5rem', ...btnStyle }}
|
45
|
-
disabled={unitCursor <= 0}
|
46
|
-
onClick={() => setUnitCursor(0)}
|
47
|
-
>
|
48
|
-
<img src={doubleLeft} alt={i18n('goToFirst')} style={{ width: 20 }} />
|
49
|
-
</button>
|
50
|
-
<button
|
51
|
-
style={{ paddingLeft: '0.5rem', ...btnStyle }}
|
52
|
-
disabled={unitCursor <= 0}
|
53
|
-
onClick={() => setUnitCursor(unitCursor - 1)}
|
54
|
-
>
|
55
|
-
<img src={left} alt={i18n('goToPrevious')} style={{ width: 20 }} />
|
56
|
-
</button>
|
57
|
-
<strong style={{ color: 'white' }}>
|
58
|
-
{unitCursor + 1}/{unitNum}
|
59
|
-
</strong>
|
60
|
-
</div>
|
61
|
-
)}
|
62
|
-
{unitCursor + 1 < unitNum && (
|
63
|
-
<div style={{ marginLeft: 'auto', marginRight: '1rem', ...buttonWrapStyle }}>
|
64
|
-
<strong style={{ color: 'white' }}>
|
65
|
-
{unitCursor + 1}/{unitNum}
|
66
|
-
</strong>
|
67
|
-
<button
|
68
|
-
style={{ paddingRight: '0.5rem', ...btnStyle }}
|
69
|
-
disabled={unitCursor + 1 >= unitNum}
|
70
|
-
onClick={() => setUnitCursor(unitCursor + 1)}
|
71
|
-
>
|
72
|
-
<img src={right} alt={i18n('goToNext')} style={{ width: 20 }} />
|
73
|
-
</button>
|
74
|
-
<button
|
75
|
-
style={{ paddingRight: '0.5rem', ...btnStyle }}
|
76
|
-
disabled={unitCursor + 1 >= unitNum}
|
77
|
-
onClick={() => setUnitCursor(unitNum - 1)}
|
78
|
-
>
|
79
|
-
<img src={doubleRight} alt={i18n('goToFirst')} style={{ width: 20 }} />
|
80
|
-
</button>
|
81
|
-
</div>
|
82
|
-
)}
|
83
|
-
</>
|
84
|
-
);
|
85
|
-
};
|
86
|
-
|
87
|
-
export default UnitPager;
|