1 |
|
2 |
|
3 |
|
4 |
|
5 | import { nullTranslator } from '@jupyterlab/translation';
|
6 | import { JSONExt } from '@lumino/coreutils';
|
7 | import Form from '@rjsf/core';
|
8 | import { ADDITIONAL_PROPERTY_FLAG, canExpand, getTemplate } from '@rjsf/utils';
|
9 | import React from 'react';
|
10 | import { addIcon, caretDownIcon, caretUpIcon, closeIcon } from '../icon';
|
11 |
|
12 |
|
13 |
|
14 | export const DEFAULT_UI_OPTIONS = {
|
15 | |
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | submitButtonOptions: {
|
22 | norender: true
|
23 | }
|
24 | };
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | export const MoveButton = (props) => {
|
31 | var _a;
|
32 | const trans = ((_a = props.translator) !== null && _a !== void 0 ? _a : nullTranslator).load('jupyterlab');
|
33 | let buttonContent;
|
34 | |
35 |
|
36 |
|
37 | const disabled = () => {
|
38 | if (props.direction === 'up') {
|
39 | return !props.item.hasMoveUp;
|
40 | }
|
41 | else {
|
42 | return !props.item.hasMoveDown;
|
43 | }
|
44 | };
|
45 | if (props.buttonStyle === 'icons') {
|
46 | const iconProps = {
|
47 | tag: 'span',
|
48 | elementSize: 'xlarge',
|
49 | elementPosition: 'center'
|
50 | };
|
51 | buttonContent =
|
52 | props.direction === 'up' ? (React.createElement(caretUpIcon.react, { ...iconProps })) : (React.createElement(caretDownIcon.react, { ...iconProps }));
|
53 | }
|
54 | else {
|
55 | buttonContent =
|
56 | props.direction === 'up' ? trans.__('Move up') : trans.__('Move down');
|
57 | }
|
58 | const moveTo = props.direction === 'up' ? props.item.index - 1 : props.item.index + 1;
|
59 | return (React.createElement("button", { className: "jp-mod-styled jp-mod-reject jp-ArrayOperationsButton", onClick: props.item.onReorderClick(props.item.index, moveTo), disabled: disabled() }, buttonContent));
|
60 | };
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 | export const DropButton = (props) => {
|
67 | var _a;
|
68 | const trans = ((_a = props.translator) !== null && _a !== void 0 ? _a : nullTranslator).load('jupyterlab');
|
69 | let buttonContent;
|
70 | if (props.buttonStyle === 'icons') {
|
71 | buttonContent = (React.createElement(closeIcon.react, { tag: "span", elementSize: "xlarge", elementPosition: "center" }));
|
72 | }
|
73 | else {
|
74 | buttonContent = trans.__('Remove');
|
75 | }
|
76 | return (React.createElement("button", { className: "jp-mod-styled jp-mod-warn jp-ArrayOperationsButton", onClick: props.item.onDropIndexClick(props.item.index) }, buttonContent));
|
77 | };
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 | export const AddButton = (props) => {
|
84 | var _a;
|
85 | const trans = ((_a = props.translator) !== null && _a !== void 0 ? _a : nullTranslator).load('jupyterlab');
|
86 | let buttonContent;
|
87 | if (props.buttonStyle === 'icons') {
|
88 | buttonContent = (React.createElement(addIcon.react, { tag: "span", elementSize: "xlarge", elementPosition: "center" }));
|
89 | }
|
90 | else {
|
91 | buttonContent = trans.__('Add');
|
92 | }
|
93 | return (React.createElement("button", { className: "jp-mod-styled jp-mod-reject jp-ArrayOperationsButton", onClick: props.onAddClick }, buttonContent));
|
94 | };
|
95 | function customizeForLab(options) {
|
96 | const { component, name, buttonStyle, compact, showModifiedFromDefault, translator } = options;
|
97 | const isCompact = compact !== null && compact !== void 0 ? compact : false;
|
98 | const button = buttonStyle !== null && buttonStyle !== void 0 ? buttonStyle : (isCompact ? 'icons' : 'text');
|
99 | const factory = (props) => component({
|
100 | ...props,
|
101 | buttonStyle: button,
|
102 | compact: isCompact,
|
103 | showModifiedFromDefault: showModifiedFromDefault !== null && showModifiedFromDefault !== void 0 ? showModifiedFromDefault : true,
|
104 | translator: translator !== null && translator !== void 0 ? translator : nullTranslator
|
105 | });
|
106 | if (name) {
|
107 | factory.displayName = name;
|
108 | }
|
109 | return factory;
|
110 | }
|
111 |
|
112 |
|
113 |
|
114 | function getTemplates(registry, uiSchema) {
|
115 | const TitleField = getTemplate('TitleFieldTemplate', registry, uiSchema);
|
116 | const DescriptionField = getTemplate('DescriptionFieldTemplate', registry, uiSchema);
|
117 | return { TitleField, DescriptionField };
|
118 | }
|
119 |
|
120 |
|
121 |
|
122 |
|
123 | const CustomArrayTemplateFactory = (options) => customizeForLab({
|
124 | ...options,
|
125 | name: 'JupyterLabArrayTemplate',
|
126 | component: props => {
|
127 | var _a;
|
128 | const { schema, registry, uiSchema, required } = props;
|
129 | const commonProps = { schema, registry, uiSchema, required };
|
130 | const { TitleField, DescriptionField } = getTemplates(registry, uiSchema);
|
131 | return (React.createElement("div", { className: props.className },
|
132 | props.compact ? (React.createElement("div", { className: "jp-FormGroup-compactTitle" },
|
133 | React.createElement("div", { className: "jp-FormGroup-fieldLabel jp-FormGroup-contentItem", id: `${props.idSchema.$id}__title` }, props.title || ''),
|
134 | React.createElement("div", { className: "jp-FormGroup-description", id: `${props.idSchema.$id}-description` }, props.schema.description || ''))) : (React.createElement(React.Fragment, null,
|
135 | props.title && (React.createElement(TitleField, { ...commonProps, title: props.title, id: `${props.idSchema.$id}-title` })),
|
136 | React.createElement(DescriptionField, { ...commonProps, id: `${props.idSchema.$id}-description`, description: (_a = props.schema.description) !== null && _a !== void 0 ? _a : '' }))),
|
137 | props.items.map(item => {
|
138 | return (React.createElement("div", { key: item.key, className: item.className },
|
139 | item.children,
|
140 | React.createElement("div", { className: "jp-ArrayOperations" },
|
141 | React.createElement(MoveButton, { buttonStyle: props.buttonStyle, translator: props.translator, item: item, direction: "up" }),
|
142 | React.createElement(MoveButton, { buttonStyle: props.buttonStyle, translator: props.translator, item: item, direction: "down" }),
|
143 | React.createElement(DropButton, { buttonStyle: props.buttonStyle, translator: props.translator, item: item }))));
|
144 | }),
|
145 | props.canAdd && (React.createElement(AddButton, { onAddClick: props.onAddClick, buttonStyle: props.buttonStyle, translator: props.translator }))));
|
146 | }
|
147 | });
|
148 |
|
149 |
|
150 |
|
151 | const CustomObjectTemplateFactory = (options) => customizeForLab({
|
152 | ...options,
|
153 | name: 'JupyterLabObjectTemplate',
|
154 | component: props => {
|
155 | var _a;
|
156 | const { schema, registry, uiSchema, required } = props;
|
157 | const commonProps = { schema, registry, uiSchema, required };
|
158 | const { TitleField, DescriptionField } = getTemplates(registry, uiSchema);
|
159 | return (React.createElement("fieldset", { id: props.idSchema.$id },
|
160 | props.compact ? (React.createElement("div", { className: "jp-FormGroup-compactTitle" },
|
161 | React.createElement("div", { className: "jp-FormGroup-fieldLabel jp-FormGroup-contentItem", id: `${props.idSchema.$id}__title` }, props.title || ''),
|
162 | React.createElement("div", { className: "jp-FormGroup-description", id: `${props.idSchema.$id}__description` }, props.schema.description || ''))) : (React.createElement(React.Fragment, null,
|
163 | (props.title ||
|
164 | (props.uiSchema || JSONExt.emptyObject)['ui:title']) && (React.createElement(TitleField, { ...commonProps, id: `${props.idSchema.$id}__title`, title: props.title ||
|
165 | `${(props.uiSchema || JSONExt.emptyObject)['ui:title']}` ||
|
166 | '' })),
|
167 | React.createElement(DescriptionField, { ...commonProps, id: `${props.idSchema.$id}__description`, description: (_a = props.schema.description) !== null && _a !== void 0 ? _a : '' }))),
|
168 | props.properties.map(property => property.content),
|
169 | canExpand(props.schema, props.uiSchema, props.formData) && (React.createElement(AddButton, { onAddClick: props.onAddClick(props.schema), buttonStyle: props.buttonStyle, translator: props.translator }))));
|
170 | }
|
171 | });
|
172 |
|
173 |
|
174 |
|
175 | const CustomTemplateFactory = (options) => customizeForLab({
|
176 | ...options,
|
177 | name: 'JupyterLabFieldTemplate',
|
178 | component: props => {
|
179 | var _a;
|
180 | const trans = ((_a = props.translator) !== null && _a !== void 0 ? _a : nullTranslator).load('jupyterlab');
|
181 | let isModified = false;
|
182 | let defaultValue;
|
183 | const { formData, schema, label, displayLabel, id, formContext, errors, rawErrors, children, onKeyChange, onDropPropertyClick } = props;
|
184 | const { defaultFormData } = formContext;
|
185 | const schemaIds = id.split('_');
|
186 | schemaIds.shift();
|
187 | const schemaId = schemaIds.join('.');
|
188 | const isRoot = schemaId === '';
|
189 | const hasCustomField = schemaId === (props.uiSchema || JSONExt.emptyObject)['ui:field'];
|
190 | if (props.showModifiedFromDefault) {
|
191 | |
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 | defaultValue = schemaIds.reduce((acc, key) => acc === null || acc === void 0 ? void 0 : acc[key], defaultFormData);
|
198 | isModified =
|
199 | !isRoot &&
|
200 | formData !== undefined &&
|
201 | defaultValue !== undefined &&
|
202 | !schema.properties &&
|
203 | schema.type !== 'array' &&
|
204 | !JSONExt.deepEqual(formData, defaultValue);
|
205 | }
|
206 | const needsDescription = !isRoot &&
|
207 | schema.type != 'object' &&
|
208 | id !=
|
209 | 'jp-SettingsEditor-@jupyterlab/shortcuts-extension:shortcuts_shortcuts';
|
210 |
|
211 |
|
212 |
|
213 | const isAdditional = schema.hasOwnProperty(ADDITIONAL_PROPERTY_FLAG);
|
214 | const isItem = !(schema.type === 'object' || schema.type === 'array');
|
215 | return (React.createElement("div", { className: `form-group ${displayLabel || schema.type === 'boolean' ? 'small-field' : ''}` },
|
216 | !hasCustomField &&
|
217 | (rawErrors ? (
|
218 |
|
219 | React.createElement("div", { className: "jp-modifiedIndicator jp-errorIndicator" })) : (
|
220 |
|
221 | isModified && React.createElement("div", { className: "jp-modifiedIndicator" }))),
|
222 | React.createElement("div", { className: `jp-FormGroup-content ${props.compact
|
223 | ? 'jp-FormGroup-contentCompact'
|
224 | : 'jp-FormGroup-contentNormal'}` },
|
225 | isItem && displayLabel && !isRoot && label && !isAdditional ? (props.compact ? (React.createElement("div", { className: "jp-FormGroup-compactTitle" },
|
226 | React.createElement("div", { className: "jp-FormGroup-fieldLabel jp-FormGroup-contentItem" }, label),
|
227 | isItem && schema.description && needsDescription && (React.createElement("div", { className: "jp-FormGroup-description" }, schema.description)))) : (React.createElement("h3", { className: "jp-FormGroup-fieldLabel jp-FormGroup-contentItem" }, label))) : (React.createElement(React.Fragment, null)),
|
228 | isAdditional && (React.createElement("input", { className: "jp-FormGroup-contentItem jp-mod-styled", type: "text", onBlur: event => onKeyChange(event.target.value), defaultValue: label })),
|
229 | React.createElement("div", { className: `${isRoot
|
230 | ? 'jp-root'
|
231 | : schema.type === 'object'
|
232 | ? 'jp-objectFieldWrapper'
|
233 | : schema.type === 'array'
|
234 | ? 'jp-arrayFieldWrapper'
|
235 | : 'jp-inputFieldWrapper jp-FormGroup-contentItem'}` }, children),
|
236 | isAdditional && (React.createElement("button", { className: "jp-FormGroup-contentItem jp-mod-styled jp-mod-warn jp-FormGroup-removeButton", onClick: onDropPropertyClick(label) }, trans.__('Remove'))),
|
237 | !props.compact && schema.description && needsDescription && (React.createElement("div", { className: "jp-FormGroup-description" }, schema.description)),
|
238 | isModified && defaultValue !== undefined && (React.createElement("div", { className: "jp-FormGroup-default" }, trans.__('Default: %1', defaultValue !== null ? defaultValue.toLocaleString() : 'null'))),
|
239 | React.createElement("div", { className: "validationErrors" }, errors))));
|
240 | }
|
241 | });
|
242 |
|
243 |
|
244 |
|
245 | export function FormComponent(props) {
|
246 | const { buttonStyle, compact, showModifiedFromDefault, translator, formContext, ...others } = props;
|
247 | const uiSchema = { ...(others.uiSchema || JSONExt.emptyObject) };
|
248 | uiSchema['ui:options'] = { ...DEFAULT_UI_OPTIONS, ...uiSchema['ui:options'] };
|
249 | others.uiSchema = uiSchema;
|
250 | const { FieldTemplate, ArrayFieldTemplate, ObjectFieldTemplate } = props.templates || JSONExt.emptyObject;
|
251 | const customization = {
|
252 | buttonStyle,
|
253 | compact,
|
254 | showModifiedFromDefault,
|
255 | translator
|
256 | };
|
257 | const fieldTemplate = React.useMemo(() => FieldTemplate !== null && FieldTemplate !== void 0 ? FieldTemplate : CustomTemplateFactory(customization), [FieldTemplate, buttonStyle, compact, showModifiedFromDefault, translator]);
|
258 | const arrayTemplate = React.useMemo(() => ArrayFieldTemplate !== null && ArrayFieldTemplate !== void 0 ? ArrayFieldTemplate : CustomArrayTemplateFactory(customization), [
|
259 | ArrayFieldTemplate,
|
260 | buttonStyle,
|
261 | compact,
|
262 | showModifiedFromDefault,
|
263 | translator
|
264 | ]);
|
265 | const objectTemplate = React.useMemo(() => ObjectFieldTemplate !== null && ObjectFieldTemplate !== void 0 ? ObjectFieldTemplate : CustomObjectTemplateFactory(customization), [
|
266 | ObjectFieldTemplate,
|
267 | buttonStyle,
|
268 | compact,
|
269 | showModifiedFromDefault,
|
270 | translator
|
271 | ]);
|
272 | const templates = {
|
273 | FieldTemplate: fieldTemplate,
|
274 | ArrayFieldTemplate: arrayTemplate,
|
275 | ObjectFieldTemplate: objectTemplate
|
276 | };
|
277 | return (React.createElement(Form, { templates: templates, formContext: formContext, ...others }));
|
278 | }
|
279 |
|
\ | No newline at end of file |