@pdfme/ui 1.0.0-beta.5 → 1.0.0-beta.9

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 (102) hide show
  1. package/coverage/clover.xml +6 -0
  2. package/coverage/coverage-final.json +1 -0
  3. package/coverage/lcov-report/base.css +224 -0
  4. package/coverage/lcov-report/block-navigation.js +87 -0
  5. package/coverage/lcov-report/favicon.png +0 -0
  6. package/coverage/lcov-report/index.html +101 -0
  7. package/coverage/lcov-report/prettify.css +1 -0
  8. package/coverage/lcov-report/prettify.js +2 -0
  9. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  10. package/coverage/lcov-report/sorter.js +196 -0
  11. package/coverage/lcov.info +0 -0
  12. package/dist/index.js +1 -1
  13. package/dist/index.js.LICENSE.txt +3 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/types/{ui/src/Designer.d.ts → Designer.d.ts} +0 -0
  16. package/dist/types/{ui/src/Form.d.ts → Form.d.ts} +0 -0
  17. package/dist/types/{ui/src/Viewer.d.ts → Viewer.d.ts} +0 -0
  18. package/dist/types/{ui/src/class.d.ts → class.d.ts} +1 -1
  19. package/dist/types/{ui/src/components → components}/Designer/Main/Guides.d.ts +0 -0
  20. package/dist/types/{ui/src/components → components}/Designer/Main/Mask.d.ts +0 -0
  21. package/dist/types/{ui/src/components → components}/Designer/Main/Moveable.d.ts +1 -1
  22. package/dist/types/{ui/src/components → components}/Designer/Main/Selecto.d.ts +0 -0
  23. package/dist/types/{ui/src/components → components}/Designer/Main/index.d.ts +0 -0
  24. package/dist/types/{ui/src/components → components}/Designer/Sidebar/DetailView/ExampleInputEditor.d.ts +4 -1
  25. package/dist/types/components/Designer/Sidebar/DetailView/PositionAndSizeEditor.d.ts +6 -0
  26. package/dist/types/{ui/src/components → components}/Designer/Sidebar/DetailView/TextPropEditor.d.ts +4 -1
  27. package/dist/types/{ui/src/components → components}/Designer/Sidebar/DetailView/TypeAndKeyEditor.d.ts +4 -1
  28. package/dist/types/components/Designer/Sidebar/DetailView/index.d.ts +6 -0
  29. package/dist/types/components/Designer/Sidebar/ListView/Item.d.ts +25 -0
  30. package/dist/types/components/Designer/Sidebar/ListView/SelectableSortableContainer.d.ts +3 -0
  31. package/dist/types/components/Designer/Sidebar/ListView/SelectableSortableItem.d.ts +14 -0
  32. package/dist/types/{ui/src/components/Designer/Sidebar/ListView.d.ts → components/Designer/Sidebar/ListView/index.d.ts} +2 -2
  33. package/dist/types/{ui/src/components → components}/Designer/Sidebar/index.d.ts +2 -7
  34. package/dist/types/{ui/src/components → components}/Designer/index.d.ts +0 -1
  35. package/dist/types/{ui/src/components → components}/Divider.d.ts +0 -0
  36. package/dist/types/{ui/src/components → components}/Error.d.ts +0 -1
  37. package/dist/types/{ui/src/components → components}/Paper.d.ts +0 -0
  38. package/dist/types/{ui/src/components → components}/Preview/Pager/Page.d.ts +0 -1
  39. package/dist/types/{ui/src/components → components}/Preview/Pager/Unit.d.ts +0 -1
  40. package/dist/types/{ui/src/components → components}/Preview/index.d.ts +0 -1
  41. package/dist/types/{ui/src/components → components}/Root.d.ts +0 -0
  42. package/dist/types/{ui/src/components → components}/Schemas/BarcodeSchema.d.ts +0 -0
  43. package/dist/types/{ui/src/components → components}/Schemas/ImageSchema.d.ts +0 -0
  44. package/dist/types/{ui/src/components → components}/Schemas/SchemaUI.d.ts +0 -0
  45. package/dist/types/{ui/src/components → components}/Schemas/TextSchema.d.ts +0 -0
  46. package/dist/types/{ui/src/components → components}/Spinner.d.ts +0 -0
  47. package/dist/types/{ui/src/constants.d.ts → constants.d.ts} +1 -0
  48. package/dist/types/{ui/src/contexts.d.ts → contexts.d.ts} +1 -1
  49. package/dist/types/{ui/src/helper.d.ts → helper.d.ts} +1 -1
  50. package/dist/types/{ui/src/hooks.d.ts → hooks.d.ts} +1 -0
  51. package/dist/types/{ui/src/i18n.d.ts → i18n.d.ts} +4 -2
  52. package/dist/types/{ui/src/index.d.ts → index.d.ts} +0 -0
  53. package/package.json +13 -11
  54. package/src/Designer.tsx +2 -1
  55. package/src/Form.tsx +1 -0
  56. package/src/Viewer.tsx +1 -0
  57. package/src/assets/icons/align-horizontal-center.svg +1 -0
  58. package/src/assets/icons/align-horizontal-left.svg +1 -0
  59. package/src/assets/icons/align-horizontal-right.svg +1 -0
  60. package/src/assets/icons/align-vertical-bottom.svg +1 -0
  61. package/src/assets/icons/align-vertical-middle.svg +1 -0
  62. package/src/assets/icons/align-vertical-top.svg +1 -0
  63. package/src/assets/icons/close.svg +4 -0
  64. package/src/assets/icons/horizontal-distribute.svg +1 -0
  65. package/src/assets/icons/vertical-distribute.svg +1 -0
  66. package/src/assets/imageExample.png +0 -0
  67. package/src/class.ts +5 -6
  68. package/src/components/Designer/Main/Moveable.tsx +1 -1
  69. package/src/components/Designer/Main/index.tsx +21 -15
  70. package/src/components/Designer/Sidebar/DetailView/ExampleInputEditor.tsx +28 -6
  71. package/src/components/Designer/Sidebar/DetailView/PositionAndSizeEditor.tsx +115 -24
  72. package/src/components/Designer/Sidebar/DetailView/TextPropEditor.tsx +36 -6
  73. package/src/components/Designer/Sidebar/DetailView/TypeAndKeyEditor.tsx +14 -6
  74. package/src/components/Designer/Sidebar/DetailView/index.tsx +19 -14
  75. package/src/components/Designer/Sidebar/ListView/Item.tsx +113 -0
  76. package/src/components/Designer/Sidebar/ListView/SelectableSortableContainer.tsx +162 -0
  77. package/src/components/Designer/Sidebar/ListView/SelectableSortableItem.tsx +78 -0
  78. package/src/components/Designer/Sidebar/ListView/index.tsx +118 -0
  79. package/src/components/Designer/Sidebar/index.tsx +26 -12
  80. package/src/components/Designer/index.tsx +12 -24
  81. package/src/components/Paper.tsx +1 -3
  82. package/src/components/Preview/Pager/Page.tsx +1 -1
  83. package/src/components/Preview/Pager/Unit.tsx +1 -1
  84. package/src/components/Preview/index.tsx +3 -4
  85. package/src/components/Root.tsx +2 -7
  86. package/src/components/Schemas/BarcodeSchema.tsx +37 -22
  87. package/src/components/Schemas/ImageSchema.tsx +71 -66
  88. package/src/components/Schemas/TextSchema.tsx +1 -1
  89. package/src/constants.ts +2 -0
  90. package/src/helper.ts +42 -37
  91. package/src/hooks.ts +11 -0
  92. package/src/i18n.ts +10 -7
  93. package/tsconfig.json +1 -1
  94. package/webpack.config.js +0 -18
  95. package/dist/types/common/src/constants.d.ts +0 -6
  96. package/dist/types/common/src/helper.d.ts +0 -15
  97. package/dist/types/common/src/index.d.ts +0 -6
  98. package/dist/types/common/src/schema.d.ts +0 -3613
  99. package/dist/types/common/src/type.d.ts +0 -64
  100. package/dist/types/ui/src/components/Designer/Sidebar/DetailView/PositionAndSizeEditor.d.ts +0 -3
  101. package/dist/types/ui/src/components/Designer/Sidebar/DetailView/index.d.ts +0 -3
  102. package/src/components/Designer/Sidebar/ListView.tsx +0 -180
