fastapi-rtk 2.5.0 → 2.6.0
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/.bundled/jsonforms/cjs/packages/jsonforms/src/complex/MantineTableControl/MantineTableControl.cjs +3 -2
- package/dist/.bundled/jsonforms/cjs/packages/jsonforms/src/hooks/useArrayHeaderErrors.cjs +44 -0
- package/dist/.bundled/jsonforms/cjs/packages/jsonforms/src/hooks/useNullableErrorProps.cjs +10 -14
- package/dist/.bundled/jsonforms/cjs/packages/jsonforms/src/layouts/Array/MantineArrayLayout.cjs +3 -2
- package/dist/.bundled/jsonforms/cjs/packages/jsonforms/src/utils/nullOptionErrors.cjs +31 -0
- package/dist/.bundled/jsonforms/esm/packages/jsonforms/src/complex/MantineTableControl/MantineTableControl.mjs +3 -2
- package/dist/.bundled/jsonforms/esm/packages/jsonforms/src/hooks/useArrayHeaderErrors.mjs +44 -0
- package/dist/.bundled/jsonforms/esm/packages/jsonforms/src/hooks/useNullableErrorProps.mjs +10 -14
- package/dist/.bundled/jsonforms/esm/packages/jsonforms/src/layouts/Array/MantineArrayLayout.mjs +3 -2
- package/dist/.bundled/jsonforms/esm/packages/jsonforms/src/utils/nullOptionErrors.mjs +31 -0
- package/dist/contexts/lib/ApiContext/ApiContext.d.ts +3 -2
- package/dist/contexts/lib/ApiContext/types.d.ts +7 -6
- package/dist/core/lib/Wrappers/ApiProvider/ApiProvider.d.ts +1 -1
- package/dist/core/lib/Wrappers/ApiProvider/types.d.ts +10 -4
- package/dist/jsonforms/cjs/complex/MantineTableControl/MantineTableControl.cjs +3 -2
- package/dist/jsonforms/cjs/hooks/useArrayHeaderErrors.cjs +44 -0
- package/dist/jsonforms/cjs/hooks/useNullableErrorProps.cjs +10 -14
- package/dist/jsonforms/cjs/layouts/Array/MantineArrayLayout.cjs +3 -2
- package/dist/jsonforms/cjs/utils/nullOptionErrors.cjs +31 -0
- package/dist/jsonforms/esm/complex/MantineTableControl/MantineTableControl.mjs +3 -2
- package/dist/jsonforms/esm/hooks/useArrayHeaderErrors.mjs +44 -0
- package/dist/jsonforms/esm/hooks/useNullableErrorProps.mjs +10 -14
- package/dist/jsonforms/esm/layouts/Array/MantineArrayLayout.mjs +3 -2
- package/dist/jsonforms/esm/utils/nullOptionErrors.mjs +31 -0
- package/dist/jsonforms/lib/hooks/useArrayHeaderErrors.d.ts +14 -0
- package/dist/jsonforms/lib/hooks/useArrayHeaderErrors.test.d.ts +1 -0
- package/dist/jsonforms/lib/hooks/useNullableErrorProps.d.ts +3 -0
- package/dist/jsonforms/lib/utils/nullOptionErrors.d.ts +27 -0
- package/dist/jsonforms/lib/utils/nullOptionErrors.test.d.ts +1 -0
- package/package.json +1 -1
|
@@ -11,6 +11,7 @@ const range = require("../../../../../_virtual/range.cjs");
|
|
|
11
11
|
const startCase = require("../../../../../_virtual/startCase.cjs");
|
|
12
12
|
const union = require("../../../../../_virtual/union.cjs");
|
|
13
13
|
const React = require("react");
|
|
14
|
+
const useArrayHeaderErrors = require("../../hooks/useArrayHeaderErrors.cjs");
|
|
14
15
|
const useContextProps = require("../../hooks/useContextProps.cjs");
|
|
15
16
|
const useNavigationComponent = require("../../hooks/useNavigationComponent.cjs");
|
|
16
17
|
const useThemeCustomizer = require("../../hooks/useThemeCustomizer.cjs");
|
|
@@ -239,7 +240,6 @@ const MantineTableControl = React.memo(function MantineTableControl2(props) {
|
|
|
239
240
|
schema,
|
|
240
241
|
rootSchema,
|
|
241
242
|
uischema,
|
|
242
|
-
errors,
|
|
243
243
|
visible,
|
|
244
244
|
enabled,
|
|
245
245
|
cells,
|
|
@@ -255,6 +255,7 @@ const MantineTableControl = React.memo(function MantineTableControl2(props) {
|
|
|
255
255
|
const isObjectSchema = isValidObjectSchema(schema);
|
|
256
256
|
const headerCells = isObjectSchema ? generateCells(TableHeaderCell, schema, path, enabled, cells) : void 0;
|
|
257
257
|
const isEnabled = enabled && !doDisableAdd;
|
|
258
|
+
const headerErrors = useArrayHeaderErrors.useArrayHeaderErrors(path, schema);
|
|
258
259
|
const [Component, _props] = useContextProps.useContextProps("Table", `${path}.Table`, {}, props, { withAllProps: false });
|
|
259
260
|
if (!visible) {
|
|
260
261
|
return null;
|
|
@@ -265,7 +266,7 @@ const MantineTableControl = React.memo(function MantineTableControl2(props) {
|
|
|
265
266
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
266
267
|
TableToolbar.TableToolbar,
|
|
267
268
|
{
|
|
268
|
-
errors,
|
|
269
|
+
errors: headerErrors,
|
|
269
270
|
label,
|
|
270
271
|
description,
|
|
271
272
|
addItem,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsonformsCore_esm = require("../../../../../../../.external/cjs/@jsonforms_core@3.7.0/@jsonforms/core/lib/jsonforms-core.esm.cjs");
|
|
4
|
+
const jsonformsReact_esm = require("../../../../../../../.external/cjs/@jsonforms_react@3.7.0_@jsonforms_core@3.7.0_react@19.2.3/@jsonforms/react/lib/jsonforms-react.esm.cjs");
|
|
5
|
+
const React = require("react");
|
|
6
|
+
const nullOptionErrors = require("../utils/nullOptionErrors.cjs");
|
|
7
|
+
const useArrayHeaderErrors = (path, schema) => {
|
|
8
|
+
const { core } = jsonformsReact_esm.useJsonForms();
|
|
9
|
+
const errors = core == null ? void 0 : core.errors;
|
|
10
|
+
return React.useMemo(() => {
|
|
11
|
+
var _a;
|
|
12
|
+
if (!(errors == null ? void 0 : errors.length)) {
|
|
13
|
+
return "";
|
|
14
|
+
}
|
|
15
|
+
const scoped = jsonformsCore_esm.errorsAt(
|
|
16
|
+
path,
|
|
17
|
+
schema,
|
|
18
|
+
(controlPath) => controlPath === path || controlPath.startsWith(`${path}.`)
|
|
19
|
+
)(errors);
|
|
20
|
+
const byField = /* @__PURE__ */ new Map();
|
|
21
|
+
for (const error of scoped) {
|
|
22
|
+
const group = byField.get(error.instancePath);
|
|
23
|
+
if (group) {
|
|
24
|
+
group.push(error);
|
|
25
|
+
} else {
|
|
26
|
+
byField.set(error.instancePath, [error]);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const messages = [];
|
|
30
|
+
for (const group of byField.values()) {
|
|
31
|
+
const [representative] = group;
|
|
32
|
+
const fieldMessages = group.map((error) => error.message).filter((message) => !!message);
|
|
33
|
+
messages.push(
|
|
34
|
+
...nullOptionErrors.resolveNullableErrorMessages(
|
|
35
|
+
representative.data,
|
|
36
|
+
nullOptionErrors.isNullableSchemaType((_a = representative.parentSchema) == null ? void 0 : _a.type),
|
|
37
|
+
fieldMessages
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
return jsonformsCore_esm.formatErrorMessage(messages);
|
|
42
|
+
}, [errors, path, schema]);
|
|
43
|
+
};
|
|
44
|
+
exports.useArrayHeaderErrors = useArrayHeaderErrors;
|
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const React = require("react");
|
|
4
|
-
const
|
|
5
|
-
const NULL_OPTION_ERRORS = /* @__PURE__ */ new Set([
|
|
6
|
-
"must be equal to one of the allowed values",
|
|
7
|
-
"must be equal to constant",
|
|
8
|
-
"must match exactly one schema in oneOf"
|
|
9
|
-
]);
|
|
10
|
-
const REQUIRED_ERROR = "is a required property";
|
|
4
|
+
const nullOptionErrors = require("../utils/nullOptionErrors.cjs");
|
|
11
5
|
function useNullableErrorProps(value, error, schema) {
|
|
12
6
|
return React.useMemo(() => {
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
switch (nullOptionErrors.nullableErrorAction(value, nullOptionErrors.isNullableSchemaType(schema.type))) {
|
|
8
|
+
case "keep":
|
|
9
|
+
return { error };
|
|
10
|
+
case "drop-options": {
|
|
11
|
+
const kept = error == null ? void 0 : error.filter((e) => !nullOptionErrors.NULL_OPTION_ERRORS.has(e.key ?? ""));
|
|
12
|
+
return { error: (kept == null ? void 0 : kept.length) ? kept : void 0 };
|
|
13
|
+
}
|
|
14
|
+
case "required":
|
|
15
|
+
return { error: nullOptionErrors.REQUIRED_ERROR };
|
|
15
16
|
}
|
|
16
|
-
if (isSchemaTypeInclude.isSchemaTypeInclude(schema.type ?? "", "null")) {
|
|
17
|
-
const kept = error == null ? void 0 : error.filter((e) => !NULL_OPTION_ERRORS.has(e.key ?? ""));
|
|
18
|
-
return { error: (kept == null ? void 0 : kept.length) ? kept : void 0 };
|
|
19
|
-
}
|
|
20
|
-
return { error: REQUIRED_ERROR };
|
|
21
17
|
}, [error, schema.type, value]);
|
|
22
18
|
}
|
|
23
19
|
exports.useNullableErrorProps = useNullableErrorProps;
|
package/dist/.bundled/jsonforms/cjs/packages/jsonforms/src/layouts/Array/MantineArrayLayout.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const useArrayHeaderErrors = require("../../hooks/useArrayHeaderErrors.cjs");
|
|
4
5
|
const useContextProps = require("../../hooks/useContextProps.cjs");
|
|
5
6
|
const jsonformsCore_esm = require("../../../../../../../../.external/cjs/@jsonforms_core@3.7.0/@jsonforms/core/lib/jsonforms-core.esm.cjs");
|
|
6
7
|
const core = require("@mantine/core");
|
|
@@ -17,7 +18,6 @@ const Component = (props) => {
|
|
|
17
18
|
path,
|
|
18
19
|
schema,
|
|
19
20
|
uischema,
|
|
20
|
-
errors,
|
|
21
21
|
addItem,
|
|
22
22
|
renderers,
|
|
23
23
|
cells,
|
|
@@ -38,6 +38,7 @@ const Component = (props) => {
|
|
|
38
38
|
const [Component2, _props] = useContextProps.useContextProps("Array.Accordion", `${path}.Accordion`, {}, props, {
|
|
39
39
|
withAllProps: false
|
|
40
40
|
});
|
|
41
|
+
const headerErrors = useArrayHeaderErrors.useArrayHeaderErrors(path, schema);
|
|
41
42
|
return /* @__PURE__ */ jsxRuntime.jsxs(core.Stack, { children: [
|
|
42
43
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
43
44
|
ArrayToolbar.ArrayLayoutToolbar,
|
|
@@ -45,7 +46,7 @@ const Component = (props) => {
|
|
|
45
46
|
translations,
|
|
46
47
|
label: jsonformsCore_esm.computeLabel(label, required ?? false, appliedUiSchemaOptions.hideRequiredAsterisk),
|
|
47
48
|
description,
|
|
48
|
-
errors,
|
|
49
|
+
errors: headerErrors,
|
|
49
50
|
path,
|
|
50
51
|
enabled,
|
|
51
52
|
addItem,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const isSchemaTypeInclude = require("./isSchemaTypeInclude.cjs");
|
|
4
|
+
const NULL_OPTION_ERRORS = /* @__PURE__ */ new Set([
|
|
5
|
+
"must be equal to one of the allowed values",
|
|
6
|
+
"must be equal to constant",
|
|
7
|
+
"must match exactly one schema in oneOf"
|
|
8
|
+
]);
|
|
9
|
+
const REQUIRED_ERROR = "is a required property";
|
|
10
|
+
const nullableErrorAction = (value, nullable) => {
|
|
11
|
+
if (value !== null && value !== "") {
|
|
12
|
+
return "keep";
|
|
13
|
+
}
|
|
14
|
+
return nullable ? "drop-options" : "required";
|
|
15
|
+
};
|
|
16
|
+
const resolveNullableErrorMessages = (value, nullable, messages) => {
|
|
17
|
+
switch (nullableErrorAction(value, nullable)) {
|
|
18
|
+
case "keep":
|
|
19
|
+
return messages;
|
|
20
|
+
case "drop-options":
|
|
21
|
+
return messages.filter((message) => !NULL_OPTION_ERRORS.has(message));
|
|
22
|
+
case "required":
|
|
23
|
+
return [REQUIRED_ERROR];
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const isNullableSchemaType = (type) => isSchemaTypeInclude.isSchemaTypeInclude(type ?? "", "null");
|
|
27
|
+
exports.NULL_OPTION_ERRORS = NULL_OPTION_ERRORS;
|
|
28
|
+
exports.REQUIRED_ERROR = REQUIRED_ERROR;
|
|
29
|
+
exports.isNullableSchemaType = isNullableSchemaType;
|
|
30
|
+
exports.nullableErrorAction = nullableErrorAction;
|
|
31
|
+
exports.resolveNullableErrorMessages = resolveNullableErrorMessages;
|
|
@@ -9,6 +9,7 @@ import range from "../../../../../_virtual/range.mjs";
|
|
|
9
9
|
import startCase from "../../../../../_virtual/startCase.mjs";
|
|
10
10
|
import union from "../../../../../_virtual/union.mjs";
|
|
11
11
|
import React, { useMemo, memo } from "react";
|
|
12
|
+
import { useArrayHeaderErrors } from "../../hooks/useArrayHeaderErrors.mjs";
|
|
12
13
|
import { useContextProps } from "../../hooks/useContextProps.mjs";
|
|
13
14
|
import { useNavigationComponent } from "../../hooks/useNavigationComponent.mjs";
|
|
14
15
|
import { useThemeCustomizer } from "../../hooks/useThemeCustomizer.mjs";
|
|
@@ -237,7 +238,6 @@ const MantineTableControl = memo(function MantineTableControl2(props) {
|
|
|
237
238
|
schema,
|
|
238
239
|
rootSchema,
|
|
239
240
|
uischema,
|
|
240
|
-
errors,
|
|
241
241
|
visible,
|
|
242
242
|
enabled,
|
|
243
243
|
cells,
|
|
@@ -253,6 +253,7 @@ const MantineTableControl = memo(function MantineTableControl2(props) {
|
|
|
253
253
|
const isObjectSchema = isValidObjectSchema(schema);
|
|
254
254
|
const headerCells = isObjectSchema ? generateCells(TableHeaderCell, schema, path, enabled, cells) : void 0;
|
|
255
255
|
const isEnabled = enabled && !doDisableAdd;
|
|
256
|
+
const headerErrors = useArrayHeaderErrors(path, schema);
|
|
256
257
|
const [Component, _props] = useContextProps("Table", `${path}.Table`, {}, props, { withAllProps: false });
|
|
257
258
|
if (!visible) {
|
|
258
259
|
return null;
|
|
@@ -263,7 +264,7 @@ const MantineTableControl = memo(function MantineTableControl2(props) {
|
|
|
263
264
|
/* @__PURE__ */ jsx(
|
|
264
265
|
TableToolbar,
|
|
265
266
|
{
|
|
266
|
-
errors,
|
|
267
|
+
errors: headerErrors,
|
|
267
268
|
label,
|
|
268
269
|
description,
|
|
269
270
|
addItem,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { errorsAt, formatErrorMessage } from "../../../../../../../.external/esm/@jsonforms_core@3.7.0/@jsonforms/core/lib/jsonforms-core.esm.mjs";
|
|
2
|
+
import { useJsonForms } from "../../../../../../../.external/esm/@jsonforms_react@3.7.0_@jsonforms_core@3.7.0_react@19.2.3/@jsonforms/react/lib/jsonforms-react.esm.mjs";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { resolveNullableErrorMessages, isNullableSchemaType } from "../utils/nullOptionErrors.mjs";
|
|
5
|
+
const useArrayHeaderErrors = (path, schema) => {
|
|
6
|
+
const { core } = useJsonForms();
|
|
7
|
+
const errors = core == null ? void 0 : core.errors;
|
|
8
|
+
return useMemo(() => {
|
|
9
|
+
var _a;
|
|
10
|
+
if (!(errors == null ? void 0 : errors.length)) {
|
|
11
|
+
return "";
|
|
12
|
+
}
|
|
13
|
+
const scoped = errorsAt(
|
|
14
|
+
path,
|
|
15
|
+
schema,
|
|
16
|
+
(controlPath) => controlPath === path || controlPath.startsWith(`${path}.`)
|
|
17
|
+
)(errors);
|
|
18
|
+
const byField = /* @__PURE__ */ new Map();
|
|
19
|
+
for (const error of scoped) {
|
|
20
|
+
const group = byField.get(error.instancePath);
|
|
21
|
+
if (group) {
|
|
22
|
+
group.push(error);
|
|
23
|
+
} else {
|
|
24
|
+
byField.set(error.instancePath, [error]);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const messages = [];
|
|
28
|
+
for (const group of byField.values()) {
|
|
29
|
+
const [representative] = group;
|
|
30
|
+
const fieldMessages = group.map((error) => error.message).filter((message) => !!message);
|
|
31
|
+
messages.push(
|
|
32
|
+
...resolveNullableErrorMessages(
|
|
33
|
+
representative.data,
|
|
34
|
+
isNullableSchemaType((_a = representative.parentSchema) == null ? void 0 : _a.type),
|
|
35
|
+
fieldMessages
|
|
36
|
+
)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return formatErrorMessage(messages);
|
|
40
|
+
}, [errors, path, schema]);
|
|
41
|
+
};
|
|
42
|
+
export {
|
|
43
|
+
useArrayHeaderErrors
|
|
44
|
+
};
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
|
-
import {
|
|
3
|
-
const NULL_OPTION_ERRORS = /* @__PURE__ */ new Set([
|
|
4
|
-
"must be equal to one of the allowed values",
|
|
5
|
-
"must be equal to constant",
|
|
6
|
-
"must match exactly one schema in oneOf"
|
|
7
|
-
]);
|
|
8
|
-
const REQUIRED_ERROR = "is a required property";
|
|
2
|
+
import { nullableErrorAction, isNullableSchemaType, REQUIRED_ERROR, NULL_OPTION_ERRORS } from "../utils/nullOptionErrors.mjs";
|
|
9
3
|
function useNullableErrorProps(value, error, schema) {
|
|
10
4
|
return useMemo(() => {
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
switch (nullableErrorAction(value, isNullableSchemaType(schema.type))) {
|
|
6
|
+
case "keep":
|
|
7
|
+
return { error };
|
|
8
|
+
case "drop-options": {
|
|
9
|
+
const kept = error == null ? void 0 : error.filter((e) => !NULL_OPTION_ERRORS.has(e.key ?? ""));
|
|
10
|
+
return { error: (kept == null ? void 0 : kept.length) ? kept : void 0 };
|
|
11
|
+
}
|
|
12
|
+
case "required":
|
|
13
|
+
return { error: REQUIRED_ERROR };
|
|
13
14
|
}
|
|
14
|
-
if (isSchemaTypeInclude(schema.type ?? "", "null")) {
|
|
15
|
-
const kept = error == null ? void 0 : error.filter((e) => !NULL_OPTION_ERRORS.has(e.key ?? ""));
|
|
16
|
-
return { error: (kept == null ? void 0 : kept.length) ? kept : void 0 };
|
|
17
|
-
}
|
|
18
|
-
return { error: REQUIRED_ERROR };
|
|
19
15
|
}, [error, schema.type, value]);
|
|
20
16
|
}
|
|
21
17
|
export {
|
package/dist/.bundled/jsonforms/esm/packages/jsonforms/src/layouts/Array/MantineArrayLayout.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useArrayHeaderErrors } from "../../hooks/useArrayHeaderErrors.mjs";
|
|
2
3
|
import { useContextProps } from "../../hooks/useContextProps.mjs";
|
|
3
4
|
import { createDefaultValue, computeLabel, Paths } from "../../../../../../../../.external/esm/@jsonforms_core@3.7.0/@jsonforms/core/lib/jsonforms-core.esm.mjs";
|
|
4
5
|
import { Stack, Accordion, Text } from "@mantine/core";
|
|
@@ -15,7 +16,6 @@ const Component = (props) => {
|
|
|
15
16
|
path,
|
|
16
17
|
schema,
|
|
17
18
|
uischema,
|
|
18
|
-
errors,
|
|
19
19
|
addItem,
|
|
20
20
|
renderers,
|
|
21
21
|
cells,
|
|
@@ -36,6 +36,7 @@ const Component = (props) => {
|
|
|
36
36
|
const [Component2, _props] = useContextProps("Array.Accordion", `${path}.Accordion`, {}, props, {
|
|
37
37
|
withAllProps: false
|
|
38
38
|
});
|
|
39
|
+
const headerErrors = useArrayHeaderErrors(path, schema);
|
|
39
40
|
return /* @__PURE__ */ jsxs(Stack, { children: [
|
|
40
41
|
/* @__PURE__ */ jsx(
|
|
41
42
|
ArrayLayoutToolbar,
|
|
@@ -43,7 +44,7 @@ const Component = (props) => {
|
|
|
43
44
|
translations,
|
|
44
45
|
label: computeLabel(label, required ?? false, appliedUiSchemaOptions.hideRequiredAsterisk),
|
|
45
46
|
description,
|
|
46
|
-
errors,
|
|
47
|
+
errors: headerErrors,
|
|
47
48
|
path,
|
|
48
49
|
enabled,
|
|
49
50
|
addItem,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { isSchemaTypeInclude } from "./isSchemaTypeInclude.mjs";
|
|
2
|
+
const NULL_OPTION_ERRORS = /* @__PURE__ */ new Set([
|
|
3
|
+
"must be equal to one of the allowed values",
|
|
4
|
+
"must be equal to constant",
|
|
5
|
+
"must match exactly one schema in oneOf"
|
|
6
|
+
]);
|
|
7
|
+
const REQUIRED_ERROR = "is a required property";
|
|
8
|
+
const nullableErrorAction = (value, nullable) => {
|
|
9
|
+
if (value !== null && value !== "") {
|
|
10
|
+
return "keep";
|
|
11
|
+
}
|
|
12
|
+
return nullable ? "drop-options" : "required";
|
|
13
|
+
};
|
|
14
|
+
const resolveNullableErrorMessages = (value, nullable, messages) => {
|
|
15
|
+
switch (nullableErrorAction(value, nullable)) {
|
|
16
|
+
case "keep":
|
|
17
|
+
return messages;
|
|
18
|
+
case "drop-options":
|
|
19
|
+
return messages.filter((message) => !NULL_OPTION_ERRORS.has(message));
|
|
20
|
+
case "required":
|
|
21
|
+
return [REQUIRED_ERROR];
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const isNullableSchemaType = (type) => isSchemaTypeInclude(type ?? "", "null");
|
|
25
|
+
export {
|
|
26
|
+
NULL_OPTION_ERRORS,
|
|
27
|
+
REQUIRED_ERROR,
|
|
28
|
+
isNullableSchemaType,
|
|
29
|
+
nullableErrorAction,
|
|
30
|
+
resolveNullableErrorMessages
|
|
31
|
+
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { SafeContextOptions } from 'fastapi-rtk/utils';
|
|
2
2
|
import { ApiContextValue, ApiTypeOverrides, EntryRow, UseApiResult } from './types';
|
|
3
|
-
export declare const ApiContextProvider: import('react').Provider<ApiContextValue<import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow> | null>, useApiProvider: (options?: SafeContextOptions<ApiContextValue<import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow>>) => ApiContextValue<import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow>;
|
|
3
|
+
export declare const ApiContextProvider: import('react').Provider<ApiContextValue<import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, object> | null>, useApiProvider: (options?: SafeContextOptions<ApiContextValue<import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, object>>) => ApiContextValue<import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, import('fastapi-rtk/api-types').ResultRow, object>;
|
|
4
4
|
/**
|
|
5
5
|
* Access the API context.
|
|
6
6
|
*
|
|
7
7
|
* @typeParam TDefault - Uniform row/payload type applied to every operation. Defaults to the dynamic `EntryRow`.
|
|
8
8
|
* @typeParam TOverrides - Per-operation overrides (`list` / `get` / `add` / `edit`); each replaces `TDefault` for that operation only.
|
|
9
|
+
* @typeParam TQuery - Custom query-param keys forwarded to the backend, surfaced typed on `queryParams` / `setQueryParams`.
|
|
9
10
|
* @param options - Options for the context hook.
|
|
10
11
|
* @returns The API context object, with `data`, `getEntry`, `addEntry`, `updateEntry`, etc. typed per operation.
|
|
11
12
|
*/
|
|
12
|
-
export declare const useApi: <TDefault = EntryRow, TOverrides extends ApiTypeOverrides = ApiTypeOverrides>(options?: SafeContextOptions<UseApiResult<TDefault, TOverrides>>) => UseApiResult<TDefault, TOverrides>;
|
|
13
|
+
export declare const useApi: <TDefault = EntryRow, TOverrides extends ApiTypeOverrides = ApiTypeOverrides, TQuery extends object = object>(options?: SafeContextOptions<UseApiResult<TDefault, TOverrides, TQuery>>) => UseApiResult<TDefault, TOverrides, TQuery>;
|
|
@@ -121,8 +121,9 @@ export type OpType<TOverrides extends ApiTypeOverrides, K extends keyof ApiTypeO
|
|
|
121
121
|
* @typeParam TGet - Shape of a single fetched/affected record (`getEntry`, and the record returned by `addEntry` / `updateEntry`).
|
|
122
122
|
* @typeParam TAdd - Payload accepted by `addEntry`.
|
|
123
123
|
* @typeParam TEdit - Payload accepted by `updateEntry`.
|
|
124
|
+
* @typeParam TQuery - Custom query-param keys forwarded to the backend, intersected onto `queryParams` and `setQueryParams`.
|
|
124
125
|
*/
|
|
125
|
-
export interface ApiContextValue<TList = EntryRow, TGet = EntryRow, TAdd = EntryRow, TEdit = EntryRow> {
|
|
126
|
+
export interface ApiContextValue<TList = EntryRow, TGet = EntryRow, TAdd = EntryRow, TEdit = EntryRow, TQuery extends object = object> {
|
|
126
127
|
/** The API path. */
|
|
127
128
|
path: string;
|
|
128
129
|
/** Information about the API, including schemas, UI schemas, and the normalized add/edit form blocks. */
|
|
@@ -130,7 +131,7 @@ export interface ApiContextValue<TList = EntryRow, TGet = EntryRow, TAdd = Entry
|
|
|
130
131
|
/** The data returned by the API. */
|
|
131
132
|
data?: APIData<TList>;
|
|
132
133
|
/** The query parameters used in the API request. */
|
|
133
|
-
queryParams?: APIQueryParams;
|
|
134
|
+
queryParams?: APIQueryParams & TQuery;
|
|
134
135
|
/** Indicates whether the API request is currently loading. */
|
|
135
136
|
loading: boolean;
|
|
136
137
|
/** Indicates whether the API info request is currently loading. */
|
|
@@ -154,7 +155,7 @@ export interface ApiContextValue<TList = EntryRow, TGet = EntryRow, TAdd = Entry
|
|
|
154
155
|
/** An object containing special keys for the API query, such as 'all' and 'actions'. */
|
|
155
156
|
specialKey: APISpecialKey;
|
|
156
157
|
/** A function to update the query parameters. */
|
|
157
|
-
setQueryParams: (partialQueryParams: Partial<APIQueryParams> | ((prev: APIQueryParams) => Partial<APIQueryParams>)) => void;
|
|
158
|
+
setQueryParams: (partialQueryParams: Partial<APIQueryParams & TQuery> | ((prev: APIQueryParams & TQuery) => Partial<APIQueryParams & TQuery>)) => void;
|
|
158
159
|
/** A function to refetch the data from the API. */
|
|
159
160
|
refetch: (options?: {
|
|
160
161
|
force?: boolean;
|
|
@@ -185,7 +186,7 @@ export interface ApiContextValue<TList = EntryRow, TGet = EntryRow, TAdd = Entry
|
|
|
185
186
|
resetError: () => void;
|
|
186
187
|
}
|
|
187
188
|
/**
|
|
188
|
-
* The `ApiContextValue` returned by `useApi<TDefault, TOverrides>`: the uniform `TDefault` applied to
|
|
189
|
-
* every operation, with any `TOverrides` keys replacing it per operation.
|
|
189
|
+
* The `ApiContextValue` returned by `useApi<TDefault, TOverrides, TQuery>`: the uniform `TDefault` applied to
|
|
190
|
+
* every operation, with any `TOverrides` keys replacing it per operation, and `TQuery` adding custom query-param keys.
|
|
190
191
|
*/
|
|
191
|
-
export type UseApiResult<TDefault = EntryRow, TOverrides extends ApiTypeOverrides = ApiTypeOverrides> = ApiContextValue<OpType<TOverrides, 'list', TDefault>, OpType<TOverrides, 'get', TDefault>, OpType<TOverrides, 'add', TDefault>, OpType<TOverrides, 'edit', TDefault
|
|
192
|
+
export type UseApiResult<TDefault = EntryRow, TOverrides extends ApiTypeOverrides = ApiTypeOverrides, TQuery extends object = object> = ApiContextValue<OpType<TOverrides, 'list', TDefault>, OpType<TOverrides, 'get', TDefault>, OpType<TOverrides, 'add', TDefault>, OpType<TOverrides, 'edit', TDefault>, TQuery>;
|
|
@@ -3,7 +3,7 @@ import { ApiProviderProps, WithApiProviderOptions } from './types';
|
|
|
3
3
|
/**
|
|
4
4
|
* Provides the API context, bulk actions context, and form contexts to its children.
|
|
5
5
|
*/
|
|
6
|
-
export declare function ApiProvider(props: ApiProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export declare function ApiProvider<TQuery extends object = object>(props: ApiProviderProps<TQuery>): import("react/jsx-runtime").JSX.Element;
|
|
7
7
|
/**
|
|
8
8
|
* Higher-order component to wrap a component with ApiProvider.
|
|
9
9
|
*
|
|
@@ -3,12 +3,18 @@ import { InfiniteData, QueryKey, UseInfiniteQueryOptions, UseQueryOptions } from
|
|
|
3
3
|
import { PropsWithChildren } from 'react';
|
|
4
4
|
import { InfoQueryData, RelationParam } from './hooks/types';
|
|
5
5
|
import { QueryParams } from './utils/types';
|
|
6
|
-
/**
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Props accepted by the `ApiProvider` component.
|
|
8
|
+
*
|
|
9
|
+
* @typeParam TQuery - Custom query-param keys forwarded to the backend (read off `request.query_params`).
|
|
10
|
+
* Surfaced typed on `initialQueryParams`; pass the same shape to `useApi<…, TQuery>()` to type `queryParams` /
|
|
11
|
+
* `setQueryParams` (React context cannot carry the Provider's type param to a distant `useApi` call).
|
|
12
|
+
*/
|
|
13
|
+
export type ApiProviderProps<TQuery extends object = object> = PropsWithChildren<{
|
|
8
14
|
/** The name of the resource to be used in the API path. */
|
|
9
15
|
resource_name?: string;
|
|
10
|
-
/** The initial query parameters to be used in the API requests. */
|
|
11
|
-
initialQueryParams?: QueryParams
|
|
16
|
+
/** The initial query parameters to be used in the API requests. May include custom keys (typed via `TQuery`) forwarded to the backend. */
|
|
17
|
+
initialQueryParams?: QueryParams & Partial<TQuery>;
|
|
12
18
|
/** The relation to be used in the API requests. */
|
|
13
19
|
relation?: RelationParam;
|
|
14
20
|
/** Whether to fetch the `info` for the API requests when the component mounts. */
|
|
@@ -11,6 +11,7 @@ const range = require("../../_virtual/range.cjs");
|
|
|
11
11
|
const startCase = require("../../_virtual/startCase.cjs");
|
|
12
12
|
const union = require("../../_virtual/union.cjs");
|
|
13
13
|
const React = require("react");
|
|
14
|
+
const useArrayHeaderErrors = require("../../hooks/useArrayHeaderErrors.cjs");
|
|
14
15
|
const useContextProps = require("../../hooks/useContextProps.cjs");
|
|
15
16
|
const useNavigationComponent = require("../../hooks/useNavigationComponent.cjs");
|
|
16
17
|
const useThemeCustomizer = require("../../hooks/useThemeCustomizer.cjs");
|
|
@@ -239,7 +240,6 @@ const MantineTableControl = React.memo(function MantineTableControl2(props) {
|
|
|
239
240
|
schema,
|
|
240
241
|
rootSchema,
|
|
241
242
|
uischema,
|
|
242
|
-
errors,
|
|
243
243
|
visible,
|
|
244
244
|
enabled,
|
|
245
245
|
cells,
|
|
@@ -255,6 +255,7 @@ const MantineTableControl = React.memo(function MantineTableControl2(props) {
|
|
|
255
255
|
const isObjectSchema = isValidObjectSchema(schema);
|
|
256
256
|
const headerCells = isObjectSchema ? generateCells(TableHeaderCell, schema, path, enabled, cells) : void 0;
|
|
257
257
|
const isEnabled = enabled && !doDisableAdd;
|
|
258
|
+
const headerErrors = useArrayHeaderErrors.useArrayHeaderErrors(path, schema);
|
|
258
259
|
const [Component, _props] = useContextProps.useContextProps("Table", `${path}.Table`, {}, props, { withAllProps: false });
|
|
259
260
|
if (!visible) {
|
|
260
261
|
return null;
|
|
@@ -265,7 +266,7 @@ const MantineTableControl = React.memo(function MantineTableControl2(props) {
|
|
|
265
266
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
266
267
|
TableToolbar.TableToolbar,
|
|
267
268
|
{
|
|
268
|
-
errors,
|
|
269
|
+
errors: headerErrors,
|
|
269
270
|
label,
|
|
270
271
|
description,
|
|
271
272
|
addItem,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const core = require("@jsonforms/core");
|
|
4
|
+
const react = require("@jsonforms/react");
|
|
5
|
+
const React = require("react");
|
|
6
|
+
const nullOptionErrors = require("../utils/nullOptionErrors.cjs");
|
|
7
|
+
const useArrayHeaderErrors = (path, schema) => {
|
|
8
|
+
const { core: core$1 } = react.useJsonForms();
|
|
9
|
+
const errors = core$1 == null ? void 0 : core$1.errors;
|
|
10
|
+
return React.useMemo(() => {
|
|
11
|
+
var _a;
|
|
12
|
+
if (!(errors == null ? void 0 : errors.length)) {
|
|
13
|
+
return "";
|
|
14
|
+
}
|
|
15
|
+
const scoped = core.errorsAt(
|
|
16
|
+
path,
|
|
17
|
+
schema,
|
|
18
|
+
(controlPath) => controlPath === path || controlPath.startsWith(`${path}.`)
|
|
19
|
+
)(errors);
|
|
20
|
+
const byField = /* @__PURE__ */ new Map();
|
|
21
|
+
for (const error of scoped) {
|
|
22
|
+
const group = byField.get(error.instancePath);
|
|
23
|
+
if (group) {
|
|
24
|
+
group.push(error);
|
|
25
|
+
} else {
|
|
26
|
+
byField.set(error.instancePath, [error]);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const messages = [];
|
|
30
|
+
for (const group of byField.values()) {
|
|
31
|
+
const [representative] = group;
|
|
32
|
+
const fieldMessages = group.map((error) => error.message).filter((message) => !!message);
|
|
33
|
+
messages.push(
|
|
34
|
+
...nullOptionErrors.resolveNullableErrorMessages(
|
|
35
|
+
representative.data,
|
|
36
|
+
nullOptionErrors.isNullableSchemaType((_a = representative.parentSchema) == null ? void 0 : _a.type),
|
|
37
|
+
fieldMessages
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
return core.formatErrorMessage(messages);
|
|
42
|
+
}, [errors, path, schema]);
|
|
43
|
+
};
|
|
44
|
+
exports.useArrayHeaderErrors = useArrayHeaderErrors;
|
|
@@ -1,23 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const React = require("react");
|
|
4
|
-
const
|
|
5
|
-
const NULL_OPTION_ERRORS = /* @__PURE__ */ new Set([
|
|
6
|
-
"must be equal to one of the allowed values",
|
|
7
|
-
"must be equal to constant",
|
|
8
|
-
"must match exactly one schema in oneOf"
|
|
9
|
-
]);
|
|
10
|
-
const REQUIRED_ERROR = "is a required property";
|
|
4
|
+
const nullOptionErrors = require("../utils/nullOptionErrors.cjs");
|
|
11
5
|
function useNullableErrorProps(value, error, schema) {
|
|
12
6
|
return React.useMemo(() => {
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
switch (nullOptionErrors.nullableErrorAction(value, nullOptionErrors.isNullableSchemaType(schema.type))) {
|
|
8
|
+
case "keep":
|
|
9
|
+
return { error };
|
|
10
|
+
case "drop-options": {
|
|
11
|
+
const kept = error == null ? void 0 : error.filter((e) => !nullOptionErrors.NULL_OPTION_ERRORS.has(e.key ?? ""));
|
|
12
|
+
return { error: (kept == null ? void 0 : kept.length) ? kept : void 0 };
|
|
13
|
+
}
|
|
14
|
+
case "required":
|
|
15
|
+
return { error: nullOptionErrors.REQUIRED_ERROR };
|
|
15
16
|
}
|
|
16
|
-
if (isSchemaTypeInclude.isSchemaTypeInclude(schema.type ?? "", "null")) {
|
|
17
|
-
const kept = error == null ? void 0 : error.filter((e) => !NULL_OPTION_ERRORS.has(e.key ?? ""));
|
|
18
|
-
return { error: (kept == null ? void 0 : kept.length) ? kept : void 0 };
|
|
19
|
-
}
|
|
20
|
-
return { error: REQUIRED_ERROR };
|
|
21
17
|
}, [error, schema.type, value]);
|
|
22
18
|
}
|
|
23
19
|
exports.useNullableErrorProps = useNullableErrorProps;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const useArrayHeaderErrors = require("../../hooks/useArrayHeaderErrors.cjs");
|
|
4
5
|
const useContextProps = require("../../hooks/useContextProps.cjs");
|
|
5
6
|
const core = require("@jsonforms/core");
|
|
6
7
|
const core$1 = require("@mantine/core");
|
|
@@ -17,7 +18,6 @@ const Component = (props) => {
|
|
|
17
18
|
path,
|
|
18
19
|
schema,
|
|
19
20
|
uischema,
|
|
20
|
-
errors,
|
|
21
21
|
addItem,
|
|
22
22
|
renderers,
|
|
23
23
|
cells,
|
|
@@ -38,6 +38,7 @@ const Component = (props) => {
|
|
|
38
38
|
const [Component2, _props] = useContextProps.useContextProps("Array.Accordion", `${path}.Accordion`, {}, props, {
|
|
39
39
|
withAllProps: false
|
|
40
40
|
});
|
|
41
|
+
const headerErrors = useArrayHeaderErrors.useArrayHeaderErrors(path, schema);
|
|
41
42
|
return /* @__PURE__ */ jsxRuntime.jsxs(core$1.Stack, { children: [
|
|
42
43
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
43
44
|
ArrayToolbar.ArrayLayoutToolbar,
|
|
@@ -45,7 +46,7 @@ const Component = (props) => {
|
|
|
45
46
|
translations,
|
|
46
47
|
label: core.computeLabel(label, required ?? false, appliedUiSchemaOptions.hideRequiredAsterisk),
|
|
47
48
|
description,
|
|
48
|
-
errors,
|
|
49
|
+
errors: headerErrors,
|
|
49
50
|
path,
|
|
50
51
|
enabled,
|
|
51
52
|
addItem,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const isSchemaTypeInclude = require("./isSchemaTypeInclude.cjs");
|
|
4
|
+
const NULL_OPTION_ERRORS = /* @__PURE__ */ new Set([
|
|
5
|
+
"must be equal to one of the allowed values",
|
|
6
|
+
"must be equal to constant",
|
|
7
|
+
"must match exactly one schema in oneOf"
|
|
8
|
+
]);
|
|
9
|
+
const REQUIRED_ERROR = "is a required property";
|
|
10
|
+
const nullableErrorAction = (value, nullable) => {
|
|
11
|
+
if (value !== null && value !== "") {
|
|
12
|
+
return "keep";
|
|
13
|
+
}
|
|
14
|
+
return nullable ? "drop-options" : "required";
|
|
15
|
+
};
|
|
16
|
+
const resolveNullableErrorMessages = (value, nullable, messages) => {
|
|
17
|
+
switch (nullableErrorAction(value, nullable)) {
|
|
18
|
+
case "keep":
|
|
19
|
+
return messages;
|
|
20
|
+
case "drop-options":
|
|
21
|
+
return messages.filter((message) => !NULL_OPTION_ERRORS.has(message));
|
|
22
|
+
case "required":
|
|
23
|
+
return [REQUIRED_ERROR];
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const isNullableSchemaType = (type) => isSchemaTypeInclude.isSchemaTypeInclude(type ?? "", "null");
|
|
27
|
+
exports.NULL_OPTION_ERRORS = NULL_OPTION_ERRORS;
|
|
28
|
+
exports.REQUIRED_ERROR = REQUIRED_ERROR;
|
|
29
|
+
exports.isNullableSchemaType = isNullableSchemaType;
|
|
30
|
+
exports.nullableErrorAction = nullableErrorAction;
|
|
31
|
+
exports.resolveNullableErrorMessages = resolveNullableErrorMessages;
|
|
@@ -9,6 +9,7 @@ import range from "../../_virtual/range.mjs";
|
|
|
9
9
|
import startCase from "../../_virtual/startCase.mjs";
|
|
10
10
|
import union from "../../_virtual/union.mjs";
|
|
11
11
|
import React, { useMemo, memo } from "react";
|
|
12
|
+
import { useArrayHeaderErrors } from "../../hooks/useArrayHeaderErrors.mjs";
|
|
12
13
|
import { useContextProps } from "../../hooks/useContextProps.mjs";
|
|
13
14
|
import { useNavigationComponent } from "../../hooks/useNavigationComponent.mjs";
|
|
14
15
|
import { useThemeCustomizer } from "../../hooks/useThemeCustomizer.mjs";
|
|
@@ -237,7 +238,6 @@ const MantineTableControl = memo(function MantineTableControl2(props) {
|
|
|
237
238
|
schema,
|
|
238
239
|
rootSchema,
|
|
239
240
|
uischema,
|
|
240
|
-
errors,
|
|
241
241
|
visible,
|
|
242
242
|
enabled,
|
|
243
243
|
cells,
|
|
@@ -253,6 +253,7 @@ const MantineTableControl = memo(function MantineTableControl2(props) {
|
|
|
253
253
|
const isObjectSchema = isValidObjectSchema(schema);
|
|
254
254
|
const headerCells = isObjectSchema ? generateCells(TableHeaderCell, schema, path, enabled, cells) : void 0;
|
|
255
255
|
const isEnabled = enabled && !doDisableAdd;
|
|
256
|
+
const headerErrors = useArrayHeaderErrors(path, schema);
|
|
256
257
|
const [Component, _props] = useContextProps("Table", `${path}.Table`, {}, props, { withAllProps: false });
|
|
257
258
|
if (!visible) {
|
|
258
259
|
return null;
|
|
@@ -263,7 +264,7 @@ const MantineTableControl = memo(function MantineTableControl2(props) {
|
|
|
263
264
|
/* @__PURE__ */ jsx(
|
|
264
265
|
TableToolbar,
|
|
265
266
|
{
|
|
266
|
-
errors,
|
|
267
|
+
errors: headerErrors,
|
|
267
268
|
label,
|
|
268
269
|
description,
|
|
269
270
|
addItem,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { errorsAt, formatErrorMessage } from "@jsonforms/core";
|
|
2
|
+
import { useJsonForms } from "@jsonforms/react";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { resolveNullableErrorMessages, isNullableSchemaType } from "../utils/nullOptionErrors.mjs";
|
|
5
|
+
const useArrayHeaderErrors = (path, schema) => {
|
|
6
|
+
const { core } = useJsonForms();
|
|
7
|
+
const errors = core == null ? void 0 : core.errors;
|
|
8
|
+
return useMemo(() => {
|
|
9
|
+
var _a;
|
|
10
|
+
if (!(errors == null ? void 0 : errors.length)) {
|
|
11
|
+
return "";
|
|
12
|
+
}
|
|
13
|
+
const scoped = errorsAt(
|
|
14
|
+
path,
|
|
15
|
+
schema,
|
|
16
|
+
(controlPath) => controlPath === path || controlPath.startsWith(`${path}.`)
|
|
17
|
+
)(errors);
|
|
18
|
+
const byField = /* @__PURE__ */ new Map();
|
|
19
|
+
for (const error of scoped) {
|
|
20
|
+
const group = byField.get(error.instancePath);
|
|
21
|
+
if (group) {
|
|
22
|
+
group.push(error);
|
|
23
|
+
} else {
|
|
24
|
+
byField.set(error.instancePath, [error]);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const messages = [];
|
|
28
|
+
for (const group of byField.values()) {
|
|
29
|
+
const [representative] = group;
|
|
30
|
+
const fieldMessages = group.map((error) => error.message).filter((message) => !!message);
|
|
31
|
+
messages.push(
|
|
32
|
+
...resolveNullableErrorMessages(
|
|
33
|
+
representative.data,
|
|
34
|
+
isNullableSchemaType((_a = representative.parentSchema) == null ? void 0 : _a.type),
|
|
35
|
+
fieldMessages
|
|
36
|
+
)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return formatErrorMessage(messages);
|
|
40
|
+
}, [errors, path, schema]);
|
|
41
|
+
};
|
|
42
|
+
export {
|
|
43
|
+
useArrayHeaderErrors
|
|
44
|
+
};
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
|
-
import {
|
|
3
|
-
const NULL_OPTION_ERRORS = /* @__PURE__ */ new Set([
|
|
4
|
-
"must be equal to one of the allowed values",
|
|
5
|
-
"must be equal to constant",
|
|
6
|
-
"must match exactly one schema in oneOf"
|
|
7
|
-
]);
|
|
8
|
-
const REQUIRED_ERROR = "is a required property";
|
|
2
|
+
import { nullableErrorAction, isNullableSchemaType, REQUIRED_ERROR, NULL_OPTION_ERRORS } from "../utils/nullOptionErrors.mjs";
|
|
9
3
|
function useNullableErrorProps(value, error, schema) {
|
|
10
4
|
return useMemo(() => {
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
switch (nullableErrorAction(value, isNullableSchemaType(schema.type))) {
|
|
6
|
+
case "keep":
|
|
7
|
+
return { error };
|
|
8
|
+
case "drop-options": {
|
|
9
|
+
const kept = error == null ? void 0 : error.filter((e) => !NULL_OPTION_ERRORS.has(e.key ?? ""));
|
|
10
|
+
return { error: (kept == null ? void 0 : kept.length) ? kept : void 0 };
|
|
11
|
+
}
|
|
12
|
+
case "required":
|
|
13
|
+
return { error: REQUIRED_ERROR };
|
|
13
14
|
}
|
|
14
|
-
if (isSchemaTypeInclude(schema.type ?? "", "null")) {
|
|
15
|
-
const kept = error == null ? void 0 : error.filter((e) => !NULL_OPTION_ERRORS.has(e.key ?? ""));
|
|
16
|
-
return { error: (kept == null ? void 0 : kept.length) ? kept : void 0 };
|
|
17
|
-
}
|
|
18
|
-
return { error: REQUIRED_ERROR };
|
|
19
15
|
}, [error, schema.type, value]);
|
|
20
16
|
}
|
|
21
17
|
export {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useArrayHeaderErrors } from "../../hooks/useArrayHeaderErrors.mjs";
|
|
2
3
|
import { useContextProps } from "../../hooks/useContextProps.mjs";
|
|
3
4
|
import { createDefaultValue, computeLabel, Paths } from "@jsonforms/core";
|
|
4
5
|
import { Stack, Accordion, Text } from "@mantine/core";
|
|
@@ -15,7 +16,6 @@ const Component = (props) => {
|
|
|
15
16
|
path,
|
|
16
17
|
schema,
|
|
17
18
|
uischema,
|
|
18
|
-
errors,
|
|
19
19
|
addItem,
|
|
20
20
|
renderers,
|
|
21
21
|
cells,
|
|
@@ -36,6 +36,7 @@ const Component = (props) => {
|
|
|
36
36
|
const [Component2, _props] = useContextProps("Array.Accordion", `${path}.Accordion`, {}, props, {
|
|
37
37
|
withAllProps: false
|
|
38
38
|
});
|
|
39
|
+
const headerErrors = useArrayHeaderErrors(path, schema);
|
|
39
40
|
return /* @__PURE__ */ jsxs(Stack, { children: [
|
|
40
41
|
/* @__PURE__ */ jsx(
|
|
41
42
|
ArrayLayoutToolbar,
|
|
@@ -43,7 +44,7 @@ const Component = (props) => {
|
|
|
43
44
|
translations,
|
|
44
45
|
label: computeLabel(label, required ?? false, appliedUiSchemaOptions.hideRequiredAsterisk),
|
|
45
46
|
description,
|
|
46
|
-
errors,
|
|
47
|
+
errors: headerErrors,
|
|
47
48
|
path,
|
|
48
49
|
enabled,
|
|
49
50
|
addItem,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { isSchemaTypeInclude } from "./isSchemaTypeInclude.mjs";
|
|
2
|
+
const NULL_OPTION_ERRORS = /* @__PURE__ */ new Set([
|
|
3
|
+
"must be equal to one of the allowed values",
|
|
4
|
+
"must be equal to constant",
|
|
5
|
+
"must match exactly one schema in oneOf"
|
|
6
|
+
]);
|
|
7
|
+
const REQUIRED_ERROR = "is a required property";
|
|
8
|
+
const nullableErrorAction = (value, nullable) => {
|
|
9
|
+
if (value !== null && value !== "") {
|
|
10
|
+
return "keep";
|
|
11
|
+
}
|
|
12
|
+
return nullable ? "drop-options" : "required";
|
|
13
|
+
};
|
|
14
|
+
const resolveNullableErrorMessages = (value, nullable, messages) => {
|
|
15
|
+
switch (nullableErrorAction(value, nullable)) {
|
|
16
|
+
case "keep":
|
|
17
|
+
return messages;
|
|
18
|
+
case "drop-options":
|
|
19
|
+
return messages.filter((message) => !NULL_OPTION_ERRORS.has(message));
|
|
20
|
+
case "required":
|
|
21
|
+
return [REQUIRED_ERROR];
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const isNullableSchemaType = (type) => isSchemaTypeInclude(type ?? "", "null");
|
|
25
|
+
export {
|
|
26
|
+
NULL_OPTION_ERRORS,
|
|
27
|
+
REQUIRED_ERROR,
|
|
28
|
+
isNullableSchemaType,
|
|
29
|
+
nullableErrorAction,
|
|
30
|
+
resolveNullableErrorMessages
|
|
31
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { JsonSchema } from '@jsonforms/core';
|
|
2
|
+
/**
|
|
3
|
+
* Builds the aggregated validation error string shown on an array control's header. JsonForms'
|
|
4
|
+
* `mapStateToArrayLayoutProps` aggregates every descendant error unconditionally, so without this the
|
|
5
|
+
* header reports errors its own fields hide (an empty value on a nullable enum / oneOf / const field,
|
|
6
|
+
* or the raw type+option errors on a non-nullable empty field).
|
|
7
|
+
*
|
|
8
|
+
* Reconstructs that aggregation (the array's own path plus every sub-path), groups the errors by the
|
|
9
|
+
* field that owns them, then applies the same per-field rule the inputs use ({@link
|
|
10
|
+
* resolveNullableErrorMessages}) so the header and its fields hide/show identical errors. `path` is
|
|
11
|
+
* the array's data path, `schema` its resolved item schema. Returns a newline-joined error string
|
|
12
|
+
* (empty when there is nothing to show).
|
|
13
|
+
*/
|
|
14
|
+
export declare const useArrayHeaderErrors: (path: string, schema: JsonSchema) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -7,6 +7,9 @@ import { JsonFormsDataValue } from './types';
|
|
|
7
7
|
* is valid, so the option-mismatch errors are hidden; a non-nullable field is missing, so a single
|
|
8
8
|
* "is a required property" error is shown. A non-empty value passes its errors through unchanged.
|
|
9
9
|
*
|
|
10
|
+
* Shares its branching with the array-header aggregation via {@link nullableErrorAction} so the field
|
|
11
|
+
* and its array header always hide/show the same errors.
|
|
12
|
+
*
|
|
10
13
|
* @param value the current value; `null` or `''` counts as empty
|
|
11
14
|
* @param error the rendered error nodes from `useCommonProps`
|
|
12
15
|
* @param schema the control schema; a `type` that includes `'null'` marks the field nullable
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const NULL_OPTION_ERRORS: Set<string>;
|
|
2
|
+
export declare const REQUIRED_ERROR = "is a required property";
|
|
3
|
+
/**
|
|
4
|
+
* The single source of truth for how an empty-capable single-value field treats its validation
|
|
5
|
+
* errors, shared by `useNullableErrorProps` (per field) and `useArrayHeaderErrors` (array header) so
|
|
6
|
+
* the two never drift:
|
|
7
|
+
*
|
|
8
|
+
* - `keep`: a non-empty value passes its errors through unchanged.
|
|
9
|
+
* - `drop-options`: an empty (`null` / `''`) value of a nullable field is valid, so the
|
|
10
|
+
* option-mismatch errors ({@link NULL_OPTION_ERRORS}) are hidden.
|
|
11
|
+
* - `required`: an empty value of a non-nullable field is missing, so a single
|
|
12
|
+
* {@link REQUIRED_ERROR} replaces whatever AJV reported.
|
|
13
|
+
*
|
|
14
|
+
* `value` is the current field value (`null` / `''` counts as empty), `nullable` whether the field
|
|
15
|
+
* schema permits `null`.
|
|
16
|
+
*/
|
|
17
|
+
export declare const nullableErrorAction: (value: unknown, nullable: boolean) => "keep" | "drop-options" | "required";
|
|
18
|
+
/**
|
|
19
|
+
* Applies {@link nullableErrorAction} to a list of AJV error messages. Used by the array header,
|
|
20
|
+
* which works with the raw message strings of one field's errors (grouped by data path).
|
|
21
|
+
*
|
|
22
|
+
* `value` / `nullable` describe that field; `messages` are its error messages. Returns the messages
|
|
23
|
+
* to surface.
|
|
24
|
+
*/
|
|
25
|
+
export declare const resolveNullableErrorMessages: (value: unknown, nullable: boolean, messages: string[]) => string[];
|
|
26
|
+
/** Whether a schema permits a `null` value (i.e. is nullable / optional). */
|
|
27
|
+
export declare const isNullableSchemaType: (type: unknown) => boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED