@pdfme/ui 3.0.1 → 3.1.0-dev.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 (64) hide show
  1. package/__mocks__/assetsTransformer.js +7 -0
  2. package/__mocks__/pdfjs-dist.js +15 -0
  3. package/dist/__vite-browser-external-jWVCDlBL.js +4 -0
  4. package/dist/index.js +1115 -3
  5. package/dist/path2d-polyfill.esm-yIGK7UQJ.js +214 -0
  6. package/dist/style.css +1 -0
  7. package/dist/types/class.d.ts +3 -3
  8. package/dist/types/components/AppContextProvider.d.ts +11 -0
  9. package/dist/types/components/{CtlBar/index.d.ts → CtlBar.d.ts} +2 -2
  10. package/dist/types/components/Designer/Canvas/Selecto.d.ts +3 -2
  11. package/dist/types/components/Designer/Sidebar/DetailView/AlignWidget.d.ts +1 -1
  12. package/dist/types/components/Designer/Sidebar/ListView/SelectableSortableContainer.d.ts +1 -1
  13. package/dist/types/components/Renderer.d.ts +1 -1
  14. package/dist/types/components/UnitPager.d.ts +1 -1
  15. package/dist/types/constants.d.ts +1 -0
  16. package/dist/types/contexts.d.ts +46 -4
  17. package/dist/types/helper.d.ts +2 -1
  18. package/dist/types/hooks.d.ts +19 -2
  19. package/dist/types/i18n.d.ts +3 -27
  20. package/dist/types/theme.d.ts +2 -0
  21. package/package.json +17 -11
  22. package/src/Designer.tsx +27 -53
  23. package/src/Form.tsx +22 -23
  24. package/src/Viewer.tsx +10 -11
  25. package/src/class.ts +5 -5
  26. package/src/components/AppContextProvider.tsx +63 -0
  27. package/src/components/CtlBar.tsx +125 -0
  28. package/src/components/Designer/Canvas/Guides.tsx +18 -23
  29. package/src/components/Designer/Canvas/Mask.tsx +2 -1
  30. package/src/components/Designer/Canvas/Moveable.tsx +60 -60
  31. package/src/components/Designer/Canvas/Selecto.tsx +33 -20
  32. package/src/components/Designer/Canvas/index.tsx +21 -15
  33. package/src/components/Designer/Sidebar/DetailView/AlignWidget.tsx +53 -89
  34. package/src/components/Designer/Sidebar/DetailView/index.tsx +41 -30
  35. package/src/components/Designer/Sidebar/ListView/Item.tsx +30 -19
  36. package/src/components/Designer/Sidebar/ListView/SelectableSortableContainer.tsx +9 -6
  37. package/src/components/Designer/Sidebar/ListView/SelectableSortableItem.tsx +4 -1
  38. package/src/components/Designer/Sidebar/ListView/index.tsx +76 -71
  39. package/src/components/Designer/Sidebar/index.tsx +25 -49
  40. package/src/components/Designer/index.tsx +24 -82
  41. package/src/components/ErrorScreen.tsx +13 -11
  42. package/src/components/Preview.tsx +5 -2
  43. package/src/components/Renderer.tsx +10 -6
  44. package/src/components/Root.tsx +2 -8
  45. package/src/components/Spinner.tsx +12 -31
  46. package/src/components/UnitPager.tsx +72 -55
  47. package/src/constants.ts +2 -0
  48. package/src/contexts.ts +4 -5
  49. package/src/helper.ts +8 -5
  50. package/src/hooks.ts +136 -3
  51. package/src/i18n.ts +168 -59
  52. package/src/theme.ts +20 -0
  53. package/tsconfig.json +35 -13
  54. package/vite.config.ts +27 -0
  55. package/dist/index.js.LICENSE.txt +0 -142
  56. package/dist/index.js.map +0 -1
  57. package/dist/types/components/CtlBar/Pager.d.ts +0 -8
  58. package/dist/types/components/CtlBar/Zoom.d.ts +0 -7
  59. package/dist/types/components/Divider.d.ts +0 -3
  60. package/src/components/CtlBar/Pager.tsx +0 -53
  61. package/src/components/CtlBar/Zoom.tsx +0 -56
  62. package/src/components/CtlBar/index.tsx +0 -46
  63. package/src/components/Divider.tsx +0 -7
  64. package/webpack.config.js +0 -40
