@syncfusion/ej2-react-form-renderer 0.1.0-beta → 0.1.2-beta
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/README.md +3 -10
- package/package.json +1 -1
- package/src/CheckboxGroup.js +3 -2
- package/src/ConditionalRuleEngine.d.ts +295 -0
- package/src/ConditionalRuleEngine.js +566 -0
- package/src/DataGridComponent.d.ts +0 -1
- package/src/DataGridComponent.js +9 -22
- package/src/FormRenderer.d.ts +28 -7
- package/src/FormRenderer.js +342 -202
- package/src/MinMaxRuleEngine.d.ts +95 -0
- package/src/MinMaxRuleEngine.js +361 -0
- package/src/expressions/DependencyTracker.d.ts +30 -0
- package/src/expressions/DependencyTracker.js +128 -0
- package/src/expressions/ExpressionEngine.d.ts +81 -0
- package/src/expressions/ExpressionEngine.js +503 -0
- package/src/expressions/ExpressionParser.d.ts +39 -0
- package/src/expressions/ExpressionParser.js +270 -0
- package/src/json-converter.d.ts +32 -31
- package/src/json-converter.js +313 -284
- package/src/parser.js +22 -18
- package/src/renderFormField.d.ts +3 -1
- package/src/renderFormField.js +70 -46
- package/src/types/FormSchema.d.ts +36 -2
- package/src/utils.js +348 -0
- package/styles/form-renderer.base.css +49 -23
package/src/utils.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Internationalization } from '@syncfusion/ej2-base';
|
|
3
|
+
import { DataManager, Query, UrlAdaptor, WebApiAdaptor, ODataV4Adaptor } from '@syncfusion/ej2-data';
|
|
4
|
+
import { ConditionalRuleEngine } from "./ConditionalRuleEngine";
|
|
5
|
+
import { UI_TYPE_TO_SEMANTIC_TYPE } from './json-converter';
|
|
1
6
|
/**
|
|
2
7
|
* Maps button style to Syncfusion CSS classes
|
|
3
8
|
* @param style - Button style ('primary' | 'flat' | 'information' | 'error' | 'success' | 'warning')
|
|
@@ -58,3 +63,346 @@ export function splitWidths(input) {
|
|
|
58
63
|
// Convert any NaN (shouldn't remain) to 0 and round knowns
|
|
59
64
|
return result.map(v => (isNaN(v) ? 0 : Math.round(v)));
|
|
60
65
|
}
|
|
66
|
+
export function extractAllDescendantIds(component) {
|
|
67
|
+
const childIds = [];
|
|
68
|
+
function traverse(comps) {
|
|
69
|
+
for (const comp of comps) {
|
|
70
|
+
childIds.push(comp.id);
|
|
71
|
+
// Recursively traverse nested structures
|
|
72
|
+
if (comp.children && Array.isArray(comp.children)) {
|
|
73
|
+
traverse(comp.children);
|
|
74
|
+
}
|
|
75
|
+
// Handle table cells
|
|
76
|
+
if (comp.tableCells && Array.isArray(comp.tableCells)) {
|
|
77
|
+
comp.tableCells.forEach((row) => {
|
|
78
|
+
if (Array.isArray(row)) {
|
|
79
|
+
row.forEach((cell) => {
|
|
80
|
+
if (Array.isArray(cell)) {
|
|
81
|
+
traverse(cell);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// Handle tab items
|
|
88
|
+
if (comp.tabItems && Array.isArray(comp.tabItems)) {
|
|
89
|
+
comp.tabItems.forEach((tabItem) => {
|
|
90
|
+
if (tabItem.content && Array.isArray(tabItem.content)) {
|
|
91
|
+
traverse(tabItem.content);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Start with direct children
|
|
98
|
+
if (component.children && Array.isArray(component.children)) {
|
|
99
|
+
traverse(component.children);
|
|
100
|
+
}
|
|
101
|
+
// Handle table cells
|
|
102
|
+
if (component.tableCells && Array.isArray(component.tableCells)) {
|
|
103
|
+
component.tableCells.forEach((row) => {
|
|
104
|
+
if (Array.isArray(row)) {
|
|
105
|
+
row.forEach((cell) => {
|
|
106
|
+
if (Array.isArray(cell)) {
|
|
107
|
+
traverse(cell);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
// Handle tab items
|
|
114
|
+
if (component.tabItems && Array.isArray(component.tabItems)) {
|
|
115
|
+
component.tabItems.forEach((tabItem) => {
|
|
116
|
+
if (tabItem.content && Array.isArray(tabItem.content)) {
|
|
117
|
+
traverse(tabItem.content);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return childIds;
|
|
122
|
+
}
|
|
123
|
+
export function formatDateValues(component, value) {
|
|
124
|
+
let intl = new Internationalization();
|
|
125
|
+
let dFormatter = intl.getDateFormat({
|
|
126
|
+
format: 'MM/dd/yyyy',
|
|
127
|
+
type: 'date'
|
|
128
|
+
});
|
|
129
|
+
if (component.type === 'date') {
|
|
130
|
+
value = dFormatter(new Date(value));
|
|
131
|
+
}
|
|
132
|
+
if (component.type === 'time') {
|
|
133
|
+
dFormatter = intl.getDateFormat({
|
|
134
|
+
format: 'hh:mm a',
|
|
135
|
+
type: 'time'
|
|
136
|
+
});
|
|
137
|
+
value = dFormatter(new Date(value));
|
|
138
|
+
}
|
|
139
|
+
if (component.type === 'dateTime') {
|
|
140
|
+
dFormatter = intl.getDateFormat({
|
|
141
|
+
format: 'MM/dd/yyyy hh:mm a',
|
|
142
|
+
type: 'dateTime'
|
|
143
|
+
});
|
|
144
|
+
value = dFormatter(new Date(value));
|
|
145
|
+
}
|
|
146
|
+
if (component.type === 'dateRange' && Array.isArray(value)) {
|
|
147
|
+
value = value.map(date => date ? dFormatter(new Date(date)) : null);
|
|
148
|
+
}
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
export const getComponentFromSchema = (id, formSchema) => {
|
|
152
|
+
if (!id || !formSchema)
|
|
153
|
+
return null;
|
|
154
|
+
const findInComponents = (components) => {
|
|
155
|
+
for (const comp of components) {
|
|
156
|
+
if (comp.id === id || comp.name === id)
|
|
157
|
+
return comp;
|
|
158
|
+
if (comp.children) {
|
|
159
|
+
const found = findInComponents(comp.children);
|
|
160
|
+
if (found)
|
|
161
|
+
return found;
|
|
162
|
+
}
|
|
163
|
+
if (comp.tableCells) {
|
|
164
|
+
for (const row of comp.tableCells) {
|
|
165
|
+
for (const cell of row) {
|
|
166
|
+
const found = findInComponents(cell);
|
|
167
|
+
if (found)
|
|
168
|
+
return found;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (comp.tabItems) {
|
|
173
|
+
for (const tab of comp.tabItems) {
|
|
174
|
+
if (tab.content) {
|
|
175
|
+
const found = findInComponents(tab.content);
|
|
176
|
+
if (found)
|
|
177
|
+
return found;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
};
|
|
184
|
+
return findInComponents(formSchema.components || []);
|
|
185
|
+
};
|
|
186
|
+
/**
|
|
187
|
+
* Helper function to get the appropriate adaptor instance
|
|
188
|
+
* @param adaptorType - Type of adaptor ('WebApiAdaptor' | 'UrlAdaptor' | 'ODataV4Adaptor')
|
|
189
|
+
* @returns Adaptor instance
|
|
190
|
+
*/
|
|
191
|
+
export const getAdaptorInstance = (adaptorType) => {
|
|
192
|
+
switch (adaptorType) {
|
|
193
|
+
case 'WebApiAdaptor':
|
|
194
|
+
return new WebApiAdaptor();
|
|
195
|
+
case 'ODataV4Adaptor':
|
|
196
|
+
return new ODataV4Adaptor();
|
|
197
|
+
case 'UrlAdaptor':
|
|
198
|
+
default:
|
|
199
|
+
return new UrlAdaptor();
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Extracts data from a nested path using dot notation and array indices
|
|
204
|
+
* @param data - The data object or array
|
|
205
|
+
* @param path - Path to the data (e.g., 'results.items', '[0].data', 'response[0].values')
|
|
206
|
+
* @returns Extracted data or empty array
|
|
207
|
+
*/
|
|
208
|
+
export const extractDataFromPath = (data, path) => {
|
|
209
|
+
if (!path || data === null || data === undefined)
|
|
210
|
+
return data;
|
|
211
|
+
// Split by dots but preserve array indices
|
|
212
|
+
const parts = path.split(/\.(?![^\[]*\])/); // Split by dots not inside brackets
|
|
213
|
+
let current = data;
|
|
214
|
+
for (const part of parts) {
|
|
215
|
+
if (current === null || current === undefined) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
// Handle array index notation like [0] or results[0]
|
|
219
|
+
const arrayMatch = part.match(/^(\w*)\[(\d+)\]$/);
|
|
220
|
+
if (arrayMatch) {
|
|
221
|
+
const propName = arrayMatch[1];
|
|
222
|
+
const index = parseInt(arrayMatch[2]);
|
|
223
|
+
// If propName is empty, current should be an array
|
|
224
|
+
if (!propName) {
|
|
225
|
+
current = current[index];
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
current = current[propName]?.[index];
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
// Regular property access
|
|
233
|
+
current = current[part];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return current;
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* Custom hook to fetch options from URL with custom headers
|
|
240
|
+
* @param componentOptions - The component options object which may contain URL and headers
|
|
241
|
+
* @param adaptorType - Type of adaptor to use ('WebApiAdaptor' | 'UrlAdaptor' | 'ODataV4Adaptor')
|
|
242
|
+
* @returns Array of fetched options
|
|
243
|
+
*/
|
|
244
|
+
export const useFetchOptions = (componentOptions) => {
|
|
245
|
+
const [fetchedOptions, setFetchedOptions] = React.useState([]);
|
|
246
|
+
React.useEffect(() => {
|
|
247
|
+
const isUrlType = componentOptions &&
|
|
248
|
+
typeof componentOptions === 'object' &&
|
|
249
|
+
!Array.isArray(componentOptions) &&
|
|
250
|
+
componentOptions.type === 'url' &&
|
|
251
|
+
componentOptions.url;
|
|
252
|
+
if (isUrlType) {
|
|
253
|
+
const urlConfig = componentOptions;
|
|
254
|
+
try {
|
|
255
|
+
const headers = {};
|
|
256
|
+
if (urlConfig.headers && Array.isArray(urlConfig.headers)) {
|
|
257
|
+
urlConfig.headers.forEach((h) => {
|
|
258
|
+
if (h.key?.trim()) {
|
|
259
|
+
headers[h.key] = h.value;
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
// ✅ Create DataManager with selected adaptor
|
|
264
|
+
const dataManager = new DataManager({
|
|
265
|
+
url: urlConfig.url,
|
|
266
|
+
adaptor: getAdaptorInstance(urlConfig.adaptorType),
|
|
267
|
+
headers: Object.keys(headers).length ? headers : undefined
|
|
268
|
+
});
|
|
269
|
+
// ✅ Build Query (dynamic support)
|
|
270
|
+
let query = new Query();
|
|
271
|
+
if (urlConfig.search && urlConfig.search.enabled && urlConfig.search.fields && urlConfig.search.fields.length > 0) {
|
|
272
|
+
const searchKey = urlConfig.search.key || 'search';
|
|
273
|
+
query = query.search(searchKey, urlConfig.search.fields);
|
|
274
|
+
}
|
|
275
|
+
// Apply sort query
|
|
276
|
+
if (urlConfig.sort && urlConfig.sort.enabled && urlConfig.sort.field) {
|
|
277
|
+
const sortDirection = urlConfig.sort.direction === 'descending' ? 'descending' : 'ascending';
|
|
278
|
+
query = query.sortBy(urlConfig.sort.field, sortDirection);
|
|
279
|
+
}
|
|
280
|
+
// Apply filter queries
|
|
281
|
+
if (urlConfig.filters && Array.isArray(urlConfig.filters) && urlConfig.filters.length > 0) {
|
|
282
|
+
urlConfig.filters.forEach((f) => {
|
|
283
|
+
if (f.field && f.operator && f.value) {
|
|
284
|
+
query = query.where(f.field, f.operator, f.value);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
// Example: add params (query string)
|
|
289
|
+
if (urlConfig.queryParams) {
|
|
290
|
+
Object.keys(urlConfig.queryParams).forEach(key => {
|
|
291
|
+
query = query.addParams(key, urlConfig.queryParams[key]);
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
// Example: paging
|
|
295
|
+
if (urlConfig.skip)
|
|
296
|
+
query = query.skip(urlConfig.skip);
|
|
297
|
+
if (urlConfig.take)
|
|
298
|
+
query = query.take(urlConfig.take);
|
|
299
|
+
// ✅ Execute query
|
|
300
|
+
dataManager.executeQuery(query).then((res) => {
|
|
301
|
+
let data = res.result;
|
|
302
|
+
if (urlConfig.dataPath) {
|
|
303
|
+
data = extractDataFromPath(data, urlConfig.dataPath);
|
|
304
|
+
}
|
|
305
|
+
if (Array.isArray(data)) {
|
|
306
|
+
setFetchedOptions(data);
|
|
307
|
+
}
|
|
308
|
+
else if (typeof data === 'string') {
|
|
309
|
+
setFetchedOptions([data]);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
setFetchedOptions([]);
|
|
313
|
+
}
|
|
314
|
+
}).catch((err) => {
|
|
315
|
+
console.error('DataManager fetch error:', err);
|
|
316
|
+
setFetchedOptions([]);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
catch (err) {
|
|
320
|
+
console.error('Setup error:', err);
|
|
321
|
+
setFetchedOptions([]);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}, [componentOptions]);
|
|
325
|
+
return fetchedOptions;
|
|
326
|
+
};
|
|
327
|
+
/**
|
|
328
|
+
* Resolves component options from various sources
|
|
329
|
+
* Handles array options, URL-fetched options, and raw data options
|
|
330
|
+
* @param options - Component options (can be array, URL config, or raw data config)
|
|
331
|
+
* @param fetchedOptions - Pre-fetched options from URL
|
|
332
|
+
* @returns Resolved array of options
|
|
333
|
+
*/
|
|
334
|
+
export const resolveOptions = (options, fetchedOptions) => {
|
|
335
|
+
// If URL type with fetched data, return fetched options
|
|
336
|
+
if (options && typeof options === 'object' && !Array.isArray(options) && options.type === 'url') {
|
|
337
|
+
return fetchedOptions.length > 0 ? fetchedOptions : [];
|
|
338
|
+
}
|
|
339
|
+
// If already an array, return as-is
|
|
340
|
+
if (Array.isArray(options)) {
|
|
341
|
+
return options;
|
|
342
|
+
}
|
|
343
|
+
// If it's raw data type
|
|
344
|
+
if (options && typeof options === 'object' && !Array.isArray(options) && options.type === 'raw') {
|
|
345
|
+
return Array.isArray(options.data) ? options.data : [];
|
|
346
|
+
}
|
|
347
|
+
return [];
|
|
348
|
+
};
|
|
349
|
+
export const collectAvailableFieldNames = (components) => {
|
|
350
|
+
const fieldNames = [];
|
|
351
|
+
const traverse = (comps) => {
|
|
352
|
+
comps.forEach(comp => {
|
|
353
|
+
// Only add fields that have a name and aren't layout components
|
|
354
|
+
if (comp.name && !['panel', 'table', 'tabs', 'card', 'message', 'button', 'splitButton', 'staticHtml'].includes(comp.type)) {
|
|
355
|
+
// Get semantic type mapping for this component
|
|
356
|
+
const semanticType = UI_TYPE_TO_SEMANTIC_TYPE[comp.type];
|
|
357
|
+
if (semanticType) {
|
|
358
|
+
fieldNames.push({
|
|
359
|
+
name: comp.name,
|
|
360
|
+
type: semanticType.type,
|
|
361
|
+
...(semanticType.format && { format: semanticType.format })
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// Traverse nested components
|
|
366
|
+
if (comp.children)
|
|
367
|
+
traverse(comp.children);
|
|
368
|
+
if (comp.tabItems) {
|
|
369
|
+
comp.tabItems.forEach(tab => {
|
|
370
|
+
if (tab.content)
|
|
371
|
+
traverse(tab.content);
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
if (comp.tableCells) {
|
|
375
|
+
comp.tableCells.forEach(row => {
|
|
376
|
+
row.forEach(cell => traverse(cell));
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
};
|
|
381
|
+
traverse(components);
|
|
382
|
+
return fieldNames;
|
|
383
|
+
};
|
|
384
|
+
/**
|
|
385
|
+
* Resolve conditional data for a DataGrid component
|
|
386
|
+
* Evaluates all conditionalData rules and applies the first matching one
|
|
387
|
+
* Returns both dataSource and custom columns if defined
|
|
388
|
+
*
|
|
389
|
+
* @param conditions - Component conditions including conditionalData rules
|
|
390
|
+
* @param formValues - Current form field values
|
|
391
|
+
* @returns Object with dataSource and columns, or undefined if no condition matches
|
|
392
|
+
*/
|
|
393
|
+
export const resolveConditionalData = (conditions, formValues) => {
|
|
394
|
+
if (!conditions?.conditionalData || !Array.isArray(conditions.conditionalData)) {
|
|
395
|
+
return undefined;
|
|
396
|
+
}
|
|
397
|
+
// Evaluate each conditional data rule in order
|
|
398
|
+
for (const rule of conditions.conditionalData) {
|
|
399
|
+
if (ConditionalRuleEngine.evaluateCondition(rule.condition, formValues)) {
|
|
400
|
+
// Condition is met - resolve and return both data source and columns
|
|
401
|
+
return {
|
|
402
|
+
dataSource: rule.dataSource,
|
|
403
|
+
columns: rule.includeColumns ? rule.columns : undefined
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return undefined;
|
|
408
|
+
};
|
|
@@ -150,6 +150,22 @@
|
|
|
150
150
|
min-width: 0;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
.field-wrapper:has(.e-small) .field-label {
|
|
154
|
+
font-size: .75rem;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.field-wrapper:has(.e-small) .field-description {
|
|
158
|
+
font-size: 0.625rem;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.field-wrapper:has(.e-bigger) .field-label {
|
|
162
|
+
font-size: 1rem;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.field-wrapper:has(.e-bigger) .field-description {
|
|
166
|
+
font-size: 0.875rem;
|
|
167
|
+
}
|
|
168
|
+
|
|
153
169
|
/* Label */
|
|
154
170
|
.field-label {
|
|
155
171
|
font-size: 0.875rem;
|
|
@@ -213,7 +229,6 @@
|
|
|
213
229
|
border: none;
|
|
214
230
|
border-radius: 8px;
|
|
215
231
|
padding: 0;
|
|
216
|
-
margin: 1rem 0;
|
|
217
232
|
}
|
|
218
233
|
|
|
219
234
|
.form-panel-renderer:has(.panel-legend) {
|
|
@@ -268,45 +283,45 @@
|
|
|
268
283
|
overflow-y: hidden;
|
|
269
284
|
}
|
|
270
285
|
|
|
271
|
-
.form-table-renderer .table-row {
|
|
286
|
+
.form-table-renderer .e-form-table-row {
|
|
272
287
|
display: table-row;
|
|
273
288
|
background: transparent;
|
|
274
289
|
}
|
|
275
290
|
|
|
276
|
-
.form-table-renderer .table-cell {
|
|
291
|
+
.form-table-renderer .e-form-table-cell {
|
|
277
292
|
display: table-cell;
|
|
278
293
|
padding: 12px;
|
|
279
294
|
vertical-align: top;
|
|
280
295
|
}
|
|
281
296
|
|
|
282
|
-
.table-border .table-cell {
|
|
297
|
+
.table-border .e-form-table-cell {
|
|
283
298
|
border-bottom: 1px solid var(--sf-layout-border-color);
|
|
284
299
|
border-right: 1px solid var(--sf-layout-border-color);
|
|
285
300
|
}
|
|
286
301
|
|
|
287
|
-
.table-cell:last-child {
|
|
302
|
+
.e-form-table-cell:last-child {
|
|
288
303
|
border-right: none;
|
|
289
304
|
}
|
|
290
305
|
|
|
291
|
-
.form-table-renderer .table-row:last-child .table-cell {
|
|
306
|
+
.form-table-renderer .e-form-table-row:last-child .e-form-table-cell {
|
|
292
307
|
border-bottom: none;
|
|
293
308
|
}
|
|
294
309
|
|
|
295
|
-
.table-cell > .form-table-renderer,
|
|
296
|
-
.table-cell > .form-tabs-renderer,
|
|
297
|
-
.table-cell > .form-card-renderer,
|
|
298
|
-
.table-cell > .form-panel-renderer,
|
|
299
|
-
.table-cell > .form-group
|
|
310
|
+
.e-form-table-cell > .form-table-renderer,
|
|
311
|
+
.e-form-table-cell > .form-tabs-renderer,
|
|
312
|
+
.e-form-table-cell > .form-card-renderer,
|
|
313
|
+
.e-form-table-cell > .form-panel-renderer,
|
|
314
|
+
.e-form-table-cell > .form-group
|
|
300
315
|
{
|
|
301
|
-
margin-bottom:
|
|
316
|
+
margin-bottom: 1.5rem;
|
|
302
317
|
}
|
|
303
318
|
|
|
304
319
|
|
|
305
|
-
.table-cell > .form-table-renderer:last-child,
|
|
306
|
-
.table-cell > .form-tabs-renderer:last-child,
|
|
307
|
-
.table-cell > .form-card-renderer:last-child,
|
|
308
|
-
.table-cell > .form-panel-renderer:last-child,
|
|
309
|
-
.table-cell > .form-group:last-child
|
|
320
|
+
.e-form-table-cell > .form-table-renderer:last-child,
|
|
321
|
+
.e-form-table-cell > .form-tabs-renderer:last-child,
|
|
322
|
+
.e-form-table-cell > .form-card-renderer:last-child,
|
|
323
|
+
.e-form-table-cell > .form-panel-renderer:last-child,
|
|
324
|
+
.e-form-table-cell > .form-group:last-child
|
|
310
325
|
{
|
|
311
326
|
margin-bottom: 0;
|
|
312
327
|
}
|
|
@@ -342,6 +357,7 @@
|
|
|
342
357
|
}
|
|
343
358
|
|
|
344
359
|
.tab-content-renderer {
|
|
360
|
+
padding-top: 10px;
|
|
345
361
|
display: flex;
|
|
346
362
|
flex-direction: column;
|
|
347
363
|
gap: 1rem;
|
|
@@ -387,11 +403,11 @@
|
|
|
387
403
|
border-color: #3d3d3d;
|
|
388
404
|
}
|
|
389
405
|
|
|
390
|
-
[data-theme="dark"] .table-row {
|
|
406
|
+
[data-theme="dark"] .e-form-table-row {
|
|
391
407
|
border-color: #3d3d3d;
|
|
392
408
|
}
|
|
393
409
|
|
|
394
|
-
[data-theme="dark"] .table-cell {
|
|
410
|
+
[data-theme="dark"] .e-form-table-cell {
|
|
395
411
|
border-color: #3d3d3d;
|
|
396
412
|
}
|
|
397
413
|
|
|
@@ -406,6 +422,16 @@
|
|
|
406
422
|
line-height: 16px;
|
|
407
423
|
}
|
|
408
424
|
|
|
425
|
+
.form-title h1,
|
|
426
|
+
.form-title h2,
|
|
427
|
+
.form-title h3 {
|
|
428
|
+
margin-top: 0;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.form-title {
|
|
432
|
+
text-align: center;
|
|
433
|
+
}
|
|
434
|
+
|
|
409
435
|
.e-card .e-card-content {
|
|
410
436
|
padding: 12px 18px 12px 18px;
|
|
411
437
|
}
|
|
@@ -442,7 +468,7 @@
|
|
|
442
468
|
width: 100%;
|
|
443
469
|
}
|
|
444
470
|
|
|
445
|
-
.form-table-renderer .table-cell {
|
|
471
|
+
.form-table-renderer .e-form-table-cell {
|
|
446
472
|
display: block;
|
|
447
473
|
flex: 1 1 auto;
|
|
448
474
|
min-width: 250px; /* minimum width before wrapping to next row */
|
|
@@ -457,17 +483,17 @@
|
|
|
457
483
|
flex: 1 1 auto;
|
|
458
484
|
}
|
|
459
485
|
|
|
460
|
-
.table-border .table-cell {
|
|
486
|
+
.table-border .e-form-table-cell {
|
|
461
487
|
border-right: none;
|
|
462
488
|
border-bottom: 1px solid var(--sf-layout-border-color);
|
|
463
489
|
border-radius: 4px;
|
|
464
490
|
}
|
|
465
491
|
|
|
466
|
-
.form-table-renderer .table-cell:last-child {
|
|
492
|
+
.form-table-renderer .e-form-table-cell:last-child {
|
|
467
493
|
border-bottom: 1px solid var(--sf-layout-border-color);
|
|
468
494
|
}
|
|
469
495
|
|
|
470
|
-
.form-table-renderer .row:last-child .table-cell {
|
|
496
|
+
.form-table-renderer .row:last-child .e-form-table-cell {
|
|
471
497
|
border-bottom: none;
|
|
472
498
|
}
|
|
473
499
|
}
|