@@ -1,33 +1,52 @@
1
1
  import React, { useContext } from 'react';
2
+ import { SchemaForUI } from '@pdfme/common';
2
3
  import { readFiles } from '../../../../helper';
3
4
  import { I18nContext } from '../../../../contexts';
4
5
  import { SidebarProps } from '..';
6
+ import closeIcon from '../../../../assets/icons/close.svg';
5
7
 
6
- const ExampleInputEditor = (props: Pick<SidebarProps, 'changeSchemas' | 'activeSchema'>) => {
8
+ const ExampleInputEditor = (
9
+ props: Pick<SidebarProps, 'changeSchemas'> & { activeSchema: SchemaForUI }
10
+ ) => {
7
11
  const { changeSchemas, activeSchema } = props;
8
12
  const i18n = useContext(I18nContext);
9
13
 
10
14
  return (
11
15
  <div>
12
- <label style={{ marginBottom: 0 }}>{i18n('inputExample')}</label>
16
+ <label>{i18n('inputExample')}</label>
13
17
  {activeSchema.type === 'image' ? (
14
- <div style={{ position: 'relative', textAlign: 'center' }}>
18
+ <div style={{ position: 'relative' }}>
15
19
  {activeSchema.data ? (
16
20
  <div style={{ margin: '0 auto' }}>
17
21
  <button
18
- style={{ position: 'absolute', top: 0, left: 0 }}
22
+ style={{
23
+ position: 'absolute',
24
+ top: 0,
25
+ left: 0,
26
+ display: 'flex',
27
+ justifyContent: 'center',
28
+ alignItems: 'center',
29
+ color: '#333',
30
+ background: '#f2f2f2',
31
+ cursor: 'pointer',
32
+ borderRadius: 2,
33
+ border: '1px solid #767676',
34
+ height: 20,
35
+ width: 20,
36
+ }}
19
37
  aria-label="close"
20
38
  onClick={() =>
21
39
  changeSchemas([{ key: 'data', value: '', schemaId: activeSchema.id }])
22
40
  }
23
41
  >
24
- x
42
+ <img src={closeIcon} alt="Close icon" width={10} />
25
43
  </button>
26
44
  <img style={{ maxHeight: 180 }} src={activeSchema.data} alt="Input Example" />
27
45
  </div>
28
46
  ) : (
29
47
  <label>
30
48
  <input
49
+ style={{ color: '#333', background: 'none' }}
31
50
  onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
32
51
  const { files } = e.target;
33
52
  readFiles(files, 'dataURL').then((result) => {
@@ -50,7 +69,10 @@ const ExampleInputEditor = (props: Pick<SidebarProps, 'changeSchemas' | 'activeS
50
69
  }
51
70
  style={{
52
71
  width: '100%',
53
- backgroundColor: activeSchema.data ? '#fff' : '#ffa19b',
72
+ border: '1px solid #767676',
73
+ borderRadius: 2,
74
+ color: '#333',
75
+ background: activeSchema.data ? 'none' : '#ffa19b',
54
76
  }}
55
77
  value={activeSchema.data}
56
78
  />
@@ -1,30 +1,128 @@
1
- import React from 'react';
1
+ import React, { CSSProperties } from 'react';
2
+ import { SchemaForUI } from '@pdfme/common';
3
+ import { round } from '../../../../helper';
2
4
  import { SidebarProps } from '..';
5
+ import alignVerticalTop from '../../../../assets/icons/align-vertical-top.svg';
6
+ import alignVerticalMiddle from '../../../../assets/icons/align-vertical-middle.svg';
7
+ import alignVerticalBottom from '../../../../assets/icons/align-vertical-bottom.svg';
8
+ import alignHorizontalRight from '../../../../assets/icons/align-horizontal-right.svg';
9
+ import alignHorizontalLeft from '../../../../assets/icons/align-horizontal-left.svg';
10
+ import alignHorizontalCenter from '../../../../assets/icons/align-horizontal-center.svg';
11
+ import verticalDistribute from '../../../../assets/icons/vertical-distribute.svg';
12
+ import horizontalDistribute from '../../../../assets/icons/horizontal-distribute.svg';
3
13
 
4
- const inputSetStyle: React.CSSProperties = {
5
- marginRight: '1rem',
14
+ const inputSetStyle: CSSProperties = { marginRight: '1rem', display: 'flex', alignItems: 'center' };
15
+
16
+ const inputStyle: CSSProperties = {
17
+ width: 70,
18
+ border: '1px solid #767676',
19
+ borderRadius: 2,
20
+ color: '#333',
21
+ background: 'none',
22
+ };
23
+
24
+ const buttonStyle: CSSProperties = {
6
25
  display: 'flex',
26
+ background: 'none',
7
27
  alignItems: 'center',
28
+ borderRadius: 2,
29
+ border: '1px solid rgb(118, 118, 118)',
30
+ cursor: 'pointer',
8
31
  };
9
32
 
10
33
  const PositionAndSizeEditor = (
11
- props: Pick<SidebarProps, 'pageSize' | 'changeSchemas' | 'activeSchema'>
34
+ props: Pick<SidebarProps, 'pageSize' | 'schemas' | 'changeSchemas' | 'activeElements'> & {
35
+ activeSchema: SchemaForUI;
36
+ }
12
37
  ) => {
13
- const { changeSchemas, activeSchema, pageSize } = props;
38
+ const { changeSchemas, schemas, activeSchema, activeElements, pageSize } = props;
39
+
40
+ const align = (type: 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom') => {
41
+ const ids = activeElements.map((ae) => ae.id);
42
+ const ass = schemas.filter((s) => ids.includes(s.id));
43
+
44
+ const isVertical = ['left', 'center', 'right'].includes(type);
45
+ const tgtPos = isVertical ? 'x' : 'y';
46
+ const tgtSize = isVertical ? 'width' : 'height';
47
+ const isSingle = ass.length === 1;
48
+ const root = pageSize[tgtSize];
49
+
50
+ const min = isSingle ? 0 : Math.min(...ass.map((as) => as.position[tgtPos]));
51
+ const max = isSingle ? root : Math.max(...ass.map((as) => as.position[tgtPos] + as[tgtSize]));
52
+
53
+ let basePos = min;
54
+ let adjust = (_: number) => 0;
55
+
56
+ if (['center', 'middle'].includes(type)) {
57
+ basePos = (min + max) / 2;
58
+ adjust = (num: number) => num / 2;
59
+ } else if (['right', 'bottom'].includes(type)) {
60
+ basePos = max;
61
+ adjust = (num: number) => num;
62
+ }
63
+
64
+ changeSchemas(
65
+ ass.map((as) => ({
66
+ key: `position.${tgtPos}`,
67
+ value: round(basePos - adjust(as[tgtSize]), 2),
68
+ schemaId: as.id,
69
+ }))
70
+ );
71
+ };
72
+
73
+ const distribute = (type: 'vertical' | 'horizontal') => {
74
+ const ids = activeElements.map((ae) => ae.id);
75
+ const ass = schemas.filter((s) => ids.includes(s.id));
76
+
77
+ const isVertical = type === 'vertical';
78
+ const tgtPos = isVertical ? 'y' : 'x';
79
+ const tgtSize = isVertical ? 'height' : 'width';
80
+ const min = Math.min(...ass.map((as) => as.position[tgtPos]));
81
+ const max = Math.max(...ass.map((as) => as.position[tgtPos] + as[tgtSize]));
82
+
83
+ if (ass.length < 3) return;
84
+
85
+ const boxPos = min;
86
+ const boxSize = max - min;
87
+ const sum = ass.reduce((acc, cur) => acc + cur[tgtSize], 0);
88
+ const remain = boxSize - sum;
89
+ const unit = remain / (ass.length - 1);
90
+
91
+ let prev = 0;
92
+ changeSchemas(
93
+ ass.map((as, index) => {
94
+ prev += index === 0 ? 0 : ass[index - 1][tgtSize] + unit;
95
+ const value = round(boxPos + prev, 2);
96
+ return { key: `position.${tgtPos}`, value, schemaId: as.id };
97
+ })
98
+ );
99
+ };
100
+
101
+ const layoutBtns: { id: string; icon: any; action: () => void }[] = [
102
+ { id: 'left', icon: alignHorizontalLeft, action: () => align('left') },
103
+ { id: 'center', icon: alignHorizontalCenter, action: () => align('center') },
104
+ { id: 'right', icon: alignHorizontalRight, action: () => align('right') },
105
+ { id: 'top', icon: alignVerticalTop, action: () => align('top') },
106
+ { id: 'middle', icon: alignVerticalMiddle, action: () => align('middle') },
107
+ { id: 'bottom', icon: alignVerticalBottom, action: () => align('bottom') },
108
+ { id: 'vertical', icon: verticalDistribute, action: () => distribute('vertical') },
109
+ { id: 'horizontal', icon: horizontalDistribute, action: () => distribute('horizontal') },
110
+ ];
14
111
 
15
112
  return (
16
113
  <div>
17
- <div
18
- style={{
19
- display: 'flex',
20
- alignItems: 'center',
21
- justifyContent: 'space-between',
22
- }}
23
- >
114
+ <div style={{ display: 'flex', alignItems: 'center', marginBottom: '0.5rem' }}>
115
+ {layoutBtns.map((b) => (
116
+ <button key={b.id} title={b.id} onClick={b.action} style={buttonStyle}>
117
+ <img width={15} src={b.icon} />
118
+ </button>
119
+ ))}
120
+ </div>
121
+ <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
24
122
  <div style={inputSetStyle}>
25
123
  <label style={{ width: 17 }}>X</label>
26
124
  <input
27
- style={{ width: 70 }}
125
+ style={inputStyle}
28
126
  type="number"
29
127
  onChange={(e) => {
30
128
  const value = Number(e.target.value);
@@ -39,7 +137,7 @@ const PositionAndSizeEditor = (
39
137
  <div style={inputSetStyle}>
40
138
  <label style={{ width: 17 }}>Y</label>
41
139
  <input
42
- style={{ width: 70 }}
140
+ style={inputStyle}
43
141
  type="number"
44
142
  onChange={(e) => {
45
143
  const value = Number(e.target.value);
@@ -52,18 +150,11 @@ const PositionAndSizeEditor = (
52
150
  <span style={{ fontSize: '0.6rem' }}>mm</span>
53
151
  </div>
54
152
  </div>
55
- <div
56
- style={{
57
- display: 'flex',
58
- alignItems: 'center',
59
- justifyContent: 'space-between',
60
- marginTop: '0.25rem',
61
- }}
62
- >
153
+ <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
63
154
  <div style={inputSetStyle}>
64
155
  <label style={{ width: 17 }}>W</label>
65
156
  <input
66
- style={{ width: 70 }}
157
+ style={inputStyle}
67
158
  type="number"
68
159
  onChange={(e) => {
69
160
  const value = Number(e.target.value);
@@ -78,7 +169,7 @@ const PositionAndSizeEditor = (
78
169
  <div style={inputSetStyle}>
79
170
  <label style={{ width: 17 }}>H</label>
80
171
  <input
81
- style={{ width: 70 }}
172
+ style={inputStyle}
82
173
  type="number"
83
174
  onChange={(e) => {
84
175
  const value = Number(e.target.value);
@@ -1,12 +1,24 @@
1
1
  import React, { useContext } from 'react';
2
2
  import {
3
+ SchemaForUI,
3
4
  getFallbackFontName,
4
5
  DEFAULT_FONT_SIZE,
5
6
  DEFAULT_LINE_HEIGHT,
6
7
  DEFAULT_CHARACTER_SPACING,
8
+ DEFAULT_FONT_COLOR,
7
9
  } from '@pdfme/common';
8
10
  import { FontContext } from '../../../../contexts';
9
11
  import { SidebarProps } from '..';
12
+ import closeIcon from '../../../../assets/icons/close.svg';
13
+
14
+ const inputStyle = {
15
+ width: '90%',
16
+ color: '#333',
17
+ background: 'none',
18
+ borderRadius: 2,
19
+ border: '1px solid #767676',
20
+ };
21
+ const selectStyle = inputStyle;
10
22
 
11
23
  const NumberInputSet = (props: {
12
24
  width: string;
@@ -19,7 +31,7 @@ const NumberInputSet = (props: {
19
31
  return (
20
32
  <div style={{ width }}>
21
33
  <label>{label}</label>
22
- <input style={{ width: '100%' }} onChange={onChange} value={value} type="number" />
34
+ <input style={inputStyle} onChange={onChange} value={value} type="number" />
23
35
  </div>
24
36
  );
25
37
  };
@@ -36,8 +48,20 @@ const ColorInputSet = (props: {
36
48
  <div style={{ width: '45%' }}>
37
49
  <label>{label}</label>
38
50
  <div style={{ display: 'flex' }}>
39
- <input onChange={onChange} value={value} type="color" style={{ width: '100%' }} />
40
- <button onClick={onClear}>X</button>
51
+ <input onChange={onChange} value={value || '#ffffff'} type="color" style={inputStyle} />
52
+ <button
53
+ onClick={onClear}
54
+ style={{
55
+ display: 'flex',
56
+ background: 'none',
57
+ alignItems: 'center',
58
+ borderRadius: 2,
59
+ border: '1px solid #767676',
60
+ cursor: 'pointer',
61
+ }}
62
+ >
63
+ <img src={closeIcon} width={10} alt="Close icon" />
64
+ </button>
41
65
  </div>
42
66
  </div>
43
67
  );
@@ -54,7 +78,7 @@ const SelectSet = (props: {
54
78
  return (
55
79
  <div style={{ width: '45%' }}>
56
80
  <label>{label}:</label>
57
- <select style={{ width: '100%' }} onChange={onChange} value={value}>
81
+ <select style={selectStyle} onChange={onChange} value={value}>
58
82
  {options.map((o) => (
59
83
  <option key={o} value={o}>
60
84
  {o}
@@ -65,7 +89,9 @@ const SelectSet = (props: {
65
89
  );
66
90
  };
67
91
 
68
- const TextPropEditor = (props: Pick<SidebarProps, 'changeSchemas' | 'activeSchema'>) => {
92
+ const TextPropEditor = (
93
+ props: Pick<SidebarProps, 'changeSchemas'> & { activeSchema: SchemaForUI }
94
+ ) => {
69
95
  const { changeSchemas, activeSchema } = props;
70
96
  const alignments = ['left', 'center', 'right'];
71
97
  const font = useContext(FontContext);
@@ -80,6 +106,7 @@ const TextPropEditor = (props: Pick<SidebarProps, 'changeSchemas' | 'activeSchem
80
106
  display: 'flex',
81
107
  alignItems: 'center',
82
108
  justifyContent: 'space-between',
109
+ marginBottom: '0.25rem',
83
110
  }}
84
111
  >
85
112
  <SelectSet
@@ -105,6 +132,7 @@ const TextPropEditor = (props: Pick<SidebarProps, 'changeSchemas' | 'activeSchem
105
132
  display: 'flex',
106
133
  alignItems: 'center',
107
134
  justifyContent: 'space-between',
135
+ marginBottom: '0.25rem',
108
136
  }}
109
137
  >
110
138
  <NumberInputSet
@@ -154,7 +182,9 @@ const TextPropEditor = (props: Pick<SidebarProps, 'changeSchemas' | 'activeSchem
154
182
  changeSchemas([{ key: 'fontColor', value: e.target.value, schemaId: activeSchema.id }])
155
183
  }
156
184
  onClear={() =>
157
- changeSchemas([{ key: 'fontColor', value: '', schemaId: activeSchema.id }])
185
+ changeSchemas([
186
+ { key: 'fontColor', value: DEFAULT_FONT_COLOR, schemaId: activeSchema.id },
187
+ ])
158
188
  }
159
189
  />
160
190
 
@@ -1,5 +1,5 @@
1
1
  import React, { useContext, useRef, useCallback } from 'react';
2
- import { schemaTypes } from '@pdfme/common';
2
+ import { schemaTypes, SchemaForUI } from '@pdfme/common';
3
3
  import { SidebarProps } from '..';
4
4
  import { I18nContext } from '../../../../contexts';
5
5
 
@@ -12,7 +12,7 @@ const ErrorLabel = ({ isError, msg }: { isError: boolean; msg: string }) => (
12
12
  );
13
13
 
14
14
  const TypeAndKeyEditor = (
15
- props: Pick<SidebarProps, 'schemas' | 'changeSchemas' | 'activeSchema'>
15
+ props: Pick<SidebarProps, 'schemas' | 'changeSchemas'> & { activeSchema: SchemaForUI }
16
16
  ) => {
17
17
  const { changeSchemas, activeSchema, schemas } = props;
18
18
  const i18n = useContext(I18nContext);
@@ -37,7 +37,13 @@ const TypeAndKeyEditor = (
37
37
  <div>
38
38
  <label style={{ marginBottom: 0 }}>{i18n('type')}</label>
39
39
  <select
40
- style={{ width: '100%' }}
40
+ style={{
41
+ width: '100%',
42
+ border: '1px solid #767676',
43
+ borderRadius: 2,
44
+ color: '#333',
45
+ background: 'none',
46
+ }}
41
47
  onChange={(e) =>
42
48
  changeSchemas([{ key: 'type', value: e.target.value, schemaId: activeSchema.id }])
43
49
  }
@@ -50,7 +56,7 @@ const TypeAndKeyEditor = (
50
56
  ))}
51
57
  </select>
52
58
  </div>
53
- <div style={{ width: '100%' }}>
59
+ <div>
54
60
  <label style={{ marginBottom: 0 }}>
55
61
  {i18n('fieldName')}
56
62
  <u style={{ fontSize: '0.7rem' }}>
@@ -65,9 +71,11 @@ const TypeAndKeyEditor = (
65
71
  changeSchemas([{ key: 'key', value: e.target.value, schemaId: activeSchema.id }])
66
72
  }
67
73
  style={{
68
- borderRadius: 2,
74
+ width: '100%',
69
75
  border: '1px solid #767676',
70
- backgroundColor: hasSameKey || blankKey ? '#ffa19b' : '#fff',
76
+ borderRadius: 2,
77
+ color: '#333',
78
+ background: hasSameKey || blankKey ? '#ffa19b' : 'none',
71
79
  }}
72
80
  value={activeSchema.key}
73
81
  />
@@ -1,4 +1,5 @@
1
1
  import React, { useContext } from 'react';
2
+ import { SchemaForUI } from '@pdfme/common';
2
3
  import { I18nContext } from '../../../../contexts';
3
4
  import Divider from '../../../Divider';
4
5
  import { SidebarProps } from '..';
@@ -8,31 +9,35 @@ import PositionAndSizeEditor from './PositionAndSizeEditor';
8
9
  import TypeAndKeyEditor from './TypeAndKeyEditor';
9
10
 
10
11
  const DetailView = (
11
- props: Pick<SidebarProps, 'schemas' | 'pageSize' | 'changeSchemas' | 'activeSchema'>
12
+ props: Pick<SidebarProps, 'schemas' | 'pageSize' | 'changeSchemas' | 'activeElements'> & {
13
+ activeSchema: SchemaForUI;
14
+ }
12
15
  ) => {
13
16
  const { activeSchema } = props;
14
17
  const i18n = useContext(I18nContext);
15
18
 
16
19
  return (
17
- <aside>
20
+ <div>
18
21
  <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
19
22
  <p style={{ textAlign: 'center', width: '100%', fontWeight: 'bold' }}>
20
23
  {i18n('editField')}
21
24
  </p>
22
25
  </div>
23
26
  <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>
27
+ <div style={{ fontSize: '0.9rem' }}>
28
+ <TypeAndKeyEditor {...props} />
29
+ <Divider />
30
+ <PositionAndSizeEditor {...props} />
31
+ <Divider />
32
+ {activeSchema.type === 'text' && (
33
+ <>
34
+ <TextPropEditor {...props} />
35
+ <Divider />
36
+ </>
37
+ )}
38
+ <ExampleInputEditor {...props} />
39
+ </div>
40
+ </div>
36
41
  );
37
42
  };
38
43
 
@@ -0,0 +1,113 @@
1
+ import React, { useEffect, useContext } from 'react';
2
+ import { DraggableSyntheticListeners } from '@dnd-kit/core';
3
+ import { I18nContext } from '../../../../contexts';
4
+ import dragIcon from '../../../../assets/icons/drag.svg';
5
+ import warningIcon from '../../../../assets/icons/warning.svg';
6
+
7
+ interface Props {
8
+ value: React.ReactNode;
9
+ style?: React.CSSProperties;
10
+ status?: 'is-warning' | 'is-danger';
11
+ title?: string;
12
+ dragOverlay?: boolean;
13
+ onClick?: () => void;
14
+ onMouseEnter?: () => void;
15
+ onMouseLeave?: () => void;
16
+ dragging?: boolean;
17
+ sorting?: boolean;
18
+ transition?: string;
19
+ transform?: { x: number; y: number; scaleX: number; scaleY: number } | null;
20
+ fadeIn?: boolean;
21
+ listeners?: DraggableSyntheticListeners;
22
+ }
23
+ const Item = React.memo(
24
+ React.forwardRef<HTMLLIElement, Props>(
25
+ (
26
+ {
27
+ value,
28
+ status,
29
+ title,
30
+ style,
31
+ dragOverlay,
32
+ onClick,
33
+ onMouseEnter,
34
+ onMouseLeave,
35
+ dragging,
36
+ fadeIn,
37
+ listeners,
38
+ sorting,
39
+ transition,
40
+ transform,
41
+ ...props
42
+ },
43
+ ref
44
+ ) => {
45
+ const i18n = useContext(I18nContext);
46
+
47
+ useEffect(() => {
48
+ if (!dragOverlay) {
49
+ return;
50
+ }
51
+
52
+ document.body.style.cursor = 'grabbing';
53
+
54
+ return () => {
55
+ document.body.style.cursor = '';
56
+ };
57
+ }, [dragOverlay]);
58
+
59
+ const { x, y, scaleX, scaleY } = transform || { x: 0, y: 0, scaleX: 1, scaleY: 1 };
60
+
61
+ return (
62
+ <li
63
+ style={{
64
+ transition,
65
+ transform: `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`,
66
+ }}
67
+ onMouseEnter={onMouseEnter}
68
+ onMouseLeave={onMouseLeave}
69
+ ref={ref}
70
+ >
71
+ <div style={{ display: 'flex', alignItems: 'center', ...style }} {...props}>
72
+ <button
73
+ {...listeners}
74
+ style={{ padding: '0.5rem', background: 'none', border: 'none', display: 'flex' }}
75
+ >
76
+ <img style={{ cursor: 'grab' }} src={dragIcon} width={15} alt="Drag icon" />
77
+ </button>
78
+ <div
79
+ style={{
80
+ width: '100%',
81
+ padding: '0.5rem',
82
+ paddingLeft: 0,
83
+ cursor: 'pointer',
84
+ overflow: 'hidden',
85
+ whiteSpace: 'nowrap',
86
+ textOverflow: 'ellipsis',
87
+ }}
88
+ title={title || ''}
89
+ onClick={() => onClick && onClick()}
90
+ >
91
+ {status === undefined ? (
92
+ value
93
+ ) : (
94
+ <span style={{ display: 'flex', alignItems: 'center' }}>
95
+ <img
96
+ alt="Warning icon"
97
+ src={warningIcon}
98
+ width={15}
99
+ style={{ marginRight: '0.5rem' }}
100
+ />
101
+ {status === 'is-warning' ? i18n('noKeyName') : value}
102
+ {status === 'is-danger' ? i18n('notUniq') : ''}
103
+ </span>
104
+ )}
105
+ </div>
106
+ </div>
107
+ </li>
108
+ );
109
+ }
110
+ )
111
+ );
112
+
113
+ export default Item;