@@ -1,29 +1,42 @@
1
- import React from 'react';
1
+ import React, { useEffect } from 'react';
2
2
  import Selecto, { OnDragStart as _OnDragStart, OnSelect as _OnSelect } from 'react-selecto';
3
3
  import { SELECTABLE_CLASSNAME } from '../../../constants';
4
+ import { theme } from 'antd';
4
5
 
5
- const _Selecto = ({
6
- container,
7
- continueSelect,
8
- onDragStart,
9
- onSelect,
10
- }: {
6
+ type Props = {
11
7
  container: HTMLElement | null;
12
8
  continueSelect: boolean;
13
9
  onDragStart: (e: _OnDragStart) => void;
14
10
  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
- );
11
+ };
12
+
13
+ const className = 'pdfme-selecto';
14
+
15
+ const _Selecto = (props: Props) => {
16
+ const { token } = theme.useToken();
17
+ useEffect(() => {
18
+ const containerElement = document.querySelector('.' + className) as HTMLElement | null;
19
+ if (containerElement) {
20
+ containerElement.style.backgroundColor = token.colorPrimary;
21
+ containerElement.style.opacity = '0.75';
22
+ containerElement.style.borderColor = token.colorPrimaryBorder;
23
+ }
24
+ }, [props.container]);
25
+
26
+ return (
27
+ <Selecto
28
+ className={className}
29
+ selectFromInside={false}
30
+ selectByClick
31
+ preventDefault
32
+ hitRate={0}
33
+ selectableTargets={[`.${SELECTABLE_CLASSNAME}`]}
34
+ container={props.container}
35
+ continueSelect={props.continueSelect}
36
+ onDragStart={props.onDragStart}
37
+ onSelect={props.onSelect}
38
+ />
39
+ );
40
+ };
28
41
 
29
42
  export default _Selecto;
@@ -9,10 +9,11 @@ import React, {
9
9
  forwardRef,
10
10
  useCallback,
11
11
  } from 'react';
12
+ import { theme, Button } from 'antd';
12
13
  import { OnDrag, OnResize, OnClick, OnRotate } from 'react-moveable';
13
14
  import { ZOOM, SchemaForUI, Size, ChangeSchemas } from '@pdfme/common';
14
15
  import { PluginsRegistry } from '../../../contexts';
15
- import { XMarkIcon } from '@heroicons/react/24/outline';
16
+ import { CloseOutlined } from '@ant-design/icons';
16
17
  import { RULER_HEIGHT, SIDEBAR_WIDTH } from '../../../constants';
17
18
  import { usePrevious } from '../../../hooks';
18
19
  import { uuid, round, flatten } from '../../../helper';
@@ -30,33 +31,33 @@ const isTopLeftResize = (d: string) => d === '-1,-1' || d === '-1,0' || d === '0
30
31
  const normalizeRotate = (angle: number) => ((angle % 360) + 360) % 360;
31
32
 
32
33
  const DeleteButton = ({ activeElements: aes }: { activeElements: HTMLElement[] }) => {
34
+ const { token } = theme.useToken();
35
+
36
+ const size = 26;
33
37
  const top = Math.min(...aes.map(({ style }) => fmt4Num(style.top)));
34
38
  const left = Math.max(...aes.map(({ style }) => fmt4Num(style.left) + fmt4Num(style.width))) + 10;
35
39
 
36
40
  return (
37
- <button
41
+ <Button
38
42
  id={DELETE_BTN_ID}
39
43
  style={{
40
44
  position: 'absolute',
41
45
  zIndex: 1,
42
46
  top,
43
47
  left,
48
+ width: size,
49
+ height: size,
44
50
  padding: 2,
45
- height: 24,
46
- width: 24,
47
- cursor: 'pointer',
48
- color: 'white',
49
- border: 'none',
50
- fontWeight: 'bold',
51
- borderRadius: 2,
52
- background: 'rgb(68, 170, 255)',
53
51
  display: 'flex',
54
52
  alignItems: 'center',
55
53
  justifyContent: 'center',
54
+ borderRadius: token.borderRadius,
55
+ color: token.colorWhite,
56
+ background: token.colorPrimary,
56
57
  }}
57
58
  >
58
- <XMarkIcon style={{ pointerEvents: 'none' }} width={24} height={24} />
59
- </button>
59
+ <CloseOutlined style={{ pointerEvents: 'none' }} />
60
+ </Button>
60
61
  );
61
62
  };
62
63
 
@@ -103,6 +104,7 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
103
104
  paperRefs,
104
105
  sidebarOpen,
105
106
  } = props;
