@pdfme/ui 1.0.0-beta.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/.eslintrc.js +45 -0
- package/README.md +280 -0
- package/declaration.d.ts +8 -0
- package/dist/@pdfme/ui.js +3 -0
- package/dist/@pdfme/ui.js.LICENSE.txt +95 -0
- package/dist/@pdfme/ui.js.map +1 -0
- package/dist/types/common/src/barcode.d.ts +2 -0
- package/dist/types/common/src/constants.d.ts +6 -0
- package/dist/types/common/src/helper.d.ts +15 -0
- package/dist/types/common/src/index.d.ts +4 -0
- package/dist/types/common/src/schema.d.ts +3613 -0
- package/dist/types/common/src/type.d.ts +64 -0
- package/dist/types/common/src/utils.d.ts +12 -0
- package/dist/types/ui/src/Designer.d.ts +13 -0
- package/dist/types/ui/src/Form.d.ts +13 -0
- package/dist/types/ui/src/Viewer.d.ts +7 -0
- package/dist/types/ui/src/class.d.ts +72 -0
- package/dist/types/ui/src/components/Designer/Main/Guides.d.ts +9 -0
- package/dist/types/ui/src/components/Designer/Main/Mask.d.ts +3 -0
- package/dist/types/ui/src/components/Designer/Main/Moveable.d.ts +31 -0
- package/dist/types/ui/src/components/Designer/Main/Selecto.d.ts +8 -0
- package/dist/types/ui/src/components/Designer/Main/index.d.ts +24 -0
- package/dist/types/ui/src/components/Designer/Sidebar/DetailView/ExampleInputEditor.d.ts +3 -0
- package/dist/types/ui/src/components/Designer/Sidebar/DetailView/PositionAndSizeEditor.d.ts +3 -0
- package/dist/types/ui/src/components/Designer/Sidebar/DetailView/TextPropEditor.d.ts +3 -0
- package/dist/types/ui/src/components/Designer/Sidebar/DetailView/TypeAndKeyEditor.d.ts +3 -0
- package/dist/types/ui/src/components/Designer/Sidebar/DetailView/index.d.ts +3 -0
- package/dist/types/ui/src/components/Designer/Sidebar/ListView.d.ts +3 -0
- package/dist/types/ui/src/components/Designer/Sidebar/index.d.ts +26 -0
- package/dist/types/ui/src/components/Designer/index.d.ts +99 -0
- package/dist/types/ui/src/components/Divider.d.ts +2 -0
- package/dist/types/ui/src/components/Error.d.ts +7 -0
- package/dist/types/ui/src/components/Paper.d.ts +19 -0
- package/dist/types/ui/src/components/Preview/Pager/Page.d.ts +8 -0
- package/dist/types/ui/src/components/Preview/Pager/Unit.d.ts +8 -0
- package/dist/types/ui/src/components/Preview/index.d.ts +4 -0
- package/dist/types/ui/src/components/Root.d.ts +9 -0
- package/dist/types/ui/src/components/Schemas/BarcodeSchema.d.ts +15 -0
- package/dist/types/ui/src/components/Schemas/ImageSchema.d.ts +15 -0
- package/dist/types/ui/src/components/Schemas/SchemaUI.d.ts +14 -0
- package/dist/types/ui/src/components/Schemas/TextSchema.d.ts +22 -0
- package/dist/types/ui/src/components/Spinner.d.ts +2 -0
- package/dist/types/ui/src/constants.d.ts +5 -0
- package/dist/types/ui/src/contexts.d.ts +7 -0
- package/dist/types/ui/src/helper.d.ts +91 -0
- package/dist/types/ui/src/hooks.d.ts +26 -0
- package/dist/types/ui/src/i18n.d.ts +30 -0
- package/dist/types/ui/src/index.d.ts +5 -0
- package/dist/types/ui/src/libs/class.d.ts +84 -0
- package/dist/types/ui/src/libs/contexts.d.ts +7 -0
- package/dist/types/ui/src/libs/helper.d.ts +64 -0
- package/dist/types/ui/src/libs/hooks.d.ts +26 -0
- package/dist/types/ui/src/libs/i18n.d.ts +30 -0
- package/dist/types/ui/src/libs/ui.d.ts +64 -0
- package/package.json +80 -0
- package/public/Designer.html +90 -0
- package/public/Form.html +74 -0
- package/public/SauceHanSansJP.ttf +0 -0
- package/public/SauceHanSerifJP.ttf +0 -0
- package/public/Viewer.html +73 -0
- package/public/helper.js +51 -0
- package/public/index.html +54 -0
- package/src/Designer.tsx +72 -0
- package/src/Form.tsx +45 -0
- package/src/Viewer.tsx +27 -0
- package/src/assets/barcodeExamples/code128.png +0 -0
- package/src/assets/barcodeExamples/code39.png +0 -0
- package/src/assets/barcodeExamples/ean13.png +0 -0
- package/src/assets/barcodeExamples/ean8.png +0 -0
- package/src/assets/barcodeExamples/itf14.png +0 -0
- package/src/assets/barcodeExamples/japanpost.png +0 -0
- package/src/assets/barcodeExamples/nw7.png +0 -0
- package/src/assets/barcodeExamples/qrcode.png +0 -0
- package/src/assets/barcodeExamples/upca.png +0 -0
- package/src/assets/barcodeExamples/upce.png +0 -0
- package/src/assets/icons/back.svg +4 -0
- package/src/assets/icons/double-left.svg +11 -0
- package/src/assets/icons/double-right.svg +11 -0
- package/src/assets/icons/drag.svg +3 -0
- package/src/assets/icons/forward.svg +4 -0
- package/src/assets/icons/left.svg +4 -0
- package/src/assets/icons/right.svg +4 -0
- package/src/assets/icons/warning.svg +4 -0
- package/src/assets/imageExample.png +0 -0
- package/src/class.ts +147 -0
- package/src/components/Designer/Main/Guides.tsx +53 -0
- package/src/components/Designer/Main/Mask.tsx +19 -0
- package/src/components/Designer/Main/Moveable.tsx +79 -0
- package/src/components/Designer/Main/Selecto.tsx +29 -0
- package/src/components/Designer/Main/index.tsx +314 -0
- package/src/components/Designer/Sidebar/DetailView/ExampleInputEditor.tsx +62 -0
- package/src/components/Designer/Sidebar/DetailView/PositionAndSizeEditor.tsx +98 -0
- package/src/components/Designer/Sidebar/DetailView/TextPropEditor.tsx +178 -0
- package/src/components/Designer/Sidebar/DetailView/TypeAndKeyEditor.tsx +79 -0
- package/src/components/Designer/Sidebar/DetailView/index.tsx +39 -0
- package/src/components/Designer/Sidebar/ListView.tsx +180 -0
- package/src/components/Designer/Sidebar/index.tsx +102 -0
- package/src/components/Designer/index.tsx +283 -0
- package/src/components/Divider.tsx +7 -0
- package/src/components/Error.tsx +31 -0
- package/src/components/Paper.tsx +77 -0
- package/src/components/Preview/Pager/Page.tsx +85 -0
- package/src/components/Preview/Pager/Unit.tsx +87 -0
- package/src/components/Preview/index.tsx +102 -0
- package/src/components/Root.tsx +52 -0
- package/src/components/Schemas/BarcodeSchema.tsx +111 -0
- package/src/components/Schemas/ImageSchema.tsx +81 -0
- package/src/components/Schemas/SchemaUI.tsx +64 -0
- package/src/components/Schemas/TextSchema.tsx +62 -0
- package/src/components/Spinner.tsx +37 -0
- package/src/constants.ts +9 -0
- package/src/contexts.ts +8 -0
- package/src/helper.ts +516 -0
- package/src/hooks.ts +107 -0
- package/src/i18n.ts +64 -0
- package/src/index.ts +77 -0
- package/tsconfig.json +21 -0
- package/webpack.config.js +73 -0
@@ -0,0 +1,178 @@
|
|
1
|
+
import React, { useContext } from 'react';
|
2
|
+
import {
|
3
|
+
getFallbackFontName,
|
4
|
+
DEFAULT_FONT_SIZE,
|
5
|
+
DEFAULT_LINE_HEIGHT,
|
6
|
+
DEFAULT_CHARACTER_SPACING,
|
7
|
+
} from '@pdfme/common';
|
8
|
+
import { FontContext } from '../../../../contexts';
|
9
|
+
import { SidebarProps } from '..';
|
10
|
+
|
11
|
+
const NumberInputSet = (props: {
|
12
|
+
width: string;
|
13
|
+
label: string;
|
14
|
+
value: number;
|
15
|
+
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
16
|
+
}) => {
|
17
|
+
const { label, value, width, onChange } = props;
|
18
|
+
|
19
|
+
return (
|
20
|
+
<div style={{ width }}>
|
21
|
+
<label>{label}</label>
|
22
|
+
<input style={{ width: '100%' }} onChange={onChange} value={value} type="number" />
|
23
|
+
</div>
|
24
|
+
);
|
25
|
+
};
|
26
|
+
|
27
|
+
const ColorInputSet = (props: {
|
28
|
+
label: string;
|
29
|
+
value: string;
|
30
|
+
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
31
|
+
onClear: () => void;
|
32
|
+
}) => {
|
33
|
+
const { label, value, onChange, onClear } = props;
|
34
|
+
|
35
|
+
return (
|
36
|
+
<div style={{ width: '45%' }}>
|
37
|
+
<label>{label}</label>
|
38
|
+
<div style={{ display: 'flex' }}>
|
39
|
+
<input onChange={onChange} value={value} type="color" style={{ width: '100%' }} />
|
40
|
+
<button onClick={onClear}>X</button>
|
41
|
+
</div>
|
42
|
+
</div>
|
43
|
+
);
|
44
|
+
};
|
45
|
+
|
46
|
+
const SelectSet = (props: {
|
47
|
+
label: string;
|
48
|
+
value: string;
|
49
|
+
options: string[];
|
50
|
+
onChange: (e: React.ChangeEvent<HTMLSelectElement>) => void;
|
51
|
+
}) => {
|
52
|
+
const { label, value, options, onChange } = props;
|
53
|
+
|
54
|
+
return (
|
55
|
+
<div style={{ width: '45%' }}>
|
56
|
+
<label>{label}:</label>
|
57
|
+
<select style={{ width: '100%' }} onChange={onChange} value={value}>
|
58
|
+
{options.map((o) => (
|
59
|
+
<option key={o} value={o}>
|
60
|
+
{o}
|
61
|
+
</option>
|
62
|
+
))}
|
63
|
+
</select>
|
64
|
+
</div>
|
65
|
+
);
|
66
|
+
};
|
67
|
+
|
68
|
+
const TextPropEditor = (props: Pick<SidebarProps, 'changeSchemas' | 'activeSchema'>) => {
|
69
|
+
const { changeSchemas, activeSchema } = props;
|
70
|
+
const alignments = ['left', 'center', 'right'];
|
71
|
+
const font = useContext(FontContext);
|
72
|
+
const fallbackFontName = getFallbackFontName(font);
|
73
|
+
|
74
|
+
if (activeSchema.type !== 'text') return <></>;
|
75
|
+
|
76
|
+
return (
|
77
|
+
<div style={{ fontSize: '0.7rem' }}>
|
78
|
+
<div
|
79
|
+
style={{
|
80
|
+
display: 'flex',
|
81
|
+
alignItems: 'center',
|
82
|
+
justifyContent: 'space-between',
|
83
|
+
}}
|
84
|
+
>
|
85
|
+
<SelectSet
|
86
|
+
label={'FontName'}
|
87
|
+
value={activeSchema.fontName ?? fallbackFontName}
|
88
|
+
options={Object.keys(font)}
|
89
|
+
onChange={(e) => {
|
90
|
+
changeSchemas([{ key: 'fontName', value: e.target.value, schemaId: activeSchema.id }]);
|
91
|
+
}}
|
92
|
+
/>
|
93
|
+
|
94
|
+
<SelectSet
|
95
|
+
label={'Alignment'}
|
96
|
+
value={activeSchema.alignment ?? 'left'}
|
97
|
+
options={alignments}
|
98
|
+
onChange={(e) =>
|
99
|
+
changeSchemas([{ key: 'alignment', value: e.target.value, schemaId: activeSchema.id }])
|
100
|
+
}
|
101
|
+
/>
|
102
|
+
</div>
|
103
|
+
<div
|
104
|
+
style={{
|
105
|
+
display: 'flex',
|
106
|
+
alignItems: 'center',
|
107
|
+
justifyContent: 'space-between',
|
108
|
+
}}
|
109
|
+
>
|
110
|
+
<NumberInputSet
|
111
|
+
width="30%"
|
112
|
+
label={'FontSize(pt)'}
|
113
|
+
value={activeSchema.fontSize ?? DEFAULT_FONT_SIZE}
|
114
|
+
onChange={(e) =>
|
115
|
+
changeSchemas([
|
116
|
+
{ key: 'fontSize', value: Number(e.target.value), schemaId: activeSchema.id },
|
117
|
+
])
|
118
|
+
}
|
119
|
+
/>
|
120
|
+
<NumberInputSet
|
121
|
+
width="30%"
|
122
|
+
label={'LineHeight(em)'}
|
123
|
+
value={activeSchema.lineHeight ?? DEFAULT_LINE_HEIGHT}
|
124
|
+
onChange={(e) =>
|
125
|
+
changeSchemas([
|
126
|
+
{ key: 'lineHeight', value: Number(e.target.value), schemaId: activeSchema.id },
|
127
|
+
])
|
128
|
+
}
|
129
|
+
/>
|
130
|
+
|
131
|
+
<NumberInputSet
|
132
|
+
width="40%"
|
133
|
+
label={'CharacterSpacing(pt)'}
|
134
|
+
value={activeSchema.characterSpacing ?? DEFAULT_CHARACTER_SPACING}
|
135
|
+
onChange={(e) =>
|
136
|
+
changeSchemas([
|
137
|
+
{ key: 'characterSpacing', value: Number(e.target.value), schemaId: activeSchema.id },
|
138
|
+
])
|
139
|
+
}
|
140
|
+
/>
|
141
|
+
</div>
|
142
|
+
<div
|
143
|
+
style={{
|
144
|
+
marginBottom: '0.25rem',
|
145
|
+
display: 'flex',
|
146
|
+
alignItems: 'center',
|
147
|
+
justifyContent: 'space-between',
|
148
|
+
}}
|
149
|
+
>
|
150
|
+
<ColorInputSet
|
151
|
+
label={'FontColor'}
|
152
|
+
value={activeSchema.fontColor ?? '#000000'}
|
153
|
+
onChange={(e) =>
|
154
|
+
changeSchemas([{ key: 'fontColor', value: e.target.value, schemaId: activeSchema.id }])
|
155
|
+
}
|
156
|
+
onClear={() =>
|
157
|
+
changeSchemas([{ key: 'fontColor', value: '', schemaId: activeSchema.id }])
|
158
|
+
}
|
159
|
+
/>
|
160
|
+
|
161
|
+
<ColorInputSet
|
162
|
+
label={'Background'}
|
163
|
+
value={activeSchema.backgroundColor ?? '#ffffff'}
|
164
|
+
onChange={(e) =>
|
165
|
+
changeSchemas([
|
166
|
+
{ key: 'backgroundColor', value: e.target.value, schemaId: activeSchema.id },
|
167
|
+
])
|
168
|
+
}
|
169
|
+
onClear={() =>
|
170
|
+
changeSchemas([{ key: 'backgroundColor', value: '', schemaId: activeSchema.id }])
|
171
|
+
}
|
172
|
+
/>
|
173
|
+
</div>
|
174
|
+
</div>
|
175
|
+
);
|
176
|
+
};
|
177
|
+
|
178
|
+
export default TextPropEditor;
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import React, { useContext, useRef, useCallback } from 'react';
|
2
|
+
import { schemaTypes } from '@pdfme/common';
|
3
|
+
import { SidebarProps } from '..';
|
4
|
+
import { I18nContext } from '../../../../contexts';
|
5
|
+
|
6
|
+
const ErrorLabel = ({ isError, msg }: { isError: boolean; msg: string }) => (
|
7
|
+
<span
|
8
|
+
style={{ color: isError ? '#ffa19b' : 'inherit', fontWeight: isError ? 'bold' : 'inherit' }}
|
9
|
+
>
|
10
|
+
{msg}
|
11
|
+
</span>
|
12
|
+
);
|
13
|
+
|
14
|
+
const TypeAndKeyEditor = (
|
15
|
+
props: Pick<SidebarProps, 'schemas' | 'changeSchemas' | 'activeSchema'>
|
16
|
+
) => {
|
17
|
+
const { changeSchemas, activeSchema, schemas } = props;
|
18
|
+
const i18n = useContext(I18nContext);
|
19
|
+
|
20
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
21
|
+
|
22
|
+
const getHasSameKey = useCallback(() => {
|
23
|
+
const schemaKeys = schemas.map((s) => s.key);
|
24
|
+
const index = schemaKeys.indexOf(activeSchema.key);
|
25
|
+
if (index > -1) {
|
26
|
+
schemaKeys.splice(index, 1);
|
27
|
+
}
|
28
|
+
|
29
|
+
return schemaKeys.includes(activeSchema.key);
|
30
|
+
}, [schemas, activeSchema]);
|
31
|
+
|
32
|
+
const blankKey = !activeSchema.key;
|
33
|
+
const hasSameKey = getHasSameKey();
|
34
|
+
|
35
|
+
return (
|
36
|
+
<div style={{ display: 'flex', alignItems: 'center' }}>
|
37
|
+
<div>
|
38
|
+
<label style={{ marginBottom: 0 }}>{i18n('type')}</label>
|
39
|
+
<select
|
40
|
+
style={{ width: '100%' }}
|
41
|
+
onChange={(e) =>
|
42
|
+
changeSchemas([{ key: 'type', value: e.target.value, schemaId: activeSchema.id }])
|
43
|
+
}
|
44
|
+
value={activeSchema.type}
|
45
|
+
>
|
46
|
+
{schemaTypes.map((t) => (
|
47
|
+
<option key={t} value={t}>
|
48
|
+
{t}
|
49
|
+
</option>
|
50
|
+
))}
|
51
|
+
</select>
|
52
|
+
</div>
|
53
|
+
<div style={{ width: '100%' }}>
|
54
|
+
<label style={{ marginBottom: 0 }}>
|
55
|
+
{i18n('fieldName')}
|
56
|
+
<u style={{ fontSize: '0.7rem' }}>
|
57
|
+
(<ErrorLabel msg={i18n('require')} isError={blankKey} />+
|
58
|
+
<ErrorLabel msg={i18n('uniq')} isError={hasSameKey} />)
|
59
|
+
</u>
|
60
|
+
</label>
|
61
|
+
|
62
|
+
<input
|
63
|
+
ref={inputRef}
|
64
|
+
onChange={(e) =>
|
65
|
+
changeSchemas([{ key: 'key', value: e.target.value, schemaId: activeSchema.id }])
|
66
|
+
}
|
67
|
+
style={{
|
68
|
+
borderRadius: 2,
|
69
|
+
border: '1px solid #767676',
|
70
|
+
backgroundColor: hasSameKey || blankKey ? '#ffa19b' : '#fff',
|
71
|
+
}}
|
72
|
+
value={activeSchema.key}
|
73
|
+
/>
|
74
|
+
</div>
|
75
|
+
</div>
|
76
|
+
);
|
77
|
+
};
|
78
|
+
|
79
|
+
export default TypeAndKeyEditor;
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import React, { useContext } from 'react';
|
2
|
+
import { I18nContext } from '../../../../contexts';
|
3
|
+
import Divider from '../../../Divider';
|
4
|
+
import { SidebarProps } from '..';
|
5
|
+
import TextPropEditor from './TextPropEditor';
|
6
|
+
import ExampleInputEditor from './ExampleInputEditor';
|
7
|
+
import PositionAndSizeEditor from './PositionAndSizeEditor';
|
8
|
+
import TypeAndKeyEditor from './TypeAndKeyEditor';
|
9
|
+
|
10
|
+
const DetailView = (
|
11
|
+
props: Pick<SidebarProps, 'schemas' | 'pageSize' | 'changeSchemas' | 'activeSchema'>
|
12
|
+
) => {
|
13
|
+
const { activeSchema } = props;
|
14
|
+
const i18n = useContext(I18nContext);
|
15
|
+
|
16
|
+
return (
|
17
|
+
<aside>
|
18
|
+
<div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
|
19
|
+
<p style={{ textAlign: 'center', width: '100%', fontWeight: 'bold' }}>
|
20
|
+
{i18n('editField')}
|
21
|
+
</p>
|
22
|
+
</div>
|
23
|
+
<Divider />
|
24
|
+
<TypeAndKeyEditor {...props} />
|
25
|
+
<Divider />
|
26
|
+
<PositionAndSizeEditor {...props} />
|
27
|
+
<Divider />
|
28
|
+
{activeSchema.type === 'text' && (
|
29
|
+
<>
|
30
|
+
<TextPropEditor {...props} />
|
31
|
+
<Divider />
|
32
|
+
</>
|
33
|
+
)}
|
34
|
+
<ExampleInputEditor {...props} />
|
35
|
+
</aside>
|
36
|
+
);
|
37
|
+
};
|
38
|
+
|
39
|
+
export default DetailView;
|
@@ -0,0 +1,180 @@
|
|
1
|
+
import React, { useContext } from 'react';
|
2
|
+
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
|
3
|
+
import { SchemaForUI, Size } from '@pdfme/common';
|
4
|
+
import { ZOOM, RULER_HEIGHT } from '../../../constants';
|
5
|
+
import { I18nContext } from '../../../contexts';
|
6
|
+
import Divider from '../../Divider';
|
7
|
+
import dragIcon from '../../../assets/icons/drag.svg';
|
8
|
+
import warningIcon from '../../../assets/icons/warning.svg';
|
9
|
+
import { SidebarProps } from '.';
|
10
|
+
|
11
|
+
const isTouchable = () => true;
|
12
|
+
|
13
|
+
const DragHandle = SortableHandle(() => (
|
14
|
+
<button style={{ padding: 0, background: 'none', border: 'none', display: 'flex' }}>
|
15
|
+
<img style={{ cursor: 'grab' }} src={dragIcon} width={15} alt="Drag icon" />
|
16
|
+
</button>
|
17
|
+
));
|
18
|
+
|
19
|
+
const SortableItem = SortableElement(
|
20
|
+
(props: { schemas: SchemaForUI[]; schema: SchemaForUI; onEdit: (id: string) => void }) => {
|
21
|
+
const { schemas, schema, onEdit } = props;
|
22
|
+
const i18n = useContext(I18nContext);
|
23
|
+
|
24
|
+
const sc = schema;
|
25
|
+
let status: '' | 'is-warning' | 'is-danger' = '';
|
26
|
+
if (!sc.key) {
|
27
|
+
status = 'is-warning';
|
28
|
+
} else if (schemas.find((s) => sc.key && s.key === sc.key && s.id !== sc.id)) {
|
29
|
+
status = 'is-danger';
|
30
|
+
}
|
31
|
+
|
32
|
+
const touchable = isTouchable();
|
33
|
+
|
34
|
+
const getTitle = () => {
|
35
|
+
if (status === 'is-warning') {
|
36
|
+
return i18n('plsInputName');
|
37
|
+
}
|
38
|
+
if (status === 'is-danger') {
|
39
|
+
return i18n('fieldMustUniq');
|
40
|
+
}
|
41
|
+
|
42
|
+
return i18n('edit');
|
43
|
+
};
|
44
|
+
|
45
|
+
return (
|
46
|
+
<div
|
47
|
+
key={sc.id}
|
48
|
+
style={{
|
49
|
+
paddingLeft: 5,
|
50
|
+
display: 'flex',
|
51
|
+
alignItems: 'center',
|
52
|
+
justifyContent: 'space-between',
|
53
|
+
}}
|
54
|
+
>
|
55
|
+
<DragHandle />
|
56
|
+
<button
|
57
|
+
disabled={!touchable}
|
58
|
+
className={`${status}`}
|
59
|
+
style={{
|
60
|
+
padding: 5,
|
61
|
+
margin: 5,
|
62
|
+
width: '100%',
|
63
|
+
display: 'flex',
|
64
|
+
background: 'none',
|
65
|
+
border: 'none',
|
66
|
+
textAlign: 'left',
|
67
|
+
cursor: 'pointer',
|
68
|
+
}}
|
69
|
+
onClick={() => onEdit(sc.id)}
|
70
|
+
title={getTitle()}
|
71
|
+
>
|
72
|
+
<span
|
73
|
+
style={{
|
74
|
+
marginRight: '1rem',
|
75
|
+
width: 180,
|
76
|
+
overflow: 'hidden',
|
77
|
+
whiteSpace: 'nowrap',
|
78
|
+
textOverflow: 'ellipsis',
|
79
|
+
}}
|
80
|
+
>
|
81
|
+
{status === '' ? (
|
82
|
+
sc.key
|
83
|
+
) : (
|
84
|
+
<span style={{ display: 'flex', alignItems: 'center' }}>
|
85
|
+
<img
|
86
|
+
alt="Warning icon"
|
87
|
+
src={warningIcon}
|
88
|
+
width={15}
|
89
|
+
style={{ marginRight: '0.5rem' }}
|
90
|
+
/>
|
91
|
+
{status === 'is-warning' ? i18n('noKeyName') : sc.key}
|
92
|
+
{status === 'is-danger' ? i18n('notUniq') : ''}
|
93
|
+
</span>
|
94
|
+
)}
|
95
|
+
</span>
|
96
|
+
</button>
|
97
|
+
</div>
|
98
|
+
);
|
99
|
+
}
|
100
|
+
);
|
101
|
+
|
102
|
+
const SortableList = SortableContainer(
|
103
|
+
(props: {
|
104
|
+
schemas: SchemaForUI[];
|
105
|
+
onEdit: (id: string) => void;
|
106
|
+
size: Size;
|
107
|
+
hoveringSchemaId: string | null;
|
108
|
+
onChangeHoveringSchemaId: (id: string | null) => void;
|
109
|
+
}) => {
|
110
|
+
const { schemas, onEdit, size, hoveringSchemaId, onChangeHoveringSchemaId } = props;
|
111
|
+
const i18n = useContext(I18nContext);
|
112
|
+
|
113
|
+
return (
|
114
|
+
<div style={{ maxHeight: size.height - RULER_HEIGHT * ZOOM - 125, overflowY: 'auto' }}>
|
115
|
+
{schemas.length > 0 ? (
|
116
|
+
schemas.map((s, i) => (
|
117
|
+
<div
|
118
|
+
key={s.id}
|
119
|
+
style={{
|
120
|
+
border: `1px solid ${s.id === hoveringSchemaId ? '#18a0fb' : 'transparent'}`,
|
121
|
+
}}
|
122
|
+
onMouseEnter={() => onChangeHoveringSchemaId(s.id)}
|
123
|
+
onMouseLeave={() => onChangeHoveringSchemaId(null)}
|
124
|
+
>
|
125
|
+
<SortableItem
|
126
|
+
disabled={!isTouchable()}
|
127
|
+
index={i}
|
128
|
+
schemas={schemas}
|
129
|
+
schema={s}
|
130
|
+
onEdit={onEdit}
|
131
|
+
/>
|
132
|
+
</div>
|
133
|
+
))
|
134
|
+
) : (
|
135
|
+
<p style={{ textAlign: 'center' }}>{i18n('plsAddNewField')}</p>
|
136
|
+
)}
|
137
|
+
</div>
|
138
|
+
);
|
139
|
+
}
|
140
|
+
);
|
141
|
+
|
142
|
+
const ListView = (
|
143
|
+
props: Pick<
|
144
|
+
SidebarProps,
|
145
|
+
'schemas' | 'onSortEnd' | 'onEdit' | 'size' | 'hoveringSchemaId' | 'onChangeHoveringSchemaId'
|
146
|
+
>
|
147
|
+
) => {
|
148
|
+
const { schemas, onSortEnd, onEdit, size, hoveringSchemaId, onChangeHoveringSchemaId } = props;
|
149
|
+
const i18n = useContext(I18nContext);
|
150
|
+
|
151
|
+
return (
|
152
|
+
<aside>
|
153
|
+
<div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
|
154
|
+
<p style={{ textAlign: 'center', width: '100%', fontWeight: 'bold' }}>
|
155
|
+
{i18n('fieldsList')}
|
156
|
+
</p>
|
157
|
+
</div>
|
158
|
+
<Divider />
|
159
|
+
<SortableList
|
160
|
+
size={size}
|
161
|
+
hoveringSchemaId={hoveringSchemaId}
|
162
|
+
onChangeHoveringSchemaId={onChangeHoveringSchemaId}
|
163
|
+
updateBeforeSortStart={(node: any) => {
|
164
|
+
if (node.node.style) {
|
165
|
+
node.node.style.zIndex = '9999';
|
166
|
+
}
|
167
|
+
}}
|
168
|
+
useDragHandle
|
169
|
+
axis="y"
|
170
|
+
lockAxis="y"
|
171
|
+
schemas={schemas}
|
172
|
+
onSortEnd={onSortEnd}
|
173
|
+
onEdit={onEdit}
|
174
|
+
/>
|
175
|
+
<Divider />
|
176
|
+
</aside>
|
177
|
+
);
|
178
|
+
};
|
179
|
+
|
180
|
+
export default ListView;
|
@@ -0,0 +1,102 @@
|
|
1
|
+
import React, { useState, useContext } from 'react';
|
2
|
+
import { SchemaForUI, Size } from '@pdfme/common';
|
3
|
+
import { ZOOM, RULER_HEIGHT } from '../../../constants';
|
4
|
+
import { I18nContext } from '../../../contexts';
|
5
|
+
import backIcon from '../../../assets/icons/back.svg';
|
6
|
+
import forwardIcon from '../../../assets/icons/forward.svg';
|
7
|
+
import ListView from './ListView';
|
8
|
+
import DetailView from './DetailView';
|
9
|
+
|
10
|
+
export type SidebarProps = {
|
11
|
+
height: number;
|
12
|
+
hoveringSchemaId: string | null;
|
13
|
+
onChangeHoveringSchemaId: (id: string | null) => void;
|
14
|
+
size: Size;
|
15
|
+
pageSize: Size;
|
16
|
+
activeElement: HTMLElement | null;
|
17
|
+
activeSchema: SchemaForUI;
|
18
|
+
schemas: SchemaForUI[];
|
19
|
+
onSortEnd: ({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }) => void;
|
20
|
+
onEdit: (id: string) => void;
|
21
|
+
onEditEnd: () => void;
|
22
|
+
changeSchemas: (objs: { key: string; value: string | number; schemaId: string }[]) => void;
|
23
|
+
addSchema: () => void;
|
24
|
+
};
|
25
|
+
|
26
|
+
const Sidebar = (props: SidebarProps) => {
|
27
|
+
const { height, size, addSchema } = props;
|
28
|
+
|
29
|
+
const i18n = useContext(I18nContext);
|
30
|
+
const [open, setOpen] = useState(true);
|
31
|
+
const sidebarWidth = 300;
|
32
|
+
const top = 0;
|
33
|
+
|
34
|
+
return (
|
35
|
+
<div style={{ position: 'absolute', height, width: '100%' }}>
|
36
|
+
<div style={{ position: 'sticky', top, zIndex: 29 }}>
|
37
|
+
<button
|
38
|
+
style={{
|
39
|
+
position: 'absolute',
|
40
|
+
top: '1rem',
|
41
|
+
right: '0.5rem',
|
42
|
+
zIndex: 100,
|
43
|
+
border: 'none',
|
44
|
+
borderRadius: 3,
|
45
|
+
padding: '0.5rem',
|
46
|
+
cursor: 'pointer',
|
47
|
+
background: '#eee',
|
48
|
+
}}
|
49
|
+
onClick={() => setOpen(!open)}
|
50
|
+
>
|
51
|
+
<img src={open ? forwardIcon : backIcon} width={15} alt="Toggle icon" />
|
52
|
+
</button>
|
53
|
+
<div
|
54
|
+
style={{
|
55
|
+
width: sidebarWidth,
|
56
|
+
height: size.height - RULER_HEIGHT * ZOOM,
|
57
|
+
display: open ? 'block' : 'none',
|
58
|
+
top,
|
59
|
+
right: 0,
|
60
|
+
position: 'absolute',
|
61
|
+
background: '#ffffffed',
|
62
|
+
color: '#333',
|
63
|
+
border: '1px solid #eee',
|
64
|
+
padding: '0.5rem',
|
65
|
+
overflowY: 'auto',
|
66
|
+
fontFamily: "'Open Sans', sans-serif",
|
67
|
+
fontWeight: 400,
|
68
|
+
}}
|
69
|
+
>
|
70
|
+
{props.activeElement ? <DetailView {...props} /> : <ListView {...props} />}
|
71
|
+
<div
|
72
|
+
style={{
|
73
|
+
display: 'flex',
|
74
|
+
justifyContent: 'space-around',
|
75
|
+
position: 'absolute',
|
76
|
+
width: '100%',
|
77
|
+
left: 0,
|
78
|
+
bottom: '1rem',
|
79
|
+
paddingTop: '1rem',
|
80
|
+
}}
|
81
|
+
>
|
82
|
+
<button
|
83
|
+
style={{
|
84
|
+
padding: '0.5rem',
|
85
|
+
color: '#fff',
|
86
|
+
background: '#18a0fb',
|
87
|
+
border: 'none',
|
88
|
+
borderRadius: 3,
|
89
|
+
cursor: 'pointer',
|
90
|
+
}}
|
91
|
+
onClick={addSchema}
|
92
|
+
>
|
93
|
+
<strong>{i18n('addNewField')}</strong>
|
94
|
+
</button>
|
95
|
+
</div>
|
96
|
+
</div>
|
97
|
+
</div>
|
98
|
+
</div>
|
99
|
+
);
|
100
|
+
};
|
101
|
+
|
102
|
+
export default Sidebar;
|