@pdfme/ui 4.2.4-dev.3 → 4.2.4-dev.5
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.
- package/dist/index.es.js +3399 -3343
- package/dist/index.umd.js +96 -96
- package/dist/types/class.d.ts +3 -0
- package/dist/types/components/Designer/PluginIcon.d.ts +10 -0
- package/dist/types/components/Designer/RightSidebar/ListView/Item.d.ts +2 -0
- package/dist/types/contexts.d.ts +2 -1
- package/dist/types/helper.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/Designer/LeftSidebar.tsx +6 -14
- package/src/components/Designer/PluginIcon.tsx +47 -0
- package/src/components/Designer/RightSidebar/DetailView/index.tsx +6 -0
- package/src/components/Designer/RightSidebar/ListView/Item.tsx +6 -0
- package/src/components/Designer/RightSidebar/ListView/SelectableSortableContainer.tsx +25 -5
- package/src/components/Designer/RightSidebar/ListView/SelectableSortableItem.tsx +11 -1
- package/src/components/Designer/index.tsx +3 -1
- package/src/components/Renderer.tsx +10 -0
- package/src/helper.ts +4 -1
- package/src/i18n.ts +11 -0
package/dist/types/class.d.ts
CHANGED
@@ -37,6 +37,7 @@ export declare abstract class BaseUIClass {
|
|
37
37
|
rotate: import("zod").ZodOptional<import("zod").ZodNumber>;
|
38
38
|
opacity: import("zod").ZodOptional<import("zod").ZodNumber>;
|
39
39
|
readOnly: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
40
|
+
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
40
41
|
}, "passthrough", import("zod").ZodTypeAny, import("zod").objectOutputType<{
|
41
42
|
type: import("zod").ZodString;
|
42
43
|
content: import("zod").ZodOptional<import("zod").ZodString>;
|
@@ -55,6 +56,7 @@ export declare abstract class BaseUIClass {
|
|
55
56
|
rotate: import("zod").ZodOptional<import("zod").ZodNumber>;
|
56
57
|
opacity: import("zod").ZodOptional<import("zod").ZodNumber>;
|
57
58
|
readOnly: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
59
|
+
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
58
60
|
}, import("zod").ZodTypeAny, "passthrough">, import("zod").objectInputType<{
|
59
61
|
type: import("zod").ZodString;
|
60
62
|
content: import("zod").ZodOptional<import("zod").ZodString>;
|
@@ -73,6 +75,7 @@ export declare abstract class BaseUIClass {
|
|
73
75
|
rotate: import("zod").ZodOptional<import("zod").ZodNumber>;
|
74
76
|
opacity: import("zod").ZodOptional<import("zod").ZodNumber>;
|
75
77
|
readOnly: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
78
|
+
required: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
76
79
|
}, import("zod").ZodTypeAny, "passthrough">>>, "many">;
|
77
80
|
basePdf: import("zod").ZodUnion<[import("zod").ZodUnion<[import("zod").ZodString, import("zod").ZodType<ArrayBuffer, import("zod").ZodTypeDef, ArrayBuffer>, import("zod").ZodType<Uint8Array, import("zod").ZodTypeDef, Uint8Array>]>, import("zod").ZodObject<{
|
78
81
|
width: import("zod").ZodNumber;
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { Plugin } from "@pdfme/common";
|
3
|
+
interface PluginIconProps {
|
4
|
+
plugin: Plugin<any>;
|
5
|
+
label: string;
|
6
|
+
size?: number;
|
7
|
+
styles?: React.CSSProperties;
|
8
|
+
}
|
9
|
+
declare const PluginIcon: (props: PluginIconProps) => React.JSX.Element;
|
10
|
+
export default PluginIcon;
|
@@ -2,9 +2,11 @@ import React from 'react';
|
|
2
2
|
import { DraggableSyntheticListeners } from '@dnd-kit/core';
|
3
3
|
interface Props {
|
4
4
|
value: React.ReactNode;
|
5
|
+
icon?: React.ReactNode;
|
5
6
|
style?: React.CSSProperties;
|
6
7
|
status?: 'is-warning' | 'is-danger';
|
7
8
|
title?: string;
|
9
|
+
required?: boolean;
|
8
10
|
dragOverlay?: boolean;
|
9
11
|
onClick?: () => void;
|
10
12
|
onMouseEnter?: () => void;
|
package/dist/types/contexts.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/// <reference types="react" />
|
2
2
|
import { Plugins, UIOptions } from '@pdfme/common';
|
3
|
-
export declare const I18nContext: import("react").Context<(key: "type" | "width" | "height" | "rotate" | "opacity" | "cancel" | "field" | "fieldName" | "align" | "edit" | "plsInputName" | "fieldMustUniq" | "notUniq" | "noKeyName" | "fieldsList" | "editField" | "errorOccurred" | "errorBulkUpdateFieldName" | "commitBulkUpdateFieldName" | "bulkUpdateFieldName" | "addPageAfter" | "removePage" | "removePageConfirm" | "hexColorPrompt" | "schemas.color" | "schemas.borderWidth" | "schemas.borderColor" | "schemas.backgroundColor" | "schemas.textColor" | "schemas.bgColor" | "schemas.horizontal" | "schemas.vertical" | "schemas.left" | "schemas.center" | "schemas.right" | "schemas.top" | "schemas.middle" | "schemas.bottom" | "schemas.padding" | "schemas.text.fontName" | "schemas.text.size" | "schemas.text.spacing" | "schemas.text.textAlign" | "schemas.text.verticalAlign" | "schemas.text.lineHeight" | "schemas.text.min" | "schemas.text.max" | "schemas.text.fit" | "schemas.text.dynamicFontSize" | "schemas.text.format" | "schemas.mvt.typingInstructions" | "schemas.mvt.sampleField" | "schemas.mvt.variablesSampleData" | "schemas.barcodes.barColor" | "schemas.barcodes.includetext" | "schemas.table.alternateBackgroundColor" | "schemas.table.tableStyle" | "schemas.table.headStyle" | "schemas.table.bodyStyle" | "schemas.table.columnStyle", dict?: {
|
3
|
+
export declare const I18nContext: import("react").Context<(key: "type" | "width" | "height" | "rotate" | "opacity" | "required" | "cancel" | "field" | "fieldName" | "align" | "edit" | "plsInputName" | "fieldMustUniq" | "notUniq" | "noKeyName" | "fieldsList" | "editField" | "errorOccurred" | "errorBulkUpdateFieldName" | "commitBulkUpdateFieldName" | "bulkUpdateFieldName" | "addPageAfter" | "removePage" | "removePageConfirm" | "hexColorPrompt" | "schemas.color" | "schemas.borderWidth" | "schemas.borderColor" | "schemas.backgroundColor" | "schemas.textColor" | "schemas.bgColor" | "schemas.horizontal" | "schemas.vertical" | "schemas.left" | "schemas.center" | "schemas.right" | "schemas.top" | "schemas.middle" | "schemas.bottom" | "schemas.padding" | "schemas.text.fontName" | "schemas.text.size" | "schemas.text.spacing" | "schemas.text.textAlign" | "schemas.text.verticalAlign" | "schemas.text.lineHeight" | "schemas.text.min" | "schemas.text.max" | "schemas.text.fit" | "schemas.text.dynamicFontSize" | "schemas.text.format" | "schemas.mvt.typingInstructions" | "schemas.mvt.sampleField" | "schemas.mvt.variablesSampleData" | "schemas.barcodes.barColor" | "schemas.barcodes.includetext" | "schemas.table.alternateBackgroundColor" | "schemas.table.tableStyle" | "schemas.table.headStyle" | "schemas.table.bodyStyle" | "schemas.table.columnStyle", dict?: {
|
4
4
|
cancel: string;
|
5
5
|
field: string;
|
6
6
|
fieldName: string;
|
@@ -10,6 +10,7 @@ export declare const I18nContext: import("react").Context<(key: "type" | "width"
|
|
10
10
|
height: string;
|
11
11
|
rotate: string;
|
12
12
|
edit: string;
|
13
|
+
required: string;
|
13
14
|
plsInputName: string;
|
14
15
|
fieldMustUniq: string;
|
15
16
|
notUniq: string;
|
package/dist/types/helper.d.ts
CHANGED
@@ -36,6 +36,7 @@ export declare const template2SchemasList: (_template: Template) => Promise<{
|
|
36
36
|
key: string;
|
37
37
|
opacity?: number | undefined;
|
38
38
|
rotate?: number | undefined;
|
39
|
+
required?: boolean | undefined;
|
39
40
|
content?: string | undefined;
|
40
41
|
readOnly?: boolean | undefined;
|
41
42
|
}[][]>;
|
package/package.json
CHANGED
@@ -8,7 +8,8 @@ import { theme, Button } from 'antd';
|
|
8
8
|
import { useDraggable } from '@dnd-kit/core';
|
9
9
|
import { CSS } from "@dnd-kit/utilities";
|
10
10
|
import Renderer from '../Renderer';
|
11
|
-
import { PluginsRegistry
|
11
|
+
import { PluginsRegistry } from '../../contexts';
|
12
|
+
import PluginIcon from "./PluginIcon";
|
12
13
|
|
13
14
|
const Draggable = (props: { plugin: Plugin<any>, scale: number, basePdf: BasePdf, children: React.ReactNode }) => {
|
14
15
|
const { scale, basePdf, plugin } = props;
|
@@ -44,8 +45,6 @@ const Draggable = (props: { plugin: Plugin<any>, scale: number, basePdf: BasePdf
|
|
44
45
|
const LeftSidebar = ({ height, scale, basePdf }: { height: number, scale: number, basePdf: BasePdf }) => {
|
45
46
|
const { token } = theme.useToken();
|
46
47
|
const pluginsRegistry = useContext(PluginsRegistry);
|
47
|
-
const options = useContext(OptionsContext);
|
48
|
-
|
49
48
|
const [isDragging, setIsDragging] = useState(false);
|
50
49
|
|
51
50
|
useEffect(() => {
|
@@ -77,7 +76,6 @@ const LeftSidebar = ({ height, scale, basePdf }: { height: number, scale: number
|
|
77
76
|
>
|
78
77
|
{Object.entries(pluginsRegistry).map(([label, plugin]) => {
|
79
78
|
if (!plugin?.propPanel.defaultSchema) return null;
|
80
|
-
const icon = options.icons?.[plugin.propPanel.defaultSchema.type] ?? plugin.icon;
|
81
79
|
|
82
80
|
return <Draggable
|
83
81
|
key={label}
|
@@ -85,16 +83,10 @@ const LeftSidebar = ({ height, scale, basePdf }: { height: number, scale: number
|
|
85
83
|
basePdf={basePdf}
|
86
84
|
plugin={plugin}>
|
87
85
|
<Button
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
}}
|
92
|
-
style={{ width: 35, height: 35, marginTop: '0.25rem', padding: '0.25rem' }}>
|
93
|
-
{icon ?
|
94
|
-
<div dangerouslySetInnerHTML={{ __html: icon }} />
|
95
|
-
:
|
96
|
-
<div style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>{label}</div>
|
97
|
-
}
|
86
|
+
onMouseDown={() => setIsDragging(true)}
|
87
|
+
style={{ width: 35, height: 35, marginTop: '0.25rem', padding: '0.25rem' }}
|
88
|
+
>
|
89
|
+
<PluginIcon plugin={plugin} label={label} />
|
98
90
|
</Button>
|
99
91
|
</Draggable>
|
100
92
|
})}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import React, { useContext } from 'react';
|
2
|
+
import { Plugin } from "@pdfme/common";
|
3
|
+
import { OptionsContext } from '../../contexts';
|
4
|
+
|
5
|
+
interface PluginIconProps {
|
6
|
+
plugin: Plugin<any>;
|
7
|
+
label: string;
|
8
|
+
size?: number;
|
9
|
+
styles?: React.CSSProperties;
|
10
|
+
}
|
11
|
+
|
12
|
+
const getWithModifiedSize = (htmlString: string, label: string, size: number, styles?: React.CSSProperties) => {
|
13
|
+
const parser = new DOMParser();
|
14
|
+
const doc = parser.parseFromString(htmlString, 'text/html');
|
15
|
+
|
16
|
+
const modifyNode = (node: HTMLElement) => {
|
17
|
+
if (node.tagName === 'SVG' || node.tagName === 'svg') {
|
18
|
+
node.setAttribute('width', size.toString());
|
19
|
+
node.setAttribute('height', size.toString());
|
20
|
+
}
|
21
|
+
Array.from(node.children).forEach(child => modifyNode(child as HTMLElement));
|
22
|
+
};
|
23
|
+
|
24
|
+
Array.from(doc.body.children).forEach(child => modifyNode(child as HTMLElement));
|
25
|
+
|
26
|
+
return (
|
27
|
+
<div style={styles} title={label} dangerouslySetInnerHTML={{ __html: doc.body.innerHTML }} />
|
28
|
+
);
|
29
|
+
};
|
30
|
+
|
31
|
+
const PluginIcon = (props: PluginIconProps) => {
|
32
|
+
const { plugin, label, size, styles } = props;
|
33
|
+
const options = useContext(OptionsContext);
|
34
|
+
const icon = options.icons?.[plugin.propPanel.defaultSchema.type] ?? plugin.icon;
|
35
|
+
const iconStyles = { ...styles, display: 'flex', justifyContent: 'center' };
|
36
|
+
|
37
|
+
if (icon) {
|
38
|
+
if (size) {
|
39
|
+
return getWithModifiedSize(icon, label, size, iconStyles);
|
40
|
+
}
|
41
|
+
return <div style={iconStyles} title={label} dangerouslySetInnerHTML={{__html: icon}} />
|
42
|
+
}
|
43
|
+
|
44
|
+
return <div style={{...styles, overflow: 'hidden', fontSize: 10, }}>{label}</div>
|
45
|
+
};
|
46
|
+
|
47
|
+
export default PluginIcon;
|
@@ -65,6 +65,11 @@ const DetailView = (props: DetailViewProps) => {
|
|
65
65
|
values.x = values.position.x;
|
66
66
|
values.y = values.position.y;
|
67
67
|
delete values.position;
|
68
|
+
|
69
|
+
if (values.key !== (form.getValues() || {}).key) {
|
70
|
+
form.resetFields();
|
71
|
+
}
|
72
|
+
|
68
73
|
form.setValues(values);
|
69
74
|
|
70
75
|
}, [activeSchema, form]);
|
@@ -148,6 +153,7 @@ Check this document: https://pdfme.com/docs/custom-schemas`);
|
|
148
153
|
span: 12,
|
149
154
|
},
|
150
155
|
key: { title: i18n('fieldName'), type: 'string', required: true, span: 12 },
|
156
|
+
required: { title: i18n('required'), type: 'boolean', span: 8, hidden: defaultSchema?.readOnly },
|
151
157
|
'-': { type: 'void', widget: 'Divider' },
|
152
158
|
align: { title: i18n('align'), type: 'void', widget: 'AlignWidget' },
|
153
159
|
x: { title: 'X', type: 'number', widget: 'inputNumber', required: true, span: 8, min: 0 },
|
@@ -8,9 +8,11 @@ const { Text } = Typography;
|
|
8
8
|
|
9
9
|
interface Props {
|
10
10
|
value: React.ReactNode;
|
11
|
+
icon?: React.ReactNode;
|
11
12
|
style?: React.CSSProperties;
|
12
13
|
status?: 'is-warning' | 'is-danger';
|
13
14
|
title?: string;
|
15
|
+
required?: boolean;
|
14
16
|
dragOverlay?: boolean;
|
15
17
|
onClick?: () => void;
|
16
18
|
onMouseEnter?: () => void;
|
@@ -26,9 +28,11 @@ const Item = React.memo(
|
|
26
28
|
React.forwardRef<HTMLLIElement, Props>(
|
27
29
|
(
|
28
30
|
{
|
31
|
+
icon,
|
29
32
|
value,
|
30
33
|
status,
|
31
34
|
title,
|
35
|
+
required,
|
32
36
|
style,
|
33
37
|
dragOverlay,
|
34
38
|
onClick,
|
@@ -93,6 +97,7 @@ const Item = React.memo(
|
|
93
97
|
}}
|
94
98
|
icon={<HolderOutlined style={{ cursor: 'grab' }} />}
|
95
99
|
/>
|
100
|
+
{icon}
|
96
101
|
<Text
|
97
102
|
style={{
|
98
103
|
overflow: 'hidden',
|
@@ -111,6 +116,7 @@ const Item = React.memo(
|
|
111
116
|
{status === 'is-danger' ? i18n('notUniq') : ''}
|
112
117
|
</span>
|
113
118
|
)}
|
119
|
+
{required && <span style={{ color: 'red', marginLeft: '0.5rem' }}>*</span>}
|
114
120
|
</Text>
|
115
121
|
</div>
|
116
122
|
</li>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { useState } from 'react';
|
1
|
+
import React, { useState, useContext, ReactNode } from 'react';
|
2
2
|
import { createPortal } from 'react-dom';
|
3
3
|
import {
|
4
4
|
closestCorners,
|
@@ -17,9 +17,11 @@ import {
|
|
17
17
|
} from '@dnd-kit/sortable';
|
18
18
|
import { SchemaForUI } from '@pdfme/common';
|
19
19
|
import type { SidebarProps } from '../../../../types';
|
20
|
+
import { PluginsRegistry } from '../../../../contexts';
|
20
21
|
import Item from './Item';
|
21
22
|
import SelectableSortableItem from './SelectableSortableItem';
|
22
23
|
import { theme } from 'antd';
|
24
|
+
import PluginIcon from "../../PluginIcon";
|
23
25
|
|
24
26
|
const SelectableSortableContainer = (
|
25
27
|
props: Pick<
|
@@ -28,11 +30,11 @@ const SelectableSortableContainer = (
|
|
28
30
|
>
|
29
31
|
) => {
|
30
32
|
const { token } = theme.useToken();
|
31
|
-
|
32
33
|
const { schemas, onEdit, onSortEnd, hoveringSchemaId, onChangeHoveringSchemaId } = props;
|
33
34
|
const [selectedSchemas, setSelectedSchemas] = useState<SchemaForUI[]>([]);
|
34
|
-
const [
|
35
|
+
const [dragOverlaidItems, setClonedItems] = useState<SchemaForUI[] | null>(null);
|
35
36
|
const [activeId, setActiveId] = useState<string | null>(null);
|
37
|
+
const pluginsRegistry = useContext(PluginsRegistry);
|
36
38
|
const sensors = useSensors(
|
37
39
|
useSensor(PointerSensor, { activationConstraint: { distance: 15 } }),
|
38
40
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
@@ -56,6 +58,20 @@ const SelectableSortableContainer = (
|
|
56
58
|
}
|
57
59
|
};
|
58
60
|
|
61
|
+
const getPluginIcon = (inSchema: string|SchemaForUI): ReactNode => {
|
62
|
+
const thisSchema = (typeof inSchema === 'string') ? schemas.find((schema) => schema.id === inSchema) : inSchema;
|
63
|
+
|
64
|
+
const [pluginLabel, activePlugin] = Object.entries(pluginsRegistry).find(
|
65
|
+
([label, plugin]) => plugin?.propPanel.defaultSchema.type === thisSchema?.type
|
66
|
+
)!;
|
67
|
+
|
68
|
+
if (!activePlugin) {
|
69
|
+
return <></>
|
70
|
+
}
|
71
|
+
|
72
|
+
return <PluginIcon plugin={activePlugin} label={pluginLabel} size={20} styles={{marginRight: '0.5rem'}}/>
|
73
|
+
};
|
74
|
+
|
59
75
|
return (
|
60
76
|
<DndContext
|
61
77
|
sensors={sensors}
|
@@ -101,8 +117,8 @@ const SelectableSortableContainer = (
|
|
101
117
|
setActiveId(null);
|
102
118
|
}}
|
103
119
|
onDragCancel={() => {
|
104
|
-
if (
|
105
|
-
onSortEnd(
|
120
|
+
if (dragOverlaidItems) {
|
121
|
+
onSortEnd(dragOverlaidItems);
|
106
122
|
}
|
107
123
|
|
108
124
|
setActiveId(null);
|
@@ -139,7 +155,9 @@ const SelectableSortableContainer = (
|
|
139
155
|
<>
|
140
156
|
<ul style={{ margin: 0, padding: 0, listStyle: 'none' }}>
|
141
157
|
<Item
|
158
|
+
icon={getPluginIcon(activeId)}
|
142
159
|
value={schemas.find((schema) => schema.id === activeId)!.key}
|
160
|
+
required={schemas.find((schema) => schema.id === activeId)!.required}
|
143
161
|
style={{ background: token.colorPrimary }}
|
144
162
|
dragOverlay
|
145
163
|
/>
|
@@ -149,8 +167,10 @@ const SelectableSortableContainer = (
|
|
149
167
|
.filter((item) => item.id !== activeId)
|
150
168
|
.map((item) => (
|
151
169
|
<Item
|
170
|
+
icon={getPluginIcon(item)}
|
152
171
|
key={item.id}
|
153
172
|
value={item.key}
|
173
|
+
required={item.required}
|
154
174
|
style={{ background: token.colorPrimary }}
|
155
175
|
dragOverlay
|
156
176
|
/>
|
@@ -1,10 +1,11 @@
|
|
1
1
|
import React, { useContext } from 'react';
|
2
2
|
import { useSortable } from '@dnd-kit/sortable';
|
3
3
|
import { SchemaForUI } from '@pdfme/common';
|
4
|
-
import { I18nContext } from '../../../../contexts';
|
4
|
+
import { PluginsRegistry, I18nContext } from '../../../../contexts';
|
5
5
|
import Item from './Item';
|
6
6
|
import { useMountStatus } from '../../../../hooks';
|
7
7
|
import { theme } from 'antd';
|
8
|
+
import PluginIcon from "../../PluginIcon";
|
8
9
|
|
9
10
|
interface Props {
|
10
11
|
isSelected: boolean;
|
@@ -29,6 +30,7 @@ const SelectableSortableItem = ({
|
|
29
30
|
const { token } = theme.useToken();
|
30
31
|
|
31
32
|
const i18n = useContext(I18nContext);
|
33
|
+
const pluginsRegistry = useContext(PluginsRegistry);
|
32
34
|
const { setNodeRef, listeners, isDragging, isSorting, transform, transition } = useSortable({
|
33
35
|
id: schema.id,
|
34
36
|
});
|
@@ -40,6 +42,12 @@ const SelectableSortableItem = ({
|
|
40
42
|
onClick: (event: any) => onSelect(schema.id, event.shiftKey),
|
41
43
|
};
|
42
44
|
|
45
|
+
const [pluginLabel, thisPlugin] = Object.entries(pluginsRegistry).find(
|
46
|
+
([label, plugin]) => plugin?.propPanel.defaultSchema.type === schema.type
|
47
|
+
)!;
|
48
|
+
|
49
|
+
const iconStyles = { width: 20, marginRight: '0.5rem' };
|
50
|
+
|
43
51
|
let status: undefined | 'is-warning' | 'is-danger';
|
44
52
|
if (!schema.key) {
|
45
53
|
status = 'is-warning';
|
@@ -64,9 +72,11 @@ const SelectableSortableItem = ({
|
|
64
72
|
onMouseEnter={onMouseEnter}
|
65
73
|
onMouseLeave={onMouseLeave}
|
66
74
|
onClick={() => onEdit(schema.id)}
|
75
|
+
icon={thisPlugin && <PluginIcon plugin={thisPlugin} label={pluginLabel} size={20} styles={iconStyles}/>}
|
67
76
|
value={schema.key}
|
68
77
|
status={status}
|
69
78
|
title={title}
|
79
|
+
required={schema.required}
|
70
80
|
style={{ ...selectedStyle, ...style }}
|
71
81
|
dragging={isDragging}
|
72
82
|
sorting={isSorting}
|
@@ -15,7 +15,7 @@ import RightSidebar from './RightSidebar/index';
|
|
15
15
|
import LeftSidebar from './LeftSidebar';
|
16
16
|
import Canvas from './Canvas/index';
|
17
17
|
import { RULER_HEIGHT, RIGHT_SIDEBAR_WIDTH } from '../../constants';
|
18
|
-
import { I18nContext, PluginsRegistry } from '../../contexts';
|
18
|
+
import { I18nContext, OptionsContext, PluginsRegistry } from '../../contexts';
|
19
19
|
import {
|
20
20
|
schemasList2template,
|
21
21
|
uuid,
|
@@ -62,6 +62,7 @@ const TemplateEditor = ({
|
|
62
62
|
|
63
63
|
const i18n = useContext(I18nContext);
|
64
64
|
const pluginsRegistry = useContext(PluginsRegistry);
|
65
|
+
const options = useContext(OptionsContext);
|
65
66
|
|
66
67
|
const [hoveringSchemaId, setHoveringSchemaId] = useState<string | null>(null);
|
67
68
|
const [activeElements, setActiveElements] = useState<HTMLElement[]>([]);
|
@@ -171,6 +172,7 @@ const TemplateEditor = ({
|
|
171
172
|
x: ensureMiddleValue(paddingLeft, defaultSchema.position.x, pageSize.width - paddingRight - defaultSchema.width),
|
172
173
|
y: ensureMiddleValue(paddingTop, defaultSchema.position.y, pageSize.height - paddingBottom - defaultSchema.height),
|
173
174
|
},
|
175
|
+
required: defaultSchema.readOnly ? false : options.requiredByDefault || defaultSchema.required || false,
|
174
176
|
} as SchemaForUI;
|
175
177
|
|
176
178
|
if (defaultSchema.position.y === 0) {
|
package/src/helper.ts
CHANGED
@@ -448,7 +448,7 @@ const handleTypeChange = (
|
|
448
448
|
pluginsRegistry: Plugins
|
449
449
|
) => {
|
450
450
|
if (key !== 'type') return;
|
451
|
-
const keysToKeep = ['id', 'key', 'type', 'position'];
|
451
|
+
const keysToKeep = ['id', 'key', 'type', 'position', 'required'];
|
452
452
|
Object.keys(schema).forEach((key) => {
|
453
453
|
if (!keysToKeep.includes(key)) {
|
454
454
|
delete schema[key as keyof typeof schema];
|
@@ -463,6 +463,9 @@ const handleTypeChange = (
|
|
463
463
|
(schema as any)[key] = propPanel?.defaultSchema[key];
|
464
464
|
}
|
465
465
|
});
|
466
|
+
if (schema.readOnly) {
|
467
|
+
schema.required = false;
|
468
|
+
}
|
466
469
|
};
|
467
470
|
|
468
471
|
export const changeSchemas = (args: {
|
package/src/i18n.ts
CHANGED
@@ -10,6 +10,7 @@ const dictEn: { [key in keyof Dict]: string } = {
|
|
10
10
|
height: 'Height',
|
11
11
|
opacity: 'Opacity',
|
12
12
|
rotate: 'Rotate',
|
13
|
+
required: 'Required',
|
13
14
|
edit: 'Edit',
|
14
15
|
plsInputName: 'Please input name',
|
15
16
|
fieldMustUniq: 'Name of field is not unique',
|
@@ -74,6 +75,7 @@ const dictZh: { [key in keyof Dict]: string } = {
|
|
74
75
|
height: '高度',
|
75
76
|
opacity: '透明度',
|
76
77
|
rotate: '旋转',
|
78
|
+
required: '必需的',
|
77
79
|
edit: '编辑',
|
78
80
|
plsInputName: '请输入名称',
|
79
81
|
fieldMustUniq: '字段名称必须唯一',
|
@@ -137,6 +139,7 @@ const dictJa: { [key in keyof Dict]: string } = {
|
|
137
139
|
height: '高さ',
|
138
140
|
opacity: '不透明度',
|
139
141
|
rotate: '回転',
|
142
|
+
required: '必須',
|
140
143
|
edit: '編集する',
|
141
144
|
plsInputName: '項目名を入力してください',
|
142
145
|
fieldMustUniq: '他の入力項目名と被っています',
|
@@ -200,6 +203,7 @@ const dictKo: { [key in keyof Dict]: string } = {
|
|
200
203
|
height: '높이',
|
201
204
|
opacity: '투명도',
|
202
205
|
rotate: '회전',
|
206
|
+
required: '필수의',
|
203
207
|
edit: '편집',
|
204
208
|
plsInputName: '이름을 입력하세요',
|
205
209
|
fieldMustUniq: '필드 이름은 유일해야 합니다',
|
@@ -263,6 +267,7 @@ const dictAr: { [key in keyof Dict]: string } = {
|
|
263
267
|
height: 'الارتفاع',
|
264
268
|
opacity: 'الشفافية',
|
265
269
|
rotate: 'تدوير',
|
270
|
+
required: 'مطلوب',
|
266
271
|
edit: 'تعديل',
|
267
272
|
plsInputName: 'الرجاء إدخال الاسم',
|
268
273
|
fieldMustUniq: 'يجب أن يكون الحقل فريداً',
|
@@ -326,6 +331,7 @@ const dictTh: { [key in keyof Dict]: string } = {
|
|
326
331
|
height: 'ความสูง',
|
327
332
|
opacity: 'ความทึบ',
|
328
333
|
rotate: 'หมุน',
|
334
|
+
required: 'ที่จำเป็น',
|
329
335
|
edit: 'แก้ไข',
|
330
336
|
plsInputName: 'กรุณาใส่ชื่อ',
|
331
337
|
fieldMustUniq: 'ชื่อฟิลด์ต้องไม่ซ้ำกัน',
|
@@ -389,6 +395,7 @@ const dictIt: { [key in keyof Dict]: string } = {
|
|
389
395
|
height: 'Altezza',
|
390
396
|
opacity: 'Opacità',
|
391
397
|
rotate: 'Ruota',
|
398
|
+
required: 'Necessaria',
|
392
399
|
edit: 'Modifica',
|
393
400
|
plsInputName: 'Inserisci il nome per favore',
|
394
401
|
fieldMustUniq: 'Il nome del campo non è univoco',
|
@@ -454,6 +461,7 @@ const dictPl: { [key in keyof Dict]: string } = {
|
|
454
461
|
height: 'Wysokość',
|
455
462
|
opacity: 'przezroczystość',
|
456
463
|
rotate: 'Obrót',
|
464
|
+
required: 'Wymagany',
|
457
465
|
edit: 'Edytuj',
|
458
466
|
plsInputName: 'Wymagane wprowadzenie klucza pola',
|
459
467
|
fieldMustUniq: 'Klucz pola nie jest unikalny',
|
@@ -517,6 +525,7 @@ const dictDe: { [key in keyof Dict]: string } = {
|
|
517
525
|
height: 'Höhe',
|
518
526
|
opacity: 'Opazität',
|
519
527
|
rotate: 'Drehen',
|
528
|
+
required: 'Erforderlich',
|
520
529
|
edit: 'Bearbeiten',
|
521
530
|
plsInputName: 'Bitte geben Sie einen Namen ein',
|
522
531
|
fieldMustUniq: 'Feldname ist nicht eindeutig',
|
@@ -582,6 +591,7 @@ const dictEs: { [key in keyof Dict]: string } = {
|
|
582
591
|
height: 'Altura',
|
583
592
|
opacity: 'Opacidad',
|
584
593
|
rotate: 'Rotar',
|
594
|
+
required: 'Requerido',
|
585
595
|
edit: 'Editar',
|
586
596
|
plsInputName: 'Introduce el nombre',
|
587
597
|
fieldMustUniq: 'El nombre del campo no es único',
|
@@ -647,6 +657,7 @@ const dictFr: { [key in keyof Dict]: string } = {
|
|
647
657
|
height: 'Hauteur',
|
648
658
|
opacity: 'Opacité',
|
649
659
|
rotate: 'Rotation',
|
660
|
+
required: 'Requis',
|
650
661
|
edit: 'Éditer',
|
651
662
|
plsInputName: 'Veuillez saisir le nom',
|
652
663
|
fieldMustUniq:"Le nom du champ n'est pas unique",
|