107
+ const { token } = theme.useToken();
106
108
  const pluginsRegistry = useContext(PluginsRegistry);
107
109
 
108
110
  const verticalGuides = useRef<GuidesInterface[]>([]);
@@ -258,10 +260,12 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
258
260
  );
259
261
  const schemaTypes = selectedSchemas.map((s) => s.type);
260
262
  const uniqueSchemaTypes = [...new Set(schemaTypes)];
261
- const defaultSchemas = Object.values(pluginsRegistry).map(plugin => plugin?.propPanel.defaultSchema)
263
+ const defaultSchemas = Object.values(pluginsRegistry).map(
264
+ (plugin) => plugin?.propPanel.defaultSchema
265
+ );
262
266
 
263
267
  return uniqueSchemaTypes.every(
264
- (type) => defaultSchemas.find(ds => ds.type === type)?.rotate !== undefined
268
+ (type) => defaultSchemas.find((ds) => ds.type === type)?.rotate !== undefined
265
269
  );
266
270
  }, [activeElements, pageCursor, schemasList, pluginsRegistry]);
267
271
 
@@ -378,7 +382,9 @@ const Canvas = (props: Props, ref: Ref<HTMLDivElement>) => {
378
382
  changeSchemas([{ key: 'data', value, schemaId: schema.id }]);
379
383
  }}
380
384
  stopEditing={() => setEditing(false)}
381
- outline={hoveringSchemaId === schema.id ? '1px solid #18a0fb' : '1px dashed #4af'}
385
+ outline={`1px ${hoveringSchemaId === schema.id ? 'solid' : 'dashed'} ${
386
+ token.colorPrimary
387
+ }`}
382
388
  scale={scale}
383
389
  />
384
390
  )}
@@ -13,12 +13,21 @@ const svgBaseProp = {
13
13
  fill: '#000000',
14
14
  };
15
15
 
