@pdfme/ui 5.3.11-dev.2 → 5.3.11-dev.21

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 (35) hide show
  1. package/dist/index.es.js +9109 -8970
  2. package/dist/index.umd.js +125 -125
  3. package/dist/types/src/components/Designer/Canvas/Guides.d.ts +3 -9
  4. package/dist/types/src/components/Designer/Canvas/Moveable.d.ts +2 -49
  5. package/dist/types/src/components/Designer/Canvas/Selecto.d.ts +5 -16
  6. package/dist/types/src/components/Designer/PluginIcon.d.ts +2 -2
  7. package/dist/types/src/components/Designer/RightSidebar/ListView/Item.d.ts +17 -0
  8. package/dist/types/src/components/Renderer.d.ts +1 -10
  9. package/dist/types/src/constants.d.ts +1 -1
  10. package/dist/types/src/contexts.d.ts +1 -1
  11. package/dist/types/src/helper.d.ts +3 -4
  12. package/package.json +3 -3
  13. package/src/components/AppContextProvider.tsx +23 -10
  14. package/src/components/CtlBar.tsx +2 -2
  15. package/src/components/Designer/Canvas/Guides.tsx +4 -13
  16. package/src/components/Designer/Canvas/Moveable.tsx +21 -76
  17. package/src/components/Designer/Canvas/Selecto.tsx +12 -24
  18. package/src/components/Designer/Canvas/index.tsx +51 -72
  19. package/src/components/Designer/LeftSidebar.tsx +2 -2
  20. package/src/components/Designer/PluginIcon.tsx +15 -3
  21. package/src/components/Designer/RightSidebar/DetailView/AlignWidget.tsx +102 -16
  22. package/src/components/Designer/RightSidebar/DetailView/ButtonGroupWidget.tsx +11 -8
  23. package/src/components/Designer/RightSidebar/DetailView/index.tsx +170 -48
  24. package/src/components/Designer/RightSidebar/ListView/Item.tsx +114 -88
  25. package/src/components/Designer/RightSidebar/ListView/SelectableSortableContainer.tsx +23 -3
  26. package/src/components/Designer/RightSidebar/ListView/SelectableSortableItem.tsx +21 -4
  27. package/src/components/Designer/index.tsx +14 -9
  28. package/src/components/Preview.tsx +5 -5
  29. package/src/components/Renderer.tsx +43 -37
  30. package/src/components/Root.tsx +1 -1
  31. package/src/constants.ts +1 -1
  32. package/src/contexts.ts +1 -1
  33. package/src/helper.ts +136 -38
  34. package/src/types/react-guides.d.ts +0 -22
  35. package/src/types/react-selecto.d.ts +0 -35
@@ -10,6 +10,7 @@ import React, {
10
10
  useCallback,
11
11
  } from 'react';
12
12
  import { theme, Button } from 'antd';
