@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,79 @@
1
+ import React, { forwardRef, Ref } from 'react';
2
+ import Moveable, {
3
+ OnDrag,
4
+ OnResize,
5
+ OnDragEnd,
6
+ OnDragGroupEnd,
7
+ OnResizeEnd,
8
+ OnResizeGroupEnd,
9
+ OnClick,
10
+ } from 'react-moveable';
11
+
12
+ type Props = {
13
+ target: HTMLElement[];
14
+ bounds: { left: number; top: number; bottom: number; right: number };
15
+ horizontalGuidelines: number[];
16
+ verticalGuidelines: number[];
17
+ keepRatio: boolean;
18
+ onDrag: ((e: OnDrag) => void) & (({ target, left, top }: OnDrag) => void);
19
+ onDragEnd: ((e: OnDragEnd) => void) &
20
+ (({ target }: { target: HTMLElement | SVGElement }) => void);
21
+ onDragGroupEnd: ((e: OnDragGroupEnd) => void) &
22
+ (({ targets }: { targets: (HTMLElement | SVGElement)[] }) => void);
23
+ onResize: ((e: OnResize) => void) & (({ target, width, height, direction }: OnResize) => void);
24
+ onResizeEnd: ((e: OnResizeEnd) => void) &
25
+ (({ target }: { target: HTMLElement | SVGElement }) => void);
26
+ onResizeGroupEnd: ((e: OnResizeGroupEnd) => void) &
27
+ (({ targets }: { targets: (HTMLElement | SVGElement)[] }) => void);
28
+ onClick: ((e: OnClick) => void) & (() => void);
29
+ };
30
+
31
+ const _Moveable = (
32
+ {
33
+ target,
34
+ bounds,
35
+ horizontalGuidelines,
36
+ verticalGuidelines,
37
+ keepRatio,
38
+ onDrag,
39
+ onDragEnd,
40
+ onDragGroupEnd,
41
+ onResize,
42
+ onResizeEnd,
43
+ onResizeGroupEnd,
44
+ onClick,
45
+ }: Props,
46
+ ref: Ref<any>
47
+ ) => (
48
+ <Moveable
49
+ style={{ zIndex: 1 }}
50
+ rootContainer={document ? document.body : undefined}
51
+ snappable
52
+ snapCenter
53
+ draggable
54
+ resizable
55
+ throttleDrag={1}
56
+ throttleResize={1}
57
+ ref={ref}
58
+ target={target}
59
+ bounds={bounds}
60
+ horizontalGuidelines={horizontalGuidelines}
61
+ verticalGuidelines={verticalGuidelines}
62
+ keepRatio={keepRatio}
63
+ onDrag={onDrag}
64
+ onDragGroup={({ events }) => {
65
+ events.forEach(onDrag);
66
+ }}
67
+ onDragEnd={onDragEnd}
68
+ onDragGroupEnd={onDragGroupEnd}
69
+ onResize={onResize}
70
+ onResizeGroup={({ events }) => {
71
+ events.forEach(onResize);
72
+ }}
73
+ onResizeEnd={onResizeEnd}
74
+ onResizeGroupEnd={onResizeGroupEnd}
75
+ onClick={onClick}
76
+ />
77
+ );
78
+
79
+ export default forwardRef<any, Props>(_Moveable);
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ import Selecto, { OnDragStart as _OnDragStart, OnSelect as _OnSelect } from 'react-selecto';
3
+ import { SELECTABLE_CLASSNAME } from '../../../constants';
4
+
5
+ const _Selecto = ({
6
+ container,
7
+ continueSelect,
8
+ onDragStart,
9
+ onSelect,
10
+ }: {
11
+ container: HTMLElement | null;
12
+ continueSelect: boolean;
13
+ onDragStart: (e: _OnDragStart) => void;
14
+ onSelect: (e: _OnSelect) => void;
15
+ }) => (
16
+ <Selecto
17
+ selectFromInside={false}
18
+ selectByClick
19
+ preventDefault
20
+ hitRate={0}
21
+ selectableTargets={[`.${SELECTABLE_CLASSNAME}`]}
22
+ container={container}
23
+ continueSelect={continueSelect}
24
+ onDragStart={onDragStart}
25
+ onSelect={onSelect}
26
+ />
27
+ );
28
+
29
+ export default _Selecto;
@@ -0,0 +1,314 @@
1
+ import React, {
2
+ Ref,
3
+ MutableRefObject,
4
+ useRef,
5
+ useState,
6
+ useEffect,
7
+ forwardRef,
8
+ useCallback,
9
+ } from 'react';
10
+ import { OnDrag, OnResize } from 'react-moveable';
11
+ import { SchemaForUI, Size } from '@pdfme/common';
12
+ import { ZOOM, RULER_HEIGHT } from '../../../constants';
13
+ import { usePrevious } from '../../../hooks';
14
+ import { uuid, round, flatten } from '../../../helper';
15
+ import Paper from '../../Paper';
16
+ import SchemaUI from '../../Schemas/SchemaUI';
17
+ import Selecto from './Selecto';
18
+ import Moveable from './Moveable';
19
+ import Guides from './Guides';
20
+ import Mask from './Mask';
21
+
22
+ const DELETE_BTN_ID = uuid();
23
+ const fmt4Num = (prop: string) => Number(prop.replace('px', ''));
24
+ const fmt = (prop: string) => round(fmt4Num(prop) / ZOOM, 2);
25
+ const isTopLeftResize = (d: string) => d === '-1,-1' || d === '-1,0' || d === '0,-1';
26
+
27
+ const DeleteButton = ({ activeElements: aes }: { activeElements: HTMLElement[] }) => {
28
+ const top = Math.min(...aes.map(({ style }) => fmt4Num(style.top)));
29
+ const left = Math.max(...aes.map(({ style }) => fmt4Num(style.left) + fmt4Num(style.width))) + 10;
30
+
31
+ return (
32
+ <button
33
+ id={DELETE_BTN_ID}
34
+ style={{
35
+ position: 'absolute',
36
+ top,
37
+ left,
38
+ cursor: 'pointer',
39
+ color: 'white',
40
+ border: 'none',
41
+ fontWeight: 'bold',
42
+ borderRadius: 3,
43
+ background: 'rgb(68, 170, 255)',
44
+ }}
45
+ >
46
+ x
47
+ </button>
48
+ );
49
+ };
50
+
51
+ interface GuidesInterface {
52
+ getGuides(): number[];
53
+ scroll(pos: number): void;
54
+ scrollGuides(pos: number): void;
55
+ loadGuides(guides: number[]): void;
56
+ resize(): void;
57
+ }
58
+
59
+ interface Props {
60
+ height: number;
61
+ hoveringSchemaId: string | null;
62
+ onChangeHoveringSchemaId: (id: string | null) => void;
63
+ pageCursor: number;
64
+ schemasList: SchemaForUI[][];
65
+ scale: number;
66
+ backgrounds: string[];
67
+ pageSizes: Size[];
68
+ size: Size;
69
+ activeElements: HTMLElement[];
70
+ onEdit: (targets: HTMLElement[]) => void;
71
+ changeSchemas: (objs: { key: string; value: string | number; schemaId: string }[]) => void;
72
+ removeSchemas: (ids: string[]) => void;
73
+ paperRefs: MutableRefObject<HTMLDivElement[]>;
74
+ }
75
+
76
+ const Main = (props: Props, ref: Ref<HTMLDivElement>) => {
77
+ const {
78
+ pageCursor,
79
+ scale,
80
+ backgrounds,
81
+ pageSizes,
82
+ size,
83
+ activeElements,
84
+ schemasList,
85
+ hoveringSchemaId,
86
+ } = props;
87
+ const { onEdit, changeSchemas, removeSchemas, onChangeHoveringSchemaId, paperRefs } = props;
88
+
89
+ const inputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null);
90
+ const verticalGuides = useRef<GuidesInterface[]>([]);
91
+ const horizontalGuides = useRef<GuidesInterface[]>([]);
92
+ const moveable = useRef<any>(null);
93
+
94
+ const [isPressShiftKey, setIsPressShiftKey] = useState(false);
95
+ const [editing, setEditing] = useState(false);
96
+
97
+ const prevSchemas = usePrevious(schemasList[pageCursor]);
98
+
99
+ const onKeydown = (e: KeyboardEvent) => {
100
+ if (e.shiftKey) setIsPressShiftKey(true);
101
+ };
102
+ const onKeyup = (e: KeyboardEvent) => {
103
+ if (e.key === 'Shift') setIsPressShiftKey(false);
104
+ if (e.key === 'Escape' || e.key === 'Esc') setEditing(false);
105
+ };
106
+
107
+ const initEvents = useCallback(() => {
108
+ window.addEventListener('keydown', onKeydown);
109
+ window.addEventListener('keyup', onKeyup);
110
+ }, []);
111
+
112
+ const destroyEvents = useCallback(() => {
113
+ window.removeEventListener('keydown', onKeydown);
114
+ window.removeEventListener('keyup', onKeyup);
115
+ }, []);
116
+
117
+ useEffect(() => {
118
+ initEvents();
119
+
120
+ return destroyEvents;
121
+ }, [initEvents, destroyEvents]);
122
+
123
+ useEffect(() => {
124
+ if (prevSchemas === null) {
125
+ moveable.current?.updateRect();
126
+
127
+ return;
128
+ }
129
+
130
+ const prevSchemaKeys = Object.keys(prevSchemas[pageCursor] || {});
131
+ const schemaKeys = Object.keys(schemasList[pageCursor] || {});
132
+
133
+ if (prevSchemaKeys.join() === schemaKeys.join()) {
134
+ moveable.current?.updateRect();
135
+ }
136
+ }, [pageCursor, schemasList, prevSchemas]);
137
+
138
+ const onDrag = ({ target, left, top }: OnDrag) => {
139
+ target.style.left = `${left < 0 ? 0 : left}px`;
140
+ target.style.top = `${top < 0 ? 0 : top}px`;
141
+ };
142
+
143
+ const onDragEnd = ({ target }: { target: HTMLElement | SVGElement }) => {
144
+ const { top, left } = target.style;
145
+ changeSchemas([
146
+ { key: 'position.y', value: fmt(top), schemaId: target.id },
147
+ { key: 'position.x', value: fmt(left), schemaId: target.id },
148
+ ]);
149
+ };
150
+
151
+ const onDragEnds = ({ targets }: { targets: (HTMLElement | SVGElement)[] }) => {
152
+ const arg = targets.map(({ style: { top, left }, id }) => [
153
+ { key: 'position.y', value: fmt(top), schemaId: id },
154
+ { key: 'position.x', value: fmt(left), schemaId: id },
155
+ ]);
156
+ changeSchemas(flatten(arg));
157
+ };
158
+
159
+ const onResizeEnd = ({ target }: { target: HTMLElement | SVGElement }) => {
160
+ const { id, style } = target;
161
+ const { width, height, top, left } = style;
162
+ changeSchemas([
163
+ { key: 'width', value: fmt(width), schemaId: id },
164
+ { key: 'height', value: fmt(height), schemaId: id },
165
+ { key: 'position.y', value: fmt(top), schemaId: id },
166
+ { key: 'position.x', value: fmt(left), schemaId: id },
167
+ ]);
168
+ };
169
+
170
+ const onResizeEnds = ({ targets }: { targets: (HTMLElement | SVGElement)[] }) => {
171
+ const arg = targets.map(({ style: { width, height, top, left }, id }) => [
172
+ { key: 'width', value: fmt(width), schemaId: id },
173
+ { key: 'height', value: fmt(height), schemaId: id },
174
+ { key: 'position.y', value: fmt(top), schemaId: id },
175
+ { key: 'position.x', value: fmt(left), schemaId: id },
176
+ ]);
177
+ changeSchemas(flatten(arg));
178
+ };
179
+
180
+ const onResize = ({ target, width, height, direction }: OnResize) => {
181
+ if (!target) return;
182
+ const s = target.style;
183
+ const newLeft = fmt4Num(s.left) + (fmt4Num(s.width) - width);
184
+ const newTop = fmt4Num(s.top) + (fmt4Num(s.height) - height);
185
+ const obj: { top?: string; left?: string; width: string; height: string } = {
186
+ width: `${width}px`,
187
+ height: `${height}px`,
188
+ };
189
+ const d = direction.toString();
190
+ if (isTopLeftResize(d)) {
191
+ obj.top = `${newTop}px`;
192
+ obj.left = `${newLeft}px`;
193
+ } else if (d === '1,-1') {
194
+ obj.top = `${newTop}px`;
195
+ } else if (d === '-1,1') {
196
+ obj.left = `${newLeft}px`;
197
+ }
198
+ Object.assign(s, obj);
199
+ };
200
+
201
+ const getGuideLines = (guides: GuidesInterface[], index: number) =>
202
+ guides[index] && guides[index].getGuides().map((g) => g * ZOOM);
203
+
204
+ const onClickMoveable = () => {
205
+ setEditing(true);
206
+ const ic = inputRef.current;
207
+ if (!ic) return;
208
+ ic.disabled = false;
209
+ ic.focus();
210
+ if (ic.type === 'file') {
211
+ ic.click();
212
+ } else {
213
+ ic.setSelectionRange(ic.value.length, ic.value.length);
214
+ }
215
+ };
216
+
217
+ return (
218
+ <div
219
+ ref={ref}
220
+ onClick={(e) => {
221
+ e.stopPropagation();
222
+ setEditing(false);
223
+ }}
224
+ style={{ height: props.height }}
225
+ >
226
+ <Selecto
227
+ container={paperRefs.current[pageCursor]}
228
+ continueSelect={isPressShiftKey}
229
+ onDragStart={(e) => {
230
+ const { inputEvent } = e;
231
+ const isMoveableElement = moveable.current?.isMoveableElement(inputEvent.target);
232
+ if ((inputEvent.type === 'touchstart' && e.isTrusted) || isMoveableElement) {
233
+ e.stop();
234
+ }
235
+
236
+ if (paperRefs.current[pageCursor] === inputEvent.target) {
237
+ onEdit([]);
238
+ }
239
+
240
+ if (inputEvent.target.id === DELETE_BTN_ID) {
241
+ removeSchemas(activeElements.map((ae) => ae.id));
242
+ }
243
+ }}
244
+ onSelect={(e) => {
245
+ onEdit(e.selected as HTMLElement[]);
246
+ }}
247
+ />
248
+ <Paper
249
+ paperRefs={paperRefs}
250
+ scale={scale}
251
+ size={size}
252
+ schemasList={schemasList}
253
+ pageSizes={pageSizes}
254
+ backgrounds={backgrounds}
255
+ renderPaper={({ index, paperSize }) => (
256
+ <>
257
+ {!editing && activeElements.length > 0 && (
258
+ <DeleteButton activeElements={activeElements} />
259
+ )}
260
+ <Guides
261
+ paperSize={paperSize}
262
+ horizontalRef={(e) => {
263
+ if (e) {
264
+ horizontalGuides.current[index] = e;
265
+ }
266
+ }}
267
+ verticalRef={(e) => {
268
+ if (e) {
269
+ verticalGuides.current[index] = e;
270
+ }
271
+ }}
272
+ />
273
+ {pageCursor !== index ? (
274
+ <Mask
275
+ width={paperSize.width + RULER_HEIGHT}
276
+ height={paperSize.height + RULER_HEIGHT}
277
+ />
278
+ ) : (
279
+ !editing && (
280
+ <Moveable
281
+ ref={moveable}
282
+ target={activeElements}
283
+ bounds={{ left: 0, top: 0, bottom: paperSize.height, right: paperSize.width }}
284
+ horizontalGuidelines={getGuideLines(horizontalGuides.current, index)}
285
+ verticalGuidelines={getGuideLines(verticalGuides.current, index)}
286
+ keepRatio={isPressShiftKey}
287
+ onDrag={onDrag}
288
+ onDragEnd={onDragEnd}
289
+ onDragGroupEnd={onDragEnds}
290
+ onResize={onResize}
291
+ onResizeEnd={onResizeEnd}
292
+ onResizeGroupEnd={onResizeEnds}
293
+ onClick={onClickMoveable}
294
+ />
295
+ )
296
+ )}
297
+ </>
298
+ )}
299
+ renderSchema={({ schema }) => (
300
+ <SchemaUI
301
+ key={schema.key}
302
+ schema={schema}
303
+ onChangeHoveringSchemaId={onChangeHoveringSchemaId}
304
+ editable={editing && activeElements.map((ae) => ae.id).includes(schema.id)}
305
+ onChange={(value) => changeSchemas([{ key: 'data', value, schemaId: schema.id }])}
306
+ border={hoveringSchemaId === schema.id ? '2px solid #18a0fb' : '1px dashed #4af'}
307
+ ref={inputRef}
308
+ />
309
+ )}
310
+ />
311
+ </div>
312
+ );
313
+ };
314
+ export default forwardRef<HTMLDivElement, Props>(Main);
@@ -0,0 +1,62 @@
1
+ import React, { useContext } from 'react';
2
+ import { readFiles } from '../../../../helper';
3
+ import { I18nContext } from '../../../../contexts';
4
+ import { SidebarProps } from '..';
5
+
6
+ const ExampleInputEditor = (props: Pick<SidebarProps, 'changeSchemas' | 'activeSchema'>) => {
7
+ const { changeSchemas, activeSchema } = props;
8
+ const i18n = useContext(I18nContext);
9
+
10
+ return (
11
+ <div>
12
+ <label style={{ marginBottom: 0 }}>{i18n('inputExample')}</label>
13
+ {activeSchema.type === 'image' ? (
14
+ <div style={{ position: 'relative', textAlign: 'center' }}>
15
+ {activeSchema.data ? (
16
+ <div style={{ margin: '0 auto' }}>
17
+ <button
18
+ style={{ position: 'absolute', top: 0, left: 0 }}
19
+ aria-label="close"
20
+ onClick={() =>
21
+ changeSchemas([{ key: 'data', value: '', schemaId: activeSchema.id }])
22
+ }
23
+ >
24
+ x
25
+ </button>
26
+ <img style={{ maxHeight: 180 }} src={activeSchema.data} alt="Input Example" />
27
+ </div>
28
+ ) : (
29
+ <label>
30
+ <input
31
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
32
+ const { files } = e.target;
33
+ readFiles(files, 'dataURL').then((result) => {
34
+ changeSchemas([
35
+ { key: 'data', value: result as string, schemaId: activeSchema.id },
36
+ ]);
37
+ });
38
+ }}
39
+ type="file"
40
+ accept="image/jpeg, image/png"
41
+ />
42
+ </label>
43
+ )}
44
+ </div>
45
+ ) : (
46
+ <textarea
47
+ rows={6}
48
+ onChange={(e) =>
49
+ changeSchemas([{ key: 'data', value: e.target.value, schemaId: activeSchema.id }])
50
+ }
51
+ style={{
52
+ width: '100%',
53
+ backgroundColor: activeSchema.data ? '#fff' : '#ffa19b',
54
+ }}
55
+ value={activeSchema.data}
56
+ />
57
+ )}
58
+ </div>
59
+ );
60
+ };
61
+
62
+ export default ExampleInputEditor;
@@ -0,0 +1,98 @@
1
+ import React from 'react';
2
+ import { SidebarProps } from '..';
3
+
4
+ const inputSetStyle: React.CSSProperties = {
5
+ marginRight: '1rem',
6
+ display: 'flex',
7
+ alignItems: 'center',
8
+ };
9
+
10
+ const PositionAndSizeEditor = (
11
+ props: Pick<SidebarProps, 'pageSize' | 'changeSchemas' | 'activeSchema'>
12
+ ) => {
13
+ const { changeSchemas, activeSchema, pageSize } = props;
14
+
15
+ return (
16
+ <div>
17
+ <div
18
+ style={{
19
+ display: 'flex',
20
+ alignItems: 'center',
21
+ justifyContent: 'space-between',
22
+ }}
23
+ >
24
+ <div style={inputSetStyle}>
25
+ <label style={{ width: 17 }}>X</label>
26
+ <input
27
+ style={{ width: 70 }}
28
+ type="number"
29
+ onChange={(e) => {
30
+ const value = Number(e.target.value);
31
+ if (value >= 0 && activeSchema.width + value < pageSize.width) {
32
+ changeSchemas([{ key: 'position.x', value, schemaId: activeSchema.id }]);
33
+ }
34
+ }}
35
+ value={activeSchema.position.x}
36
+ />
37
+ <span style={{ fontSize: '0.6rem' }}>mm</span>
38
+ </div>
39
+ <div style={inputSetStyle}>
40
+ <label style={{ width: 17 }}>Y</label>
41
+ <input
42
+ style={{ width: 70 }}
43
+ type="number"
44
+ onChange={(e) => {
45
+ const value = Number(e.target.value);
46
+ if (value >= 0 && activeSchema.height + value < pageSize.height) {
47
+ changeSchemas([{ key: 'position.y', value, schemaId: activeSchema.id }]);
48
+ }
49
+ }}
50
+ value={activeSchema.position.y}
51
+ />
52
+ <span style={{ fontSize: '0.6rem' }}>mm</span>
53
+ </div>
54
+ </div>
55
+ <div
56
+ style={{
57
+ display: 'flex',
58
+ alignItems: 'center',
59
+ justifyContent: 'space-between',
60
+ marginTop: '0.25rem',
61
+ }}
62
+ >
63
+ <div style={inputSetStyle}>
64
+ <label style={{ width: 17 }}>W</label>
65
+ <input
66
+ style={{ width: 70 }}
67
+ type="number"
68
+ onChange={(e) => {
69
+ const value = Number(e.target.value);
70
+ if (value >= 0 && activeSchema.position.x + value < pageSize.width) {
71
+ changeSchemas([{ key: 'width', value, schemaId: activeSchema.id }]);
72
+ }
73
+ }}
74
+ value={activeSchema.width}
75
+ />
76
+ <span style={{ fontSize: '0.6rem' }}>mm</span>
77
+ </div>
78
+ <div style={inputSetStyle}>
79
+ <label style={{ width: 17 }}>H</label>
80
+ <input
81
+ style={{ width: 70 }}
82
+ type="number"
83
+ onChange={(e) => {
84
+ const value = Number(e.target.value);
85
+ if (value >= 0 && activeSchema.position.y + value < pageSize.height) {
86
+ changeSchemas([{ key: 'height', value, schemaId: activeSchema.id }]);
87
+ }
88
+ }}
89
+ value={activeSchema.height}
90
+ />
91
+ <span style={{ fontSize: '0.6rem' }}>mm</span>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ );
96
+ };
97
+
98
+ export default PositionAndSizeEditor;