@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.
Files changed (118) hide show
  1. package/.eslintrc.js +45 -0
  2. package/README.md +280 -0
  3. package/declaration.d.ts +8 -0
  4. package/dist/@pdfme/ui.js +3 -0
  5. package/dist/@pdfme/ui.js.LICENSE.txt +95 -0
  6. package/dist/@pdfme/ui.js.map +1 -0
  7. package/dist/types/common/src/barcode.d.ts +2 -0
  8. package/dist/types/common/src/constants.d.ts +6 -0
  9. package/dist/types/common/src/helper.d.ts +15 -0
  10. package/dist/types/common/src/index.d.ts +4 -0
  11. package/dist/types/common/src/schema.d.ts +3613 -0
  12. package/dist/types/common/src/type.d.ts +64 -0
  13. package/dist/types/common/src/utils.d.ts +12 -0
  14. package/dist/types/ui/src/Designer.d.ts +13 -0
  15. package/dist/types/ui/src/Form.d.ts +13 -0
  16. package/dist/types/ui/src/Viewer.d.ts +7 -0
  17. package/dist/types/ui/src/class.d.ts +72 -0
  18. package/dist/types/ui/src/components/Designer/Main/Guides.d.ts +9 -0
  19. package/dist/types/ui/src/components/Designer/Main/Mask.d.ts +3 -0
  20. package/dist/types/ui/src/components/Designer/Main/Moveable.d.ts +31 -0
  21. package/dist/types/ui/src/components/Designer/Main/Selecto.d.ts +8 -0
  22. package/dist/types/ui/src/components/Designer/Main/index.d.ts +24 -0
  23. package/dist/types/ui/src/components/Designer/Sidebar/DetailView/ExampleInputEditor.d.ts +3 -0
  24. package/dist/types/ui/src/components/Designer/Sidebar/DetailView/PositionAndSizeEditor.d.ts +3 -0
  25. package/dist/types/ui/src/components/Designer/Sidebar/DetailView/TextPropEditor.d.ts +3 -0
  26. package/dist/types/ui/src/components/Designer/Sidebar/DetailView/TypeAndKeyEditor.d.ts +3 -0
  27. package/dist/types/ui/src/components/Designer/Sidebar/DetailView/index.d.ts +3 -0
  28. package/dist/types/ui/src/components/Designer/Sidebar/ListView.d.ts +3 -0
  29. package/dist/types/ui/src/components/Designer/Sidebar/index.d.ts +26 -0
  30. package/dist/types/ui/src/components/Designer/index.d.ts +99 -0
  31. package/dist/types/ui/src/components/Divider.d.ts +2 -0
  32. package/dist/types/ui/src/components/Error.d.ts +7 -0
  33. package/dist/types/ui/src/components/Paper.d.ts +19 -0
  34. package/dist/types/ui/src/components/Preview/Pager/Page.d.ts +8 -0
  35. package/dist/types/ui/src/components/Preview/Pager/Unit.d.ts +8 -0
  36. package/dist/types/ui/src/components/Preview/index.d.ts +4 -0
  37. package/dist/types/ui/src/components/Root.d.ts +9 -0
  38. package/dist/types/ui/src/components/Schemas/BarcodeSchema.d.ts +15 -0
  39. package/dist/types/ui/src/components/Schemas/ImageSchema.d.ts +15 -0
  40. package/dist/types/ui/src/components/Schemas/SchemaUI.d.ts +14 -0
  41. package/dist/types/ui/src/components/Schemas/TextSchema.d.ts +22 -0
  42. package/dist/types/ui/src/components/Spinner.d.ts +2 -0
  43. package/dist/types/ui/src/constants.d.ts +5 -0
  44. package/dist/types/ui/src/contexts.d.ts +7 -0
  45. package/dist/types/ui/src/helper.d.ts +91 -0
  46. package/dist/types/ui/src/hooks.d.ts +26 -0
  47. package/dist/types/ui/src/i18n.d.ts +30 -0
  48. package/dist/types/ui/src/index.d.ts +5 -0
  49. package/dist/types/ui/src/libs/class.d.ts +84 -0
  50. package/dist/types/ui/src/libs/contexts.d.ts +7 -0
  51. package/dist/types/ui/src/libs/helper.d.ts +64 -0
  52. package/dist/types/ui/src/libs/hooks.d.ts +26 -0
  53. package/dist/types/ui/src/libs/i18n.d.ts +30 -0
  54. package/dist/types/ui/src/libs/ui.d.ts +64 -0
  55. package/package.json +80 -0
  56. package/public/Designer.html +90 -0
  57. package/public/Form.html +74 -0
  58. package/public/SauceHanSansJP.ttf +0 -0
  59. package/public/SauceHanSerifJP.ttf +0 -0
  60. package/public/Viewer.html +73 -0
  61. package/public/helper.js +51 -0
  62. package/public/index.html +54 -0
  63. package/src/Designer.tsx +72 -0
  64. package/src/Form.tsx +45 -0
  65. package/src/Viewer.tsx +27 -0
  66. package/src/assets/barcodeExamples/code128.png +0 -0
  67. package/src/assets/barcodeExamples/code39.png +0 -0
  68. package/src/assets/barcodeExamples/ean13.png +0 -0
  69. package/src/assets/barcodeExamples/ean8.png +0 -0
  70. package/src/assets/barcodeExamples/itf14.png +0 -0
  71. package/src/assets/barcodeExamples/japanpost.png +0 -0
  72. package/src/assets/barcodeExamples/nw7.png +0 -0
  73. package/src/assets/barcodeExamples/qrcode.png +0 -0
  74. package/src/assets/barcodeExamples/upca.png +0 -0
  75. package/src/assets/barcodeExamples/upce.png +0 -0
  76. package/src/assets/icons/back.svg +4 -0
  77. package/src/assets/icons/double-left.svg +11 -0
  78. package/src/assets/icons/double-right.svg +11 -0
  79. package/src/assets/icons/drag.svg +3 -0
  80. package/src/assets/icons/forward.svg +4 -0
  81. package/src/assets/icons/left.svg +4 -0
  82. package/src/assets/icons/right.svg +4 -0
  83. package/src/assets/icons/warning.svg +4 -0
  84. package/src/assets/imageExample.png +0 -0
  85. package/src/class.ts +147 -0
  86. package/src/components/Designer/Main/Guides.tsx +53 -0
  87. package/src/components/Designer/Main/Mask.tsx +19 -0
  88. package/src/components/Designer/Main/Moveable.tsx +79 -0
  89. package/src/components/Designer/Main/Selecto.tsx +29 -0
  90. package/src/components/Designer/Main/index.tsx +314 -0
  91. package/src/components/Designer/Sidebar/DetailView/ExampleInputEditor.tsx +62 -0
  92. package/src/components/Designer/Sidebar/DetailView/PositionAndSizeEditor.tsx +98 -0
  93. package/src/components/Designer/Sidebar/DetailView/TextPropEditor.tsx +178 -0
  94. package/src/components/Designer/Sidebar/DetailView/TypeAndKeyEditor.tsx +79 -0
  95. package/src/components/Designer/Sidebar/DetailView/index.tsx +39 -0
  96. package/src/components/Designer/Sidebar/ListView.tsx +180 -0
  97. package/src/components/Designer/Sidebar/index.tsx +102 -0
  98. package/src/components/Designer/index.tsx +283 -0
  99. package/src/components/Divider.tsx +7 -0
  100. package/src/components/Error.tsx +31 -0
  101. package/src/components/Paper.tsx +77 -0
  102. package/src/components/Preview/Pager/Page.tsx +85 -0
  103. package/src/components/Preview/Pager/Unit.tsx +87 -0
  104. package/src/components/Preview/index.tsx +102 -0
  105. package/src/components/Root.tsx +52 -0
  106. package/src/components/Schemas/BarcodeSchema.tsx +111 -0
  107. package/src/components/Schemas/ImageSchema.tsx +81 -0
  108. package/src/components/Schemas/SchemaUI.tsx +64 -0
  109. package/src/components/Schemas/TextSchema.tsx +62 -0
  110. package/src/components/Spinner.tsx +37 -0
  111. package/src/constants.ts +9 -0
  112. package/src/contexts.ts +8 -0
  113. package/src/helper.ts +516 -0
  114. package/src/hooks.ts +107 -0
  115. package/src/i18n.ts +64 -0
  116. package/src/index.ts +77 -0
  117. package/tsconfig.json +21 -0
  118. 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;