13
+ import MoveableComponent, { OnDrag, OnRotate, OnResize } from 'react-moveable';
13
14
  import {
14
15
  ZOOM,
15
16
  SchemaForUI,
@@ -33,60 +34,6 @@ import Mask from './Mask.js';
33
34
  import Padding from './Padding.js';
34
35
  import StaticSchema from '../../StaticSchema.js';
35
36
 
36
- // Define the interfaces locally since they're not exported properly
37
- interface OnDrag {
38
- target: HTMLElement | SVGElement;
39
- left: number;
40
- top: number;
41
- // Add additional properties that might be used in the original library
42
- beforeDelta: any;
43
- beforeDist: any;
44
- beforeTranslate: any;
45
- delta: any;
46
- dist: any;
47
- transform: any;
48
- translate: any;
49
- }
50
-
51
- interface OnResize {
52
- target: HTMLElement | SVGElement;
53
- width: number;
54
- height: number;
55
- direction: string;
56
- // Add additional properties that might be used in the original library
57
- offsetWidth: number;
58
- offsetHeight: number;
59
- dist: any;
60
- delta: any;
61
- transform: any;
62
- translate: any;
63
- }
64
-
65
- interface OnRotate {
66
- target: HTMLElement | SVGElement;
67
- rotate: number;
68
- // Add additional properties that might be used in the original library
69
- beforeDist: any;
70
- beforeDelta: any;
71
- beforeRotate: any;
72
- dist: any;
73
- delta: any;
74
- transform: any;
75
- }
76
-
77
- interface OnClick {
78
- inputEvent: MouseEvent;
79
- // Add additional properties that might be used in the original library
80
- inputTarget: any;
81
- isTarget: boolean;
82
- containsTarget: boolean;
83
- isDouble: boolean;
84
- datas: any;
85
- targets: any[];
86
- clientX: number;
87
- clientY: number;
88
- }
89
-
90
37
  const mm2px = (mm: number) => mm * 3.7795275591;
91
38
 
92
39
  const DELETE_BTN_ID = uuid();
@@ -175,7 +122,7 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
175
122
  const pluginsRegistry = useContext(PluginsRegistry);
176
123
  const verticalGuides = useRef<GuidesInterface[]>([]);
177
124
  const horizontalGuides = useRef<GuidesInterface[]>([]);
178
- const moveable = useRef<any>(null);
125
+ const moveable = useRef<MoveableComponent>(null);
179
126
 
180
127
  const [isPressShiftKey, setIsPressShiftKey] = useState(false);
181
128
  const [editing, setEditing] = useState(false);
@@ -373,8 +320,8 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
373
320
  const getGuideLines = (guides: GuidesInterface[], index: number) =>
374
321
  guides[index] && guides[index].getGuides().map((g) => g * ZOOM);
375
322
 
376
- const onClickMoveable = (e: OnClick) => {
377
- e.inputEvent.stopPropagation();
323
+ const onClickMoveable = () => {
324
+ // Just set editing to true without trying to access event properties
378
325
  setEditing(true);
379
326
  };
380
327
 
@@ -384,13 +331,30 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
384
331
  );
385
332
  const schemaTypes = selectedSchemas.map((s) => s.type);
386
333
  const uniqueSchemaTypes = [...new Set(schemaTypes)];
387
- const defaultSchemas = Object.values(pluginsRegistry).map(
388
- (plugin) => plugin?.propPanel.defaultSchema,
389
- );
390
334
 
391
- return uniqueSchemaTypes.every(
392
- (type) => defaultSchemas.find((ds) => ds.type === type)?.rotate !== undefined,
393
- );
335
+ // Create a type-safe array of default schemas
336
+ const defaultSchemas: Record<string, unknown>[] = [];
337
+
338
+ // Safely iterate through plugins registry
339
+ Object.values(pluginsRegistry).forEach((plugin) => {
340
+ if (
341
+ plugin &&
342
+ typeof plugin === 'object' &&
343
+ 'propPanel' in plugin &&
344
+ plugin.propPanel &&
345
+ typeof plugin.propPanel === 'object' &&
346
+ 'defaultSchema' in plugin.propPanel &&
347
+ plugin.propPanel.defaultSchema
348
+ ) {
349
+ defaultSchemas.push(plugin.propPanel.defaultSchema as Record<string, unknown>);
350
+ }
351
+ });
352
+
353
+ // Check if all schema types have rotate property
354
+ return uniqueSchemaTypes.every((type) => {
355
+ const matchingSchema = defaultSchemas.find((ds) => ds && 'type' in ds && ds.type === type);
356
+ return matchingSchema && 'rotate' in matchingSchema;
357
+ });
394
358
  }, [activeElements, pageCursor, schemasList, pluginsRegistry]);
395
359
 