16
- const AlignWidget = ({
17
- activeElements,
18
- changeSchemas,
19
- schemas,
20
- pageSize,
21
- }: PropPanelWidgetProps) => {
16
+ const createSvgIcon = (path: JSX.Element) => (
17
+ <svg {...svgBaseProp}>
18
+ <rect fill="none" height="24" width="24" />
19
+ {path}
20
+ </svg>
21
+ );
22
+
23
+ const createButtonConfig = (id: string, path: JSX.Element, onClick: () => void) => ({
24
+ id,
25
+ icon: createSvgIcon(path),
26
+ onClick,
27
+ });
28
+
29
+ const AlignWidget = (props: PropPanelWidgetProps) => {
30
+ const { activeElements, changeSchemas, schemas, pageSize, schema } = props;
22
31
  const align = (type: 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom') => {
23
32
  const ids = activeElements.map((ae) => ae.id);
24
33
  const ass = schemas.filter((s) => ids.includes(s.id));
@@ -79,92 +88,47 @@ const AlignWidget = ({
79
88
  })
80
89
  );
81
90
  };
82
-
83
- const layoutBtns: { id: string; icon: any; onClick: () => void }[] = [
84
- {
85
- id: 'left',
86
- icon: (
87
- <svg {...svgBaseProp}>
88
- <rect fill="none" height="24" width="24" />
89
- <path d="M4,22H2V2h2V22z M22,7H6v3h16V7z M16,14H6v3h10V14z" />
90
- </svg>
91
- ),
92
- onClick: () => align('left'),
93
- },
94
- {
95
- id: 'center',
96
- icon: (
97
- <svg {...svgBaseProp}>
98
- <rect fill="none" height="24" width="24" />
99
- <polygon points="11,2 13,2 13,7 21,7 21,10 13,10 13,14 18,14 18,17 13,17 13,22 11,22 11,17 6,17 6,14 11,14 11,10 3,10 3,7 11,7" />
100
- </svg>
101
- ),
102
- onClick: () => align('center'),
103
- },
104
- {
105
- id: 'right',
106
- icon: (
107
- <svg {...svgBaseProp}>
108
- <rect fill="none" height="24" width="24" />
109
- <path d="M20,2h2v20h-2V2z M2,10h16V7H2V10z M8,17h10v-3H8V17z" />
110
- </svg>
111
- ),
112
- onClick: () => align('right'),
113
- },
114
- {
115
- id: 'top',
116
- icon: (
117
- <svg {...svgBaseProp}>
118
- <rect fill="none" height="24" width="24" />
119
- <path d="M22,2v2H2V2H22z M7,22h3V6H7V22z M14,16h3V6h-3V16z" />
120
- </svg>
121
- ),
122
- onClick: () => align('top'),
123
- },
124
- {
125
- id: 'middle',
126
- icon: (
127
- <svg {...svgBaseProp}>
128
- <rect fill="none" height="24" width="24" />
129
- <polygon points="22,11 17,11 17,6 14,6 14,11 10,11 10,3 7,3 7,11 1.84,11 1.84,13 7,13 7,21 10,21 10,13 14,13 14,18 17,18 17,13 22,13" />
130
- </svg>
131
- ),
132
- onClick: () => align('middle'),
133
- },
134
- {
135
- id: 'bottom',
136
- icon: (
137
- <svg {...svgBaseProp}>
138
- <rect fill="none" height="24" width="24" />
139
- <path d="M22,22H2v-2h20V22z M10,2H7v16h3V2z M17,8h-3v10h3V8z" />
140
- </svg>
141
- ),
142
- onClick: () => align('bottom'),
143
- },
144
- {
145
- id: 'vertical',
146
- icon: (
147
- <svg {...svgBaseProp}>
148
- <rect fill="none" height="24" width="24" />
149
- <path d="M22,2v2H2V2H22z M7,10.5v3h10v-3H7z M2,20v2h20v-2H2z" />
150
- </svg>
151
- ),
152
- onClick: () => distribute('vertical'),
153
- },
154
- {
155
- id: 'horizontal',
156
- icon: (
157
- <svg {...svgBaseProp}>
158
- <rect fill="none" height="24" width="24" />
159
- <path d="M4,22H2V2h2V22z M22,2h-2v20h2V2z M13.5,7h-3v10h3V7z" />
160
- </svg>
161
- ),
162
- onClick: () => distribute('horizontal'),
163
- },
91
+ const layoutBtns = [
92
+ createButtonConfig('left', <path d="M4,22H2V2h2V22z M22,7H6v3h16V7z M16,14H6v3h10V14z" />, () =>
93
+ align('left')
94
+ ),
95
+ createButtonConfig(
96
+ 'center',
97
+ <polygon points="11,2 13,2 13,7 21,7 21,10 13,10 13,14 18,14 18,17 13,17 13,22 11,22 11,17 6,17 6,14 11,14 11,10 3,10 3,7 11,7" />,
98
+ () => align('center')
99
+ ),
100
+ createButtonConfig(
101
+ 'right',
102
+ <path d="M20,2h2v20h-2V2z M2,10h16V7H2V10z M8,17h10v-3H8V17z" />,
103
+ () => align('right')
104
+ ),
105
+ createButtonConfig('top', <path d="M22,2v2H2V2H22z M7,22h3V6H7V22z M14,16h3V6h-3V16z" />, () =>
106
+ align('top')
107
+ ),
108
+ createButtonConfig(
109
+ 'middle',
110
+ <polygon points="22,11 17,11 17,6 14,6 14,11 10,11 10,3 7,3 7,11 1.84,11 1.84,13 7,13 7,21 10,21 10,13 14,13 14,18 17,18 17,13 22,13" />,
111
+ () => align('middle')
112
+ ),
113
+ createButtonConfig(
114
+ 'bottom',
115
+ <path d="M22,22H2v-2h20V22z M10,2H7v16h3V2z M17,8h-3v10h3V8z" />,
116
+ () => align('bottom')
117
+ ),
118
+ createButtonConfig(
119
+ 'vertical',
120
+ <path d="M22,2v2H2V2H22z M7,10.5v3h10v-3H7z M2,20v2h20v-2H2z" />,
121
+ () => distribute('vertical')
122
+ ),
123
+ createButtonConfig(
124
+ 'horizontal',
125
+ <path d="M4,22H2V2h2V22z M22,2h-2v20h2V2z M13.5,7h-3v10h3V7z" />,
126
+ () => distribute('horizontal')
127
+ ),
164
128
  ];
165
129
 
166
130
  return (
167
- <Form.Item label="Align">
131
+ <Form.Item label={schema.title}>
168
132
  <Button.Group>
169
133
  {layoutBtns.map((btn) => (
170
134
  <Button
@@ -1,14 +1,16 @@
1
1
  import FormRender, { useForm } from 'form-render';
2
2
  import React, { useContext, useEffect, useState } from 'react';
3
- import type { SchemaForUI, PropPanelWidgetProps, PropPanelSchema } from '@pdfme/common';
3
+ import type { Dict, SchemaForUI, PropPanelWidgetProps, PropPanelSchema } from '@pdfme/common';
4
4
  import type { SidebarProps } from '../../../../types';
5
- import { Bars3Icon } from '@heroicons/react/20/solid';
5
+ import { MenuOutlined } from '@ant-design/icons';
6
6
  import { I18nContext, PluginsRegistry, OptionsContext } from '../../../../contexts';
7
- import { RULER_HEIGHT } from '../../../../constants';
8
- import Divider from '../../../Divider';
7
+ import { getSidebarContentHeight } from '../../../../helper';
8
+ import { theme, Typography, Button, Divider } from 'antd';
9
9
  import AlignWidget from './AlignWidget';
10
10
  import WidgetRenderer from './WidgetRenderer';
11
11
 
12
+ const { Text } = Typography;
13
+
12
14
  const DetailView = (
13
15
  props: Pick<
14
16
  SidebarProps,
@@ -17,6 +19,8 @@ const DetailView = (
17
19
  activeSchema: SchemaForUI;
18
20
  }
19
21
  ) => {
22
+ const { token } = theme.useToken();
23
+
20
24
  const { size, changeSchemas, deselectSchema, activeSchema, activeElements } = props;
21
25
  const form = useForm();
22
26
 
@@ -31,18 +35,27 @@ const DetailView = (
31
35
  useEffect(() => {
32
36
  const newWidgets: typeof widgets = {
33
37
  AlignWidget: (p) => <AlignWidget {...p} {...props} options={options} />,
34
- Divider,
38
+ Divider: () => (
39
+ <Divider style={{ marginTop: token.marginXS, marginBottom: token.marginXS }} />
40
+ ),
35
41
  };
36
42
  for (const plugin of Object.values(pluginsRegistry)) {
37
43
  const widgets = plugin?.propPanel.widgets || {};
38
44
  Object.entries(widgets).forEach(([widgetKey, widgetValue]) => {
39
45
  newWidgets[widgetKey] = (p) => (
40
- <WidgetRenderer {...p} {...props} options={options} widget={widgetValue} />
46
+ <WidgetRenderer
47
+ {...p}
48
+ {...props}
49
+ options={options}
50
+ theme={token}
51
+ i18n={i18n as (key: keyof Dict | string) => string}
52
+ widget={widgetValue}
53
+ />
41
54
  );
42
55
  });
43
56
  }
44
57
  setWidgets(newWidgets);
45
- }, [activeSchema, activeElements, pluginsRegistry]);
58
+ }, [activeSchema, activeElements, pluginsRegistry, JSON.stringify(options)]);
46
59
 
47
60
  useEffect(() => {
48
61
  form.setValues({ ...activeSchema });
@@ -76,7 +89,7 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
76
89
  column: 2,
77
90
  properties: {
78
91
  type: {
79
- title: 'Type',
92
+ title: i18n('type'),
80
93
  type: 'string',
81
94
  widget: 'select',
82
95
  props: {
@@ -86,9 +99,9 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
86
99
  })),
87
100
  },
88
101
  },
89
- key: { title: 'Name', type: 'string', widget: 'input' },
102
+ key: { title: i18n('fieldName'), type: 'string', widget: 'input' },
90
103
  '-': { type: 'void', widget: 'Divider', cellSpan: 2 },
91
- align: { title: 'Align', type: 'void', widget: 'AlignWidget', cellSpan: 2 },
104
+ align: { title: i18n('align'), type: 'void', widget: 'AlignWidget', cellSpan: 2 },
92
105
  position: {
93
106
  type: 'object',
94
107
  widget: 'card',
@@ -97,10 +110,10 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
97
110
  y: { title: 'Y', type: 'number', widget: 'inputNumber' },
98
111
  },
99
112
  },
100
- width: { title: 'Width', type: 'number', widget: 'inputNumber', span: 8 },
101
- height: { title: 'Height', type: 'number', widget: 'inputNumber', span: 8 },
113
+ width: { title: i18n('width'), type: 'number', widget: 'inputNumber', span: 8 },
114
+ height: { title: i18n('height'), type: 'number', widget: 'inputNumber', span: 8 },
102
115
  rotate: {
103
- title: 'Rotate',
116
+ title: i18n('rotate'),
104
117
  type: 'number',
105
118
  widget: 'inputNumber',
106
119
  span: 8,
@@ -112,7 +125,13 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
112
125
  };
113
126
 
114
127
  if (typeof activePropPanelSchema === 'function') {
115
- const apps = activePropPanelSchema({ ...props, options }) || {};
128
+ const apps =
129
+ activePropPanelSchema({
130
+ ...props,
131
+ options,
132
+ theme: token,
133
+ i18n: i18n as (key: keyof Dict | string) => string,
134
+ }) || {};
116
135
  propPanelSchema.properties = {
117
136
  ...propPanelSchema.properties,
118
137
  ...(Object.keys(apps).length === 0
@@ -134,36 +153,28 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
134
153
  return (
135
154
  <div>
136
155
  <div style={{ height: 40, display: 'flex', alignItems: 'center' }}>
137
- <span
156
+ <Button
138
157
  style={{
139
158
  position: 'absolute',
140
- top: '0.85rem',
141
159
  zIndex: 100,
142
- border: 'none',
143
- borderRadius: 2,
144
- padding: '0.5rem',
145
- cursor: 'pointer',
146
- background: '#eee',
147
160
  display: 'flex',
148
161
  alignItems: 'center',
149
162
  justifyContent: 'center',
150
- maxWidth: 30,
151
- maxHeight: 30,
152
163
  }}
153
164
  onClick={deselectSchema}
154
- >
155
- <Bars3Icon width={15} height={15} />
156
- </span>
157
- <span style={{ textAlign: 'center', width: '100%', fontWeight: 'bold' }}>
165
+ icon={<MenuOutlined />}
166
+ />
167
+ <Text strong style={{ textAlign: 'center', width: '100%' }}>
158
168
  {i18n('editField')}
159
- </span>
169
+ </Text>
160
170
  </div>
161
- <Divider />
171
+ <Divider style={{ marginTop: token.marginXS, marginBottom: token.marginXS }} />
162
172
  <div
163
173
  style={{
164
- height: size.height - RULER_HEIGHT - RULER_HEIGHT / 2 - 145,
174
+ height: getSidebarContentHeight(size.height),
165
175
  overflowY: 'auto',
166
176
  overflowX: 'hidden',
177
+ borderBottom: `1px solid ${token.colorSplit}`,
167
178
  }}
168
179
  >
169
180
  <FormRender
@@ -1,7 +1,10 @@
1
1
  import React, { useEffect, useContext } from 'react';
2
2
  import { DraggableSyntheticListeners } from '@dnd-kit/core';
3
3
  import { I18nContext } from '../../../../contexts';
4
- import { ExclamationTriangleIcon } from '@heroicons/react/24/outline';
4
+ import { HolderOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
5
+ import { Button, Typography } from 'antd';
6
+
7
+ const { Text } = Typography;
5
8
 
6
9
  interface Props {
7
10
  value: React.ReactNode;
@@ -60,6 +63,7 @@ const Item = React.memo(
60
63
  return (
61
64
  <li
62
65
  style={{
66
+ marginTop: 10,
63
67
  transition,
64
68
  transform: `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`,
65
69
  }}
@@ -67,40 +71,47 @@ const Item = React.memo(
67
71
  onMouseLeave={onMouseLeave}
68
72
  ref={ref}
69
73
  >
70
- <div style={{ display: 'flex', alignItems: 'center', ...style }} {...props}>
71
- <button
74
+ <div
75
+ style={{
76
+ display: 'flex',
77
+ alignItems: 'center',
78
+ cursor: 'pointer',
79
+ ...style,
80
+ }}
81
+ {...props}
82
+ onClick={() => onClick && onClick()}
83
+ >
84
+ <Button
72
85
  {...listeners}
73
- style={{ padding: '0.5rem', background: 'none', border: 'none', display: 'flex' }}
74
- >
75
- <object style={{ cursor: 'grab', marginTop: 6 }} width={15}>
76
- <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="16" height="16">
77
- <path d="M10 13a1 1 0 100-2 1 1 0 000 2zm-4 0a1 1 0 100-2 1 1 0 000 2zm1-5a1 1 0 11-2 0 1 1 0 012 0zm3 1a1 1 0 100-2 1 1 0 000 2zm1-5a1 1 0 11-2 0 1 1 0 012 0zM6 5a1 1 0 100-2 1 1 0 000 2z"></path>
78
- </svg>
79
- </object>
80
- </button>
81
- <div
82
86
  style={{
83
- width: '100%',
84
- padding: '0.5rem',
85
- paddingLeft: 0,
86
- cursor: 'pointer',
87
+ display: 'flex',
88
+ alignItems: 'center',
89
+ background: 'none',
90
+ boxShadow: 'none',
91
+ border: 'none',
92
+ paddingLeft: '0.25rem',
93
+ }}
94
+ icon={<HolderOutlined style={{ cursor: 'grab' }} />}
95
+ />
96
+ <Text
97
+ style={{
87
98
  overflow: 'hidden',
88
99
  whiteSpace: 'nowrap',
89
100
  textOverflow: 'ellipsis',
101
+ width: '100%',
90
102
  }}
91
103
  title={title || ''}
92
- onClick={() => onClick && onClick()}
93
104
  >
94
105
  {status === undefined ? (
95
106
  value
96
107
  ) : (
97
108
  <span style={{ display: 'flex', alignItems: 'center' }}>
98
- <ExclamationTriangleIcon width={15} style={{ marginRight: '0.5rem' }} />
109
+ <ExclamationCircleOutlined width={15} style={{ marginRight: '0.5rem' }} />
99
110
  {status === 'is-warning' ? i18n('noKeyName') : value}
100
111
  {status === 'is-danger' ? i18n('notUniq') : ''}
101
112
  </span>
102
113
  )}
103
- </div>
114
+ </Text>
104
115
  </div>
105
116
  </li>
106
117
  );
@@ -19,14 +19,17 @@ import { SchemaForUI } from '@pdfme/common';
19
19
  import type { SidebarProps } from '../../../../types';
20
20
  import Item from './Item';
21
21
  import SelectableSortableItem from './SelectableSortableItem';
22
+ import { theme } from 'antd';
22
23
 
23
24
  const SelectableSortableContainer = (
24
25
  props: Pick<
25
26
  SidebarProps,
26
- 'schemas' | 'onEdit' | 'onSortEnd' | 'height' | 'hoveringSchemaId' | 'onChangeHoveringSchemaId'
27
+ 'schemas' | 'onEdit' | 'onSortEnd' | 'hoveringSchemaId' | 'onChangeHoveringSchemaId'
27
28
  >
28
29
  ) => {
29
- const { schemas, onEdit, onSortEnd, height, hoveringSchemaId, onChangeHoveringSchemaId } = props;
30
+ const { token } = theme.useToken();
31
+
32
+ const { schemas, onEdit, onSortEnd, hoveringSchemaId, onChangeHoveringSchemaId } = props;
30
33
  const [selectedSchemas, setSelectedSchemas] = useState<SchemaForUI[]>([]);
31
34
  const [dragOverlaydItems, setClonedItems] = useState<SchemaForUI[] | null>(null);
32
35
  const [activeId, setActiveId] = useState<string | null>(null);
@@ -107,7 +110,7 @@ const SelectableSortableContainer = (
107
110
  }}
108
111
  >
109
112
  <>
110
- <div style={{ height, overflowY: 'auto' }}>
113
+ <div style={{ height: '100%', overflowY: 'auto' }}>
111
114
  <SortableContext items={schemas} strategy={verticalListSortingStrategy}>
112
115
  <ul style={{ margin: 0, padding: 0, listStyle: 'none', borderRadius: 5 }}>
113
116
  {schemas.map((schema) => (
@@ -115,7 +118,7 @@ const SelectableSortableContainer = (
115
118
  key={schema.id}
116
119
  style={{
117
120
  border: `1px solid ${
118
- schema.id === hoveringSchemaId ? '#18a0fb' : 'transparent'
121
+ schema.id === hoveringSchemaId ? token.colorPrimary : 'transparent'
119
122
  }`,
120
123
  }}
121
124
  schema={schema}
@@ -137,7 +140,7 @@ const SelectableSortableContainer = (
137
140
  <ul style={{ margin: 0, padding: 0, listStyle: 'none' }}>
138
141
  <Item
139
142
  value={schemas.find((schema) => schema.id === activeId)!.key}
140
- style={{ color: '#fff', background: '#18a0fb' }}
143
+ style={{ background: token.colorPrimary }}
141
144
  dragOverlay
142
145
  />
143
146
  </ul>
@@ -148,7 +151,7 @@ const SelectableSortableContainer = (
148
151
  <Item
149
152
  key={item.id}
150
153
  value={item.key}
151
- style={{ color: '#fff', background: '#18a0fb' }}
154
+ style={{ background: token.colorPrimary }}
152
155
  dragOverlay
153
156
  />
154
157
  ))}
@@ -4,6 +4,7 @@ import { SchemaForUI } from '@pdfme/common';
4
4
  import { I18nContext } from '../../../../contexts';
5
5
  import Item from './Item';
6
6
  import { useMountStatus } from '../../../../hooks';
7
+ import { theme } from 'antd';
7
8
 
8
9
  interface Props {
9
10
  isSelected: boolean;
@@ -25,6 +26,8 @@ const SelectableSortableItem = ({
25
26
  onMouseEnter,
26
27
  onMouseLeave,
27
28
  }: Props) => {
29
+ const { token } = theme.useToken();
30
+
28
31
  const i18n = useContext(I18nContext);
29
32
  const { setNodeRef, listeners, isDragging, isSorting, transform, transition } = useSortable({
30
33
  id: schema.id,
@@ -52,7 +55,7 @@ const SelectableSortableItem = ({
52
55
  }
53
56
 
54
57
  const selectedStyle = isSelected
55
- ? { color: '#fff', background: '#18a0fb', opacity: isSorting || isDragging ? 0.5 : 1 }
58
+ ? { background: token.colorPrimary, opacity: isSorting || isDragging ? 0.5 : 1 }
56
59
  : ({} as React.CSSProperties);
57
60
 
58
61
  return (