@abgov/jsonforms-components 2.38.3 → 2.38.4
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/index.esm.js
CHANGED
|
@@ -9986,7 +9986,7 @@ const FlexForm = styled.div(_t10 || (_t10 = _$3`
|
|
|
9986
9986
|
flex-direction: column;
|
|
9987
9987
|
flex: 3;
|
|
9988
9988
|
`));
|
|
9989
|
-
const
|
|
9989
|
+
const TabName = styled.div(_t11 || (_t11 = _$3`
|
|
9990
9990
|
margin: 1rem 0 1rem 1rem;
|
|
9991
9991
|
font-weight: 400;
|
|
9992
9992
|
white-space: nowrap;
|
|
@@ -11076,6 +11076,57 @@ const NonEmptyRowComponent = ({
|
|
|
11076
11076
|
}) : null
|
|
11077
11077
|
}, childPath);
|
|
11078
11078
|
};
|
|
11079
|
+
const MainItemComponent = ({
|
|
11080
|
+
childPath,
|
|
11081
|
+
rowIndex,
|
|
11082
|
+
openDeleteDialog,
|
|
11083
|
+
selectCurrentTab,
|
|
11084
|
+
enabled,
|
|
11085
|
+
currentTab,
|
|
11086
|
+
current,
|
|
11087
|
+
setCurrentListPage,
|
|
11088
|
+
rowData
|
|
11089
|
+
}) => {
|
|
11090
|
+
const displayName = Object.keys(rowData !== null && rowData !== void 0 ? rowData : {}).length === 0 ? 'No data' : Object.values(rowData || {}).join(', ');
|
|
11091
|
+
return jsx(SideMenuItem, {
|
|
11092
|
+
onClick: () => selectCurrentTab(rowIndex),
|
|
11093
|
+
onKeyDown: e => {
|
|
11094
|
+
if (e.key === 'ArrowRight') {
|
|
11095
|
+
e.preventDefault();
|
|
11096
|
+
if (current) {
|
|
11097
|
+
const goa = current === null || current === void 0 ? void 0 : current.querySelector('goa-input, goa-button');
|
|
11098
|
+
if (goa === null || goa === void 0 ? void 0 : goa.shadowRoot) {
|
|
11099
|
+
const internal = goa.shadowRoot.querySelector('input, button');
|
|
11100
|
+
internal === null || internal === void 0 ? void 0 : internal.focus();
|
|
11101
|
+
selectCurrentTab(rowIndex);
|
|
11102
|
+
}
|
|
11103
|
+
}
|
|
11104
|
+
}
|
|
11105
|
+
},
|
|
11106
|
+
children: jsxs(RowFlexMenu, {
|
|
11107
|
+
tabIndex: 0,
|
|
11108
|
+
children: [jsx(TabName, {
|
|
11109
|
+
children: displayName
|
|
11110
|
+
}), enabled ? jsx(Trash, {
|
|
11111
|
+
children: jsx(GoAIconButton, {
|
|
11112
|
+
disabled: !enabled,
|
|
11113
|
+
icon: "trash",
|
|
11114
|
+
title: 'remove',
|
|
11115
|
+
testId: "remove the details",
|
|
11116
|
+
onClick: () => openDeleteDialog(childPath, rowIndex, displayName)
|
|
11117
|
+
})
|
|
11118
|
+
}) : null, jsx(IconPadding, {
|
|
11119
|
+
children: jsx(GoAIconButton, {
|
|
11120
|
+
disabled: !enabled,
|
|
11121
|
+
icon: "create",
|
|
11122
|
+
title: 'edit',
|
|
11123
|
+
testId: "edit button",
|
|
11124
|
+
onClick: () => setCurrentListPage(currentTab + 1)
|
|
11125
|
+
})
|
|
11126
|
+
})]
|
|
11127
|
+
})
|
|
11128
|
+
});
|
|
11129
|
+
};
|
|
11079
11130
|
const MainTab = ({
|
|
11080
11131
|
childPath,
|
|
11081
11132
|
rowIndex,
|
|
@@ -11083,7 +11134,6 @@ const MainTab = ({
|
|
|
11083
11134
|
selectCurrentTab,
|
|
11084
11135
|
enabled,
|
|
11085
11136
|
currentTab,
|
|
11086
|
-
name,
|
|
11087
11137
|
current,
|
|
11088
11138
|
setCurrentListPage
|
|
11089
11139
|
}) => {
|
|
@@ -11097,48 +11147,35 @@ const MainTab = ({
|
|
|
11097
11147
|
const rowErrors = (_a = core === null || core === void 0 ? void 0 : core.errors) === null || _a === void 0 ? void 0 : _a.filter(e => {
|
|
11098
11148
|
const base = `/${childPath.replace(/\./g, '/')}`;
|
|
11099
11149
|
return e.instancePath === base || e.instancePath.startsWith(base + '/');
|
|
11100
|
-
}).map(
|
|
11150
|
+
}).map(e => {
|
|
11151
|
+
var _a, _b;
|
|
11152
|
+
return ((_b = (_a = e === null || e === void 0 ? void 0 : e.message) === null || _a === void 0 ? void 0 : _a.trim) === null || _b === void 0 ? void 0 : _b.call(_a)) || '';
|
|
11153
|
+
}).filter(msg => msg.length > 0).map((msg, index, arr) => `${msg}${index < arr.length - 1 ? ', ' : ''}`);
|
|
11101
11154
|
return jsx("div", {
|
|
11102
|
-
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
-
|
|
11110
|
-
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
}
|
|
11116
|
-
}
|
|
11117
|
-
}
|
|
11118
|
-
},
|
|
11119
|
-
children: jsxs(RowFlexMenu, {
|
|
11120
|
-
tabIndex: 0,
|
|
11121
|
-
children: [jsxs(TabData, {
|
|
11122
|
-
children: [Object.keys(rowData !== null && rowData !== void 0 ? rowData : {}).length === 0 && 'No data', " ", Object.values(rowData).join(', ')]
|
|
11123
|
-
}), enabled ? jsx(Trash, {
|
|
11124
|
-
children: jsx(GoAIconButton, {
|
|
11125
|
-
disabled: !enabled,
|
|
11126
|
-
icon: "trash",
|
|
11127
|
-
title: 'remove',
|
|
11128
|
-
testId: "remove the details",
|
|
11129
|
-
onClick: () => openDeleteDialog(childPath, rowIndex, name)
|
|
11130
|
-
})
|
|
11131
|
-
}) : null, jsx(IconPadding, {
|
|
11132
|
-
children: jsx(GoAIconButton, {
|
|
11133
|
-
disabled: !enabled,
|
|
11134
|
-
icon: "create",
|
|
11135
|
-
title: 'edit',
|
|
11136
|
-
testId: "edit button",
|
|
11137
|
-
onClick: () => setCurrentListPage(currentTab + 1)
|
|
11138
|
-
})
|
|
11139
|
-
})]
|
|
11140
|
-
})
|
|
11155
|
+
"data-testid": `object-array-main-item-${rowIndex}`,
|
|
11156
|
+
children: (rowErrors === null || rowErrors === void 0 ? void 0 : rowErrors.length) ? jsx(GoAFormItem, {
|
|
11157
|
+
error: (rowErrors === null || rowErrors === void 0 ? void 0 : rowErrors.length) ? rowErrors : null,
|
|
11158
|
+
children: jsx(MainItemComponent, {
|
|
11159
|
+
rowData: rowData,
|
|
11160
|
+
childPath: childPath,
|
|
11161
|
+
rowIndex: rowIndex,
|
|
11162
|
+
openDeleteDialog: openDeleteDialog,
|
|
11163
|
+
selectCurrentTab: selectCurrentTab,
|
|
11164
|
+
enabled: enabled,
|
|
11165
|
+
currentTab: currentTab,
|
|
11166
|
+
current: current,
|
|
11167
|
+
setCurrentListPage: setCurrentListPage
|
|
11141
11168
|
})
|
|
11169
|
+
}) : jsx(MainItemComponent, {
|
|
11170
|
+
rowData: rowData,
|
|
11171
|
+
childPath: childPath,
|
|
11172
|
+
rowIndex: rowIndex,
|
|
11173
|
+
openDeleteDialog: openDeleteDialog,
|
|
11174
|
+
selectCurrentTab: selectCurrentTab,
|
|
11175
|
+
enabled: enabled,
|
|
11176
|
+
currentTab: currentTab,
|
|
11177
|
+
current: current,
|
|
11178
|
+
setCurrentListPage: setCurrentListPage
|
|
11142
11179
|
})
|
|
11143
11180
|
}, childPath);
|
|
11144
11181
|
};
|
|
@@ -11192,10 +11229,6 @@ const ObjectArrayList = ({
|
|
|
11192
11229
|
const selectCurrentTab = index => {
|
|
11193
11230
|
setCurrentIndex(index);
|
|
11194
11231
|
};
|
|
11195
|
-
(() => {
|
|
11196
|
-
const str = (appliedUiSchemaOptions === null || appliedUiSchemaOptions === void 0 ? void 0 : appliedUiSchemaOptions.itemLabel) ? `${appliedUiSchemaOptions.itemLabel}` : `${path}`;
|
|
11197
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
11198
|
-
})();
|
|
11199
11232
|
return jsx(ListContainer, {
|
|
11200
11233
|
children: jsxs(RowFlex, {
|
|
11201
11234
|
children: [currentListPage === 0 && jsx(FlexTabs, {
|
|
@@ -11204,12 +11237,10 @@ const ObjectArrayList = ({
|
|
|
11204
11237
|
},
|
|
11205
11238
|
children: range(data).map(index => {
|
|
11206
11239
|
const childPath = Paths.compose(path, `${index}`);
|
|
11207
|
-
const name = (appliedUiSchemaOptions === null || appliedUiSchemaOptions === void 0 ? void 0 : appliedUiSchemaOptions.itemLabel) ? `${pluralize.singular(appliedUiSchemaOptions === null || appliedUiSchemaOptions === void 0 ? void 0 : appliedUiSchemaOptions.itemLabel)} ${index + 1}` : `${pluralize.singular(path)} ${index + 1}`;
|
|
11208
11240
|
return jsx(MainTab, {
|
|
11209
11241
|
childPath: childPath,
|
|
11210
11242
|
rowIndex: index,
|
|
11211
11243
|
currentTab: currentIndex,
|
|
11212
|
-
name: name,
|
|
11213
11244
|
openDeleteDialog: openDeleteDialog,
|
|
11214
11245
|
selectCurrentTab: selectCurrentTab,
|
|
11215
11246
|
enabled: enabled,
|
|
@@ -13135,32 +13166,42 @@ const PhoneNumberWithTypeReviewControl = props => {
|
|
|
13135
13166
|
};
|
|
13136
13167
|
const GoAInputBasePhoneNumberWithTypeReviewControl = withJsonFormsAllOfProps(PhoneNumberWithTypeReviewControl);
|
|
13137
13168
|
|
|
13169
|
+
/**
|
|
13170
|
+
* Escape for use in RegExp
|
|
13171
|
+
*/
|
|
13138
13172
|
function escapeRegExp(s) {
|
|
13139
13173
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
13140
13174
|
}
|
|
13175
|
+
/**
|
|
13176
|
+
* Resolve a JSON Pointer–style scope like "#/properties/x" or "#/properties/arr/c3"
|
|
13177
|
+
*/
|
|
13141
13178
|
function resolveScope(scope, data) {
|
|
13142
13179
|
if (!scope || typeof scope !== 'string') return undefined;
|
|
13180
|
+
// normalize: strip "#/" and optional "properties/"
|
|
13143
13181
|
const cleaned = scope.replace(/^#\/(properties\/)?/, '');
|
|
13144
13182
|
const parts = cleaned.split('/').filter(Boolean);
|
|
13145
13183
|
let cur = data;
|
|
13146
|
-
for (const
|
|
13147
|
-
if (cur == null) return undefined;
|
|
13148
|
-
|
|
13149
|
-
cur = cur[Number(part)];
|
|
13150
|
-
} else if (typeof cur === 'object') {
|
|
13151
|
-
if (part === 'properties') continue;
|
|
13152
|
-
cur = cur[part];
|
|
13153
|
-
} else {
|
|
13154
|
-
return undefined;
|
|
13155
|
-
}
|
|
13184
|
+
for (const p of parts) {
|
|
13185
|
+
if (cur == null || typeof cur !== 'object') return undefined;
|
|
13186
|
+
cur = cur[p];
|
|
13156
13187
|
}
|
|
13157
13188
|
return cur;
|
|
13158
13189
|
}
|
|
13159
|
-
|
|
13190
|
+
/**
|
|
13191
|
+
* SUM(#/properties/arr/c3) helper
|
|
13192
|
+
*/
|
|
13193
|
+
function evaluateSum(scope, data, opts) {
|
|
13160
13194
|
if (!scope || typeof scope !== 'string') {
|
|
13161
13195
|
return {
|
|
13162
13196
|
value: undefined,
|
|
13163
|
-
error: 'SUM
|
|
13197
|
+
error: 'SUM requires a scope argument.'
|
|
13198
|
+
};
|
|
13199
|
+
}
|
|
13200
|
+
const normalized = scope.replace(/^#\/(properties\/)?/, '#/properties/');
|
|
13201
|
+
if ((opts === null || opts === void 0 ? void 0 : opts.knownScopes) && !opts.knownScopes.includes(normalized)) {
|
|
13202
|
+
return {
|
|
13203
|
+
value: undefined,
|
|
13204
|
+
error: `Invalid scope(s): ${normalized}`
|
|
13164
13205
|
};
|
|
13165
13206
|
}
|
|
13166
13207
|
const cleaned = scope.replace(/^#\/(properties\/)?/, '');
|
|
@@ -13168,83 +13209,62 @@ function evaluateSum(scope, data) {
|
|
|
13168
13209
|
if (parts.length < 2) {
|
|
13169
13210
|
return {
|
|
13170
13211
|
value: undefined,
|
|
13171
|
-
error:
|
|
13212
|
+
error: 'SUM requires array/column path like #/properties/arr/c3'
|
|
13172
13213
|
};
|
|
13173
13214
|
}
|
|
13174
|
-
const
|
|
13215
|
+
const colKey = parts[parts.length - 1];
|
|
13175
13216
|
const arrPath = parts.slice(0, -1);
|
|
13176
13217
|
let cur = data;
|
|
13177
|
-
for (const
|
|
13178
|
-
if (cur == null) {
|
|
13179
|
-
cur = undefined;
|
|
13180
|
-
break;
|
|
13181
|
-
}
|
|
13182
|
-
if (Array.isArray(cur) && /^\d+$/.test(segment)) {
|
|
13183
|
-
cur = cur[Number(segment)];
|
|
13184
|
-
} else if (typeof cur === 'object') {
|
|
13185
|
-
if (segment === 'properties') continue;
|
|
13186
|
-
cur = cur[segment];
|
|
13187
|
-
} else {
|
|
13218
|
+
for (const p of arrPath) {
|
|
13219
|
+
if (cur == null || typeof cur !== 'object') {
|
|
13188
13220
|
cur = undefined;
|
|
13189
13221
|
break;
|
|
13190
13222
|
}
|
|
13223
|
+
cur = cur[p];
|
|
13191
13224
|
}
|
|
13192
|
-
if (cur
|
|
13225
|
+
if (cur === undefined) {
|
|
13193
13226
|
return {
|
|
13194
13227
|
value: undefined,
|
|
13195
|
-
error:
|
|
13228
|
+
error: undefined
|
|
13196
13229
|
};
|
|
13197
13230
|
}
|
|
13198
13231
|
if (!Array.isArray(cur)) {
|
|
13199
13232
|
return {
|
|
13200
13233
|
value: undefined,
|
|
13201
|
-
error: `
|
|
13234
|
+
error: `Expected an array at "#/properties/${arrPath.join('/')}"`
|
|
13202
13235
|
};
|
|
13203
13236
|
}
|
|
13204
|
-
const missingIndices = [];
|
|
13205
|
-
const invalidIndices = [];
|
|
13206
13237
|
let sum = 0;
|
|
13207
|
-
|
|
13208
|
-
|
|
13209
|
-
|
|
13210
|
-
|
|
13211
|
-
|
|
13212
|
-
|
|
13213
|
-
|
|
13214
|
-
if (v === undefined || v === null || v === '') {
|
|
13215
|
-
missingIndices.push(i);
|
|
13216
|
-
} else if (typeof v !== 'number' || Number.isNaN(v)) {
|
|
13217
|
-
invalidIndices.push(i);
|
|
13218
|
-
} else {
|
|
13238
|
+
let anyValue = false;
|
|
13239
|
+
let anyMissing = false;
|
|
13240
|
+
for (const row of cur) {
|
|
13241
|
+
if (row == null || typeof row !== 'object') continue;
|
|
13242
|
+
const v = row[colKey];
|
|
13243
|
+
if (typeof v === 'number' && Number.isFinite(v)) {
|
|
13244
|
+
anyValue = true;
|
|
13219
13245
|
sum += v;
|
|
13246
|
+
} else if (v !== undefined && v !== null) {
|
|
13247
|
+
anyMissing = true;
|
|
13220
13248
|
}
|
|
13221
13249
|
}
|
|
13222
|
-
if (
|
|
13250
|
+
if (!anyValue && !anyMissing) {
|
|
13223
13251
|
return {
|
|
13224
13252
|
value: undefined,
|
|
13225
|
-
error:
|
|
13253
|
+
error: undefined
|
|
13226
13254
|
};
|
|
13227
13255
|
}
|
|
13228
|
-
if (
|
|
13256
|
+
if (anyMissing) {
|
|
13229
13257
|
return {
|
|
13230
13258
|
value: undefined,
|
|
13231
|
-
error: `Please provide values for: ${
|
|
13259
|
+
error: `Please provide values for: ${normalized}`
|
|
13232
13260
|
};
|
|
13233
13261
|
}
|
|
13234
13262
|
return {
|
|
13235
13263
|
value: sum,
|
|
13236
|
-
error:
|
|
13264
|
+
error: undefined
|
|
13237
13265
|
};
|
|
13238
13266
|
}
|
|
13239
|
-
|
|
13240
|
-
* General expression evaluation.
|
|
13241
|
-
* - Supports SUM(#/properties/arr/c3)
|
|
13242
|
-
* - Supports arithmetic with JSON pointers:
|
|
13243
|
-
* "#/properties/x * #/properties/y + #/properties/z"
|
|
13244
|
-
*
|
|
13245
|
-
* Returns { value, error } and NEVER throws.
|
|
13246
|
-
*/
|
|
13247
|
-
function evaluateExpression(expression, data) {
|
|
13267
|
+
function evaluateExpression(expression, data, opts) {
|
|
13248
13268
|
if (!expression || typeof expression !== 'string') {
|
|
13249
13269
|
return {
|
|
13250
13270
|
value: undefined,
|
|
@@ -13252,66 +13272,63 @@ function evaluateExpression(expression, data) {
|
|
|
13252
13272
|
};
|
|
13253
13273
|
}
|
|
13254
13274
|
const trimmed = expression.trim();
|
|
13255
|
-
if (!trimmed)
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13275
|
+
if (!trimmed) {
|
|
13276
|
+
return {
|
|
13277
|
+
value: undefined,
|
|
13278
|
+
error: undefined
|
|
13279
|
+
};
|
|
13280
|
+
}
|
|
13259
13281
|
const sumMatch = trimmed.match(/^SUM\(\s*['"]?(.+?)['"]?\s*\)$/i);
|
|
13260
13282
|
if (sumMatch) {
|
|
13261
|
-
const
|
|
13262
|
-
return evaluateSum(
|
|
13283
|
+
const sumScope = sumMatch[1];
|
|
13284
|
+
return evaluateSum(sumScope, data, opts);
|
|
13263
13285
|
}
|
|
13264
|
-
const scopeRegex = /#\/(?:properties\/)?[^\s"')]+/g;
|
|
13286
|
+
const scopeRegex = /#\/(?:properties\/)?[^\s"'()]+/g;
|
|
13265
13287
|
const matches = trimmed.match(scopeRegex) || [];
|
|
13266
13288
|
const uniqueScopes = Array.from(new Set(matches));
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
13275
|
-
|
|
13276
|
-
try {
|
|
13277
|
-
const parser = new Parser();
|
|
13278
|
-
parsed = parser.parse(exprForParse);
|
|
13279
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13280
|
-
} catch (e) {
|
|
13281
|
-
return {
|
|
13282
|
-
value: undefined,
|
|
13283
|
-
error: 'Invalid expression syntax'
|
|
13284
|
-
};
|
|
13289
|
+
const normalizedScopes = uniqueScopes.map(s => s.replace(/^#\/(properties\/)?/, '#/properties/'));
|
|
13290
|
+
if ((opts === null || opts === void 0 ? void 0 : opts.knownScopes) && opts.knownScopes.length) {
|
|
13291
|
+
const invalidScopes = normalizedScopes.filter(s => !opts.knownScopes.includes(s));
|
|
13292
|
+
if (invalidScopes.length > 0) {
|
|
13293
|
+
return {
|
|
13294
|
+
value: undefined,
|
|
13295
|
+
error: `Invalid scope(s): ${invalidScopes.join(', ')}`
|
|
13296
|
+
};
|
|
13297
|
+
}
|
|
13285
13298
|
}
|
|
13286
13299
|
const vars = {};
|
|
13300
|
+
let expr = trimmed;
|
|
13287
13301
|
const missingScopes = [];
|
|
13288
|
-
|
|
13289
|
-
|
|
13302
|
+
let anyValuePresent = false;
|
|
13303
|
+
uniqueScopes.forEach((scope, idx) => {
|
|
13304
|
+
const normalized = scope.replace(/^#\/(properties\/)?/, '#/properties/');
|
|
13290
13305
|
const val = resolveScope(scope, data);
|
|
13291
|
-
if (
|
|
13292
|
-
|
|
13293
|
-
|
|
13294
|
-
|
|
13295
|
-
|
|
13296
|
-
|
|
13297
|
-
|
|
13306
|
+
if (typeof val === 'number' && Number.isFinite(val)) {
|
|
13307
|
+
anyValuePresent = true;
|
|
13308
|
+
const varName = `v${idx}`;
|
|
13309
|
+
vars[varName] = val;
|
|
13310
|
+
const pattern = new RegExp(`['"]?${escapeRegExp(scope)}['"]?`, 'g');
|
|
13311
|
+
expr = expr.replace(pattern, varName);
|
|
13312
|
+
} else {
|
|
13313
|
+
missingScopes.push(normalized);
|
|
13298
13314
|
}
|
|
13299
|
-
|
|
13300
|
-
|
|
13301
|
-
}
|
|
13302
|
-
if (invalidTypeScopes.length > 0) {
|
|
13315
|
+
});
|
|
13316
|
+
if (!anyValuePresent && missingScopes.length === normalizedScopes.length) {
|
|
13303
13317
|
return {
|
|
13304
13318
|
value: undefined,
|
|
13305
|
-
error:
|
|
13319
|
+
error: undefined
|
|
13306
13320
|
};
|
|
13307
13321
|
}
|
|
13308
13322
|
if (missingScopes.length > 0) {
|
|
13323
|
+
const uniqMissing = Array.from(new Set(missingScopes));
|
|
13309
13324
|
return {
|
|
13310
13325
|
value: undefined,
|
|
13311
|
-
error: `Please provide values for: ${
|
|
13326
|
+
error: `Please provide values for: ${uniqMissing.join(', ')}`
|
|
13312
13327
|
};
|
|
13313
13328
|
}
|
|
13314
13329
|
try {
|
|
13330
|
+
const parser = new Parser();
|
|
13331
|
+
const parsed = parser.parse(expr);
|
|
13315
13332
|
const result = parsed.evaluate(vars);
|
|
13316
13333
|
if (typeof result === 'number' && Number.isFinite(result)) {
|
|
13317
13334
|
return {
|
|
@@ -13321,15 +13338,30 @@ function evaluateExpression(expression, data) {
|
|
|
13321
13338
|
}
|
|
13322
13339
|
return {
|
|
13323
13340
|
value: undefined,
|
|
13324
|
-
error: '
|
|
13341
|
+
error: 'Invalid expression result (not a finite number).'
|
|
13325
13342
|
};
|
|
13326
13343
|
} catch (_a) {
|
|
13327
13344
|
return {
|
|
13328
13345
|
value: undefined,
|
|
13329
|
-
error: '
|
|
13346
|
+
error: 'Invalid expression syntax'
|
|
13330
13347
|
};
|
|
13331
13348
|
}
|
|
13332
13349
|
}
|
|
13350
|
+
function collectScopes(schema, base = '#') {
|
|
13351
|
+
if (!schema || typeof schema !== 'object') return [];
|
|
13352
|
+
const scopes = [];
|
|
13353
|
+
if (schema.type === 'object' && schema.properties && typeof schema.properties === 'object') {
|
|
13354
|
+
Object.entries(schema.properties).forEach(([key, subschema]) => {
|
|
13355
|
+
const here = base === '#' ? `#/properties/${key}` : `${base}/${key}`;
|
|
13356
|
+
scopes.push(here);
|
|
13357
|
+
scopes.push(...collectScopes(subschema, here));
|
|
13358
|
+
});
|
|
13359
|
+
}
|
|
13360
|
+
if (schema.type === 'array' && schema.items) {
|
|
13361
|
+
scopes.push(...collectScopes(schema.items, base));
|
|
13362
|
+
}
|
|
13363
|
+
return Array.from(new Set(scopes));
|
|
13364
|
+
}
|
|
13333
13365
|
|
|
13334
13366
|
const GoACalculation = props => {
|
|
13335
13367
|
var _a;
|
|
@@ -13341,33 +13373,36 @@ const GoACalculation = props => {
|
|
|
13341
13373
|
visible,
|
|
13342
13374
|
handleChange
|
|
13343
13375
|
} = props;
|
|
13344
|
-
const label = typeof (uischema === null || uischema === void 0 ? void 0 : uischema.label) === 'string' ? uischema.label : undefined;
|
|
13345
|
-
const expression = schema === null || schema === void 0 ? void 0 : schema.description;
|
|
13346
13376
|
const {
|
|
13347
13377
|
core
|
|
13348
13378
|
} = useJsonForms();
|
|
13379
|
+
const rootSchema = core === null || core === void 0 ? void 0 : core.schema;
|
|
13349
13380
|
const rootData = (_a = core === null || core === void 0 ? void 0 : core.data) !== null && _a !== void 0 ? _a : {};
|
|
13381
|
+
const label = typeof (uischema === null || uischema === void 0 ? void 0 : uischema.label) === 'string' ? uischema.label : undefined;
|
|
13382
|
+
const expression = schema === null || schema === void 0 ? void 0 : schema.description;
|
|
13383
|
+
const knownScopes = useMemo(() => collectScopes(rootSchema), [rootSchema]);
|
|
13350
13384
|
const [hasInteracted, setHasInteracted] = useState(false);
|
|
13351
|
-
const
|
|
13352
|
-
useEffect(() => {
|
|
13353
|
-
setHasInteracted(was => was ? true : true);
|
|
13354
|
-
}, [rootData]);
|
|
13385
|
+
const initialSnapshot = useRef(JSON.stringify(rootData));
|
|
13355
13386
|
useEffect(() => {
|
|
13356
|
-
if (
|
|
13387
|
+
if (hasInteracted) return;
|
|
13388
|
+
const now = JSON.stringify(rootData);
|
|
13389
|
+
if (now !== initialSnapshot.current) {
|
|
13357
13390
|
setHasInteracted(true);
|
|
13358
|
-
prevDataRef.current = rootData;
|
|
13359
13391
|
}
|
|
13360
|
-
}, [rootData]);
|
|
13392
|
+
}, [rootData, hasInteracted]);
|
|
13361
13393
|
const {
|
|
13362
13394
|
value: computedValue,
|
|
13363
13395
|
error
|
|
13364
|
-
} = evaluateExpression(expression, rootData
|
|
13396
|
+
} = evaluateExpression(expression, rootData, {
|
|
13397
|
+
knownScopes
|
|
13398
|
+
});
|
|
13365
13399
|
useEffect(() => {
|
|
13366
13400
|
if (computedValue !== undefined && typeof handleChange === 'function' && path) {
|
|
13367
13401
|
handleChange(path, computedValue);
|
|
13368
13402
|
}
|
|
13369
13403
|
}, [computedValue, handleChange, path]);
|
|
13370
|
-
const
|
|
13404
|
+
const isConfigError = !!error && (error.toLowerCase().includes('invalid scope') || error.toLowerCase().includes('expression syntax'));
|
|
13405
|
+
const showError = !!error && (isConfigError || hasInteracted);
|
|
13371
13406
|
return jsx(Visible, {
|
|
13372
13407
|
visible: visible,
|
|
13373
13408
|
children: jsx(GoAFormItem, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abgov/jsonforms-components",
|
|
3
|
-
"version": "2.38.
|
|
3
|
+
"version": "2.38.4",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Government of Alberta - React renderers for JSON Forms based on the design system.",
|
|
6
6
|
"repository": "https://github.com/GovAlta/adsp-monorepo",
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
import { JsonSchema } from '@jsonforms/core';
|
|
2
|
+
export interface EvalResult {
|
|
2
3
|
value?: number;
|
|
3
4
|
error?: string;
|
|
4
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a JSON Pointer–style scope like "#/properties/x" or "#/properties/arr/c3"
|
|
8
|
+
*/
|
|
5
9
|
export declare function resolveScope(scope: string, data: unknown): unknown;
|
|
6
|
-
export declare function evaluateSum(scope: string | undefined, data: unknown): EvaluationResult;
|
|
7
10
|
/**
|
|
8
|
-
*
|
|
9
|
-
* - Supports SUM(#/properties/arr/c3)
|
|
10
|
-
* - Supports arithmetic with JSON pointers:
|
|
11
|
-
* "#/properties/x * #/properties/y + #/properties/z"
|
|
12
|
-
*
|
|
13
|
-
* Returns { value, error } and NEVER throws.
|
|
11
|
+
* SUM(#/properties/arr/c3) helper
|
|
14
12
|
*/
|
|
15
|
-
export declare function
|
|
13
|
+
export declare function evaluateSum(scope: string, data: unknown, opts?: {
|
|
14
|
+
knownScopes?: string[];
|
|
15
|
+
}): EvalResult;
|
|
16
|
+
export declare function evaluateExpression(expression: string | undefined, data: unknown, opts?: {
|
|
17
|
+
knownScopes?: string[];
|
|
18
|
+
}): EvalResult;
|
|
19
|
+
export declare function collectScopes(schema: JsonSchema | undefined, base?: string): string[];
|
|
@@ -10,7 +10,7 @@ export declare const RowFlex: import("styled-components/dist/types").IStyledComp
|
|
|
10
10
|
export declare const RowFlexMenu: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
11
11
|
export declare const FlexTabs: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
12
12
|
export declare const FlexForm: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
13
|
-
export declare const
|
|
13
|
+
export declare const TabName: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
14
14
|
export declare const Trash: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
15
15
|
export declare const ListContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
16
16
|
export declare const IconPadding: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|