396
360
  return (
@@ -407,26 +371,37 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
407
371
  container={paperRefs.current[pageCursor]}
408
372
  continueSelect={isPressShiftKey}
409
373
  onDragStart={(e) => {
410
- const { inputEvent } = e;
411
- const isMoveableElement = moveable.current?.isMoveableElement(inputEvent.target);
374
+ // Use type assertion to safely access inputEvent properties
375
+ const inputEvent = e.inputEvent as MouseEvent | TouchEvent;
376
+ const target = inputEvent.target as Element | null;
377
+ const isMoveableElement = moveable.current?.isMoveableElement(target as Element);
378
+
412
379
  if ((inputEvent.type === 'touchstart' && e.isTrusted) || isMoveableElement) {
413
380
  e.stop();
414
381
  }
415
382
 
416
- if (paperRefs.current[pageCursor] === inputEvent.target) {
383
+ if (paperRefs.current[pageCursor] === target) {
417
384
  onEdit([]);
418
385
  }
386
+
419
387
  // Check if the target is an HTMLElement and has an id property
420
- const targetElement = inputEvent.target as HTMLElement;
388
+ const targetElement = target as HTMLElement | null;
421
389
  if (targetElement && targetElement.id === DELETE_BTN_ID) {
422
390
  removeSchemas(activeElements.map((ae) => ae.id));
423
391
  }
424
392
  }}
425
- onSelect={({ added, removed, selected, inputEvent }) => {
393
+ onSelect={(e) => {
394
+ // Use type assertions to safely access properties
395
+ const inputEvent = e.inputEvent as MouseEvent | TouchEvent;
396
+ const added = e.added as HTMLElement[];
397
+ const removed = e.removed as HTMLElement[];
398
+ const selected = e.selected as HTMLElement[];
399
+
426
400
  const isClick = inputEvent.type === 'mousedown';
427
- let newActiveElements: HTMLElement[] = isClick ? (selected as HTMLElement[]) : [];
401
+ let newActiveElements: HTMLElement[] = isClick ? selected : [];
402
+
428
403
  if (!isClick && added.length > 0) {
429
- newActiveElements = activeElements.concat(added as HTMLElement[]);
404
+ newActiveElements = activeElements.concat(added);
430
405
  }
431
406
  if (!isClick && removed.length > 0) {
432
407
  newActiveElements = activeElements.filter((ae) => !removed.includes(ae));
@@ -436,8 +411,10 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
436
411
  if (newActiveElements != activeElements) {
437
412
  setEditing(false);
438
413
  }
414
+
439
415
  // For MacOS CMD+SHIFT+3/4 screenshots where the keydown event is never received, check mouse too
440
- if (!inputEvent.shiftKey) {
416
+ const mouseEvent = inputEvent as MouseEvent;
417
+ if (mouseEvent && typeof mouseEvent.shiftKey === 'boolean' && !mouseEvent.shiftKey) {
441
418
  setIsPressShiftKey(false);
442
419
  }
443
420
  }}
@@ -538,7 +515,9 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
538
515
  onChangeHoveringSchemaId={onChangeHoveringSchemaId}
539
516
  mode={mode}
540
517
  onChange={(arg) => {
541
- const args = Array.isArray(arg) ? arg : [arg];
518
+ // Use type assertion to safely handle the argument
519
+ type ChangeArg = { key: string; value: unknown };
520
+ const args = Array.isArray(arg) ? (arg as ChangeArg[]) : [arg as ChangeArg];
542
521
  changeSchemas(args.map(({ key, value }) => ({ key, value, schemaId: schema.id })));
543
522
  }}
544
523
  stopEditing={() => setEditing(false)}
@@ -9,14 +9,14 @@ import { PluginsRegistry } from '../../contexts.js';
9
9
  import PluginIcon from './PluginIcon.js';
10
10
 
11
11
  const Draggable = (props: {
12
- plugin: Plugin<any>;
12
+ plugin: Plugin<Schema>;
13
13
  scale: number;
14
14
  basePdf: BasePdf;
15
15
  children: React.ReactNode;
16
16
  }) => {
17
17
  const { scale, basePdf, plugin } = props;
18
18
  const { token } = theme.useToken();
19
- const defaultSchema = plugin.propPanel.defaultSchema as Schema;
19
+ const defaultSchema = plugin.propPanel.defaultSchema;
20
20
  const draggable = useDraggable({ id: defaultSchema.type, data: defaultSchema });
21
21
  const { listeners, setNodeRef, attributes, transform, isDragging } = draggable;
22
22
  const style = { transform: CSS.Translate.toString(transform) };
@@ -1,10 +1,10 @@
1
1
  import React, { useContext } from 'react';
2
- import { Plugin } from '@pdfme/common';
2
+ import { Plugin, Schema } from '@pdfme/common';
3
3
  import { OptionsContext } from '../../contexts.js';
4
4
  import { theme } from 'antd';
5
5
 
6
6
  interface PluginIconProps {
7
- plugin: Plugin<any>;
7
+ plugin: Plugin<Schema>;
8
8
  label: string;
9
9
  size?: number;
10
10
  styles?: React.CSSProperties;
@@ -38,7 +38,19 @@ const PluginIcon = (props: PluginIconProps) => {
38
38
  const { plugin, label, size, styles } = props;
39
39
  const { token } = theme.useToken();
40
40
  const options = useContext(OptionsContext);
41
- const icon = options.icons?.[plugin.propPanel.defaultSchema.type] ?? plugin.icon;
41
+
42
+ // Safely access plugin properties with proper type checking
43
+ const defaultSchemaType =
44
+ plugin.propPanel &&
45
+ typeof plugin.propPanel === 'object' &&
46
+ plugin.propPanel.defaultSchema &&
47
+ typeof plugin.propPanel.defaultSchema === 'object' &&
48
+ 'type' in plugin.propPanel.defaultSchema &&
49
+ typeof plugin.propPanel.defaultSchema.type === 'string'
50
+ ? plugin.propPanel.defaultSchema.type
51
+ : '';
52
+
53
+ const icon = options.icons?.[defaultSchemaType] ?? plugin.icon;
42
54
  const iconStyles = {
43
55
  ...styles,
44
56
  color: token.colorText,
@@ -23,28 +23,71 @@ const AlignWidget = (props: PropPanelWidgetProps) => {
23
23
  const tgtPos = isVertical ? 'x' : 'y';
24
24
  const tgtSize = isVertical ? 'width' : 'height';
25
25
  const isSingle = ass.length === 1;
26
- const root = pageSize[tgtSize];
26
+ // Access pageSize property safely with proper type assertion
27
+ const root =
28
+ pageSize && typeof pageSize === 'object'
29
+ ? tgtSize === 'width'
30
+ ? (pageSize as unknown as { width: number }).width
31
+ : (pageSize as unknown as { height: number }).height
32
+ : 0;
27
33
 
28
- const min = isSingle ? 0 : Math.min(...ass.map((as) => as.position[tgtPos]));
29
- const max = isSingle ? root : Math.max(...ass.map((as) => as.position[tgtPos] + as[tgtSize]));
34
+ // Access position properties safely with proper type assertion
35
+ const min = isSingle
36
+ ? 0
37
+ : Math.min(
38
+ ...ass.map((as) => {
39
+ // Safely access position property with proper type assertion
40
+ const position =
41
+ as.position && typeof as.position === 'object'
42
+ ? (as.position as unknown as { x: number; y: number })
43
+ : { x: 0, y: 0 };
44
+ return tgtPos === 'x' ? position.x : position.y;
45
+ }),
46
+ );
47
+ const max = isSingle
48
+ ? root
49
+ : Math.max(
50
+ ...ass.map((as) => {
51
+ // Safely access position and size properties with proper type assertion
52
+ const position =
53
+ as.position && typeof as.position === 'object'
54
+ ? (as.position as unknown as { x: number; y: number })
55
+ : { x: 0, y: 0 };
56
+ const posValue = tgtPos === 'x' ? position.x : position.y;
57
+
58
+ // Safely access width/height with proper type assertion
59
+ const asWithSize = as as unknown as { width?: number; height?: number };
60
+ const sizeValue = tgtSize === 'width' ? asWithSize.width || 0 : asWithSize.height || 0;
61
+
62
+ return posValue + sizeValue;
63
+ }),
64
+ );
30
65
 
31
66
  let basePos = min;
32
- let adjust = (_: number) => 0;
67
+ // Define adjust function with consistent parameter usage
68
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
69
+ let adjust = (_size: number): number => 0;
33
70
 
34
71
  if (['center', 'middle'].includes(type)) {
35
72
  basePos = (min + max) / 2;
36
- adjust = (num: number) => num / 2;
73
+ adjust = (size: number): number => size / 2;
37
74
  } else if (['right', 'bottom'].includes(type)) {
38
75
  basePos = max;
39
- adjust = (num: number) => num;
76
+ adjust = (size: number): number => size;
40
77
  }
41
78
 
42
79
  changeSchemas(
43
- ass.map((as) => ({
44
- key: `position.${tgtPos}`,
45
- value: round(basePos - adjust(as[tgtSize]), 2),
46
- schemaId: as.id,
47
- })),
80
+ ass.map((as) => {
81
+ // Safely access size property with proper type assertion
82
+ const asWithSize = as as unknown as { width?: number; height?: number; id: string };
83
+ const sizeValue = tgtSize === 'width' ? asWithSize.width || 0 : asWithSize.height || 0;
84
+
85
+ return {
86
+ key: `position.${tgtPos}`,
87
+ value: round(basePos - adjust(sizeValue), 2),
88
+ schemaId: asWithSize.id,
89
+ };
90
+ }),
48
91
  );
49
92
  };
50
93
 
@@ -55,23 +98,66 @@ const AlignWidget = (props: PropPanelWidgetProps) => {
55
98
  const isVertical = type === 'vertical';
56
99
  const tgtPos = isVertical ? 'y' : 'x';
57
100
  const tgtSize = isVertical ? 'height' : 'width';
58
- const min = Math.min(...ass.map((as) => as.position[tgtPos]));
59
- const max = Math.max(...ass.map((as) => as.position[tgtPos] + as[tgtSize]));
101
+
102
+ // Safely access position property with proper type assertion
103
+ const min = Math.min(
104
+ ...ass.map((as) => {
105
+ const position =
106
+ as.position && typeof as.position === 'object'
107
+ ? (as.position as unknown as { x: number; y: number })
108
+ : { x: 0, y: 0 };
109
+ return tgtPos === 'x' ? position.x : position.y;
110
+ }),
111
+ );
112
+
113
+ // Safely access position and size properties with proper type assertion
114
+ const max = Math.max(
115
+ ...ass.map((as) => {
116
+ const position =
117
+ as.position && typeof as.position === 'object'
118
+ ? (as.position as unknown as { x: number; y: number })
119
+ : { x: 0, y: 0 };
120
+ const posValue = tgtPos === 'x' ? position.x : position.y;
121
+
122
+ // Safely access width/height with proper type assertion
123
+ const asWithSize = as as unknown as { width?: number; height?: number };
124
+ const sizeValue = tgtSize === 'width' ? asWithSize.width || 0 : asWithSize.height || 0;
125
+
126
+ return posValue + sizeValue;
127
+ }),
128
+ );
60
129
 
61
130
  if (ass.length < 3) return;
62
131
 
63
132
  const boxPos = min;
64
133
  const boxSize = max - min;
65
- const sum = ass.reduce((acc, cur) => acc + cur[tgtSize], 0);
134
+ // Safely access size property with proper type assertion
135
+ const sum = ass.reduce((acc, cur) => {
136
+ const curWithSize = cur as unknown as { width?: number; height?: number };
137
+ const sizeValue = tgtSize === 'width' ? curWithSize.width || 0 : curWithSize.height || 0;
138
+ return acc + sizeValue;
139
+ }, 0);
66
140
  const remain = boxSize - sum;
67
141
  const unit = remain / (ass.length - 1);
68
142
 
69
143
  let prev = 0;
70
144
  changeSchemas(
71
145
  ass.map((as, index) => {
72
- prev += index === 0 ? 0 : ass[index - 1][tgtSize] + unit;
146
+ // Safely access size property of previous element with proper type assertion
147
+ const prevSize =
148
+ index === 0
149
+ ? 0
150
+ : (() => {
151
+ const prevAs = ass[index - 1] as unknown as { width?: number; height?: number };
152
+ return tgtSize === 'width' ? prevAs.width || 0 : prevAs.height || 0;
153
+ })();
154
+
155
+ prev += index === 0 ? 0 : prevSize + unit;
73
156
  const value = round(boxPos + prev, 2);
74
- return { key: `position.${tgtPos}`, value, schemaId: as.id };
157
+
158
+ // Safely access id with proper type assertion
159
+ const asWithId = as as unknown as { id: string };
160
+ return { key: `position.${tgtPos}`, value, schemaId: asWithId.id };
75
161
  }),
76
162
  );
77
163
  };
@@ -16,10 +16,10 @@ const ButtonGroupWidget = (props: PropPanelWidgetProps) => {
16
16
  const key = btn.key;
17
17
  const type = btn.type;
18
18
  const ids = activeElements.map((ae) => ae.id);
19
- const ass = schemas.filter((s) => ids.includes(s.id)) as SchemaForUI[];
19
+ const ass = schemas.filter((s) => ids.includes(s.id));
20
20
  changeSchemas(
21
- ass.map((s: Record<string, any>) => {
22
- const oldValue = s[key] ?? false;
21
+ ass.map((s: SchemaForUI) => {
22
+ const oldValue = Boolean((s as Record<string, unknown>)[key] ?? false);
23
23
  const newValue = type === 'boolean' ? !oldValue : btn.value;
24
24
  return { key, value: newValue, schemaId: s.id };
25
25
  }),
@@ -31,9 +31,12 @@ const ButtonGroupWidget = (props: PropPanelWidgetProps) => {
31
31
  const type = btn.type;
32
32
  let active = false;
33
33
  const ids = activeElements.map((ae) => ae.id);
34
- const ass = schemas.filter((s) => ids.includes(s.id)) as SchemaForUI[];
35
- ass.forEach((s: Record<string, any>) => {
36
- active = type === 'boolean' ? (s[key] ?? false) : s[key] === btn.value;
34
+ const ass = schemas.filter((s) => ids.includes(s.id));
35
+ ass.forEach((s: SchemaForUI) => {
36
+ // Cast schema to Record to safely access dynamic properties
37
+ const schemaRecord = s as Record<string, unknown>;
38
+ active =
39
+ type === 'boolean' ? Boolean(schemaRecord[key] ?? false) : schemaRecord[key] === btn.value;
37
40
  });
38
41
  return active;
39
42
  };
@@ -45,13 +48,13 @@ const ButtonGroupWidget = (props: PropPanelWidgetProps) => {
45
48
  const svgDataUrl = `data:image/svg+xml;utf8,${encodeURIComponent(
46
49
  replaceCurrentColor(svgString, token.colorText),
47
50
  )}`;
48
- return <img width={17} height={17} src={svgDataUrl} />;
51
+ return <img width={17} height={17} src={svgDataUrl} alt="" />;
49
52
  };
50
53
 
51
54
  return (
52
55
  <Form.Item>
53
56
  <Button.Group>
54
- {schema.buttons.map((btn: ButtonConfig, index: number) => {
57
+ {(schema.buttons as ButtonConfig[]).map((btn: ButtonConfig, index: number) => {
55
58
  const active = isActive(btn);
56
59
  return (
57
60
  <Button