schema-components 1.22.0 → 1.24.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/README.md +3 -1
- package/dist/core/adapter.d.mts +97 -3
- package/dist/core/adapter.mjs +260 -111
- package/dist/core/constraints.d.mts +2 -2
- package/dist/core/constraints.mjs +0 -7
- package/dist/core/cssClasses.d.mts +52 -0
- package/dist/core/cssClasses.mjs +51 -0
- package/dist/core/diagnostics.d.mts +1 -1
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/errors.mjs +5 -13
- package/dist/core/fieldOrder.d.mts +1 -1
- package/dist/core/formats.d.mts +9 -2
- package/dist/core/formats.mjs +12 -1
- package/dist/core/idPath.d.mts +54 -0
- package/dist/core/idPath.mjs +66 -0
- package/dist/core/merge.d.mts +10 -1
- package/dist/core/merge.mjs +49 -10
- package/dist/core/normalise.d.mts +14 -3
- package/dist/core/normalise.mjs +2 -2
- package/dist/core/openapi30.d.mts +15 -1
- package/dist/core/openapi30.mjs +2 -2
- package/dist/core/openapiConstants.d.mts +67 -0
- package/dist/core/openapiConstants.mjs +90 -0
- package/dist/core/ref.d.mts +2 -2
- package/dist/core/ref.mjs +83 -6
- package/dist/core/refChain.d.mts +70 -0
- package/dist/core/refChain.mjs +44 -0
- package/dist/core/renderer.d.mts +1 -1
- package/dist/core/swagger2.d.mts +1 -1
- package/dist/core/swagger2.mjs +1 -1
- package/dist/core/typeInference.d.mts +982 -2
- package/dist/core/types.d.mts +1 -1
- package/dist/core/unionMatch.d.mts +36 -0
- package/dist/core/unionMatch.mjs +53 -0
- package/dist/core/version.d.mts +1 -1
- package/dist/core/version.mjs +29 -17
- package/dist/core/walkBuilders.d.mts +23 -4
- package/dist/core/walkBuilders.mjs +27 -7
- package/dist/core/walker.d.mts +1 -1
- package/dist/core/walker.mjs +44 -45
- package/dist/{diagnostics-D0QCYGv0.d.mts → diagnostics-Cbwak-ZX.d.mts} +1 -1
- package/dist/{errors-DpFwqs5C.d.mts → errors-g_MCTQel.d.mts} +9 -15
- package/dist/html/a11y.d.mts +9 -4
- package/dist/html/a11y.mjs +10 -19
- package/dist/html/renderToHtml.d.mts +2 -2
- package/dist/html/renderToHtmlStream.d.mts +2 -2
- package/dist/html/renderToHtmlStream.mjs +12 -1
- package/dist/html/renderers.d.mts +32 -8
- package/dist/html/renderers.mjs +125 -111
- package/dist/html/streamRenderers.d.mts +4 -5
- package/dist/html/streamRenderers.mjs +40 -61
- package/dist/{normalise-DVEJQmF7.mjs → normalise-DCYp06Sr.mjs} +352 -162
- package/dist/openapi/ApiCallbacks.d.mts +1 -1
- package/dist/openapi/ApiLinks.d.mts +1 -1
- package/dist/openapi/ApiResponseHeaders.d.mts +1 -1
- package/dist/openapi/ApiSecurity.d.mts +1 -1
- package/dist/openapi/components.d.mts +116 -37
- package/dist/openapi/components.mjs +54 -37
- package/dist/openapi/parser.d.mts +19 -9
- package/dist/openapi/parser.mjs +262 -86
- package/dist/openapi/resolve.d.mts +20 -11
- package/dist/openapi/resolve.mjs +135 -75
- package/dist/react/SchemaComponent.d.mts +32 -7
- package/dist/react/SchemaComponent.mjs +45 -21
- package/dist/react/SchemaView.d.mts +30 -10
- package/dist/react/a11y.d.mts +21 -0
- package/dist/react/a11y.mjs +24 -0
- package/dist/react/fieldPath.d.mts +1 -1
- package/dist/react/headless.d.mts +1 -1
- package/dist/react/headlessRenderers.d.mts +8 -9
- package/dist/react/headlessRenderers.mjs +41 -72
- package/dist/{ref-D-_JBZkF.d.mts → ref-DCDuswPe.d.mts} +38 -3
- package/dist/{renderer-BaRlQIuN.d.mts → renderer-CXJ8y0qw.d.mts} +1 -1
- package/dist/themes/mantine.d.mts +1 -1
- package/dist/themes/mui.d.mts +1 -1
- package/dist/themes/radix.d.mts +1 -1
- package/dist/themes/shadcn.d.mts +1 -1
- package/dist/themes/shadcn.mjs +2 -1
- package/dist/{types-BrRMV0en.d.mts → types-BTB73MB8.d.mts} +32 -4
- package/dist/{version-D2jfdX6E.d.mts → version-BFTVLsdb.d.mts} +7 -1
- package/package.json +1 -1
- package/dist/typeInference-DkcUHfaM.d.mts +0 -982
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { isObject } from "../core/guards.mjs";
|
|
2
|
+
import { dateInputType } from "../core/formats.mjs";
|
|
2
3
|
import { isSafeHyperlink, isSafeMailtoAddress } from "../core/uri.mjs";
|
|
4
|
+
import { SC_CLASSES } from "../core/cssClasses.mjs";
|
|
3
5
|
import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
|
|
6
|
+
import { fieldDomId, panelIdFor, tabIdFor } from "../core/idPath.mjs";
|
|
7
|
+
import { matchUnionOption, resolveDiscriminatedActive } from "../core/unionMatch.mjs";
|
|
8
|
+
import { displayJsonValue } from "../core/walkBuilders.mjs";
|
|
9
|
+
import { buildAriaAttrs } from "./a11y.mjs";
|
|
4
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
11
|
import { isValidElement, useCallback, useEffect, useRef } from "react";
|
|
6
12
|
//#region src/react/headlessRenderers.tsx
|
|
@@ -41,26 +47,19 @@ function formatTime(value) {
|
|
|
41
47
|
if (isNaN(date.getTime())) return void 0;
|
|
42
48
|
return date.toLocaleTimeString();
|
|
43
49
|
}
|
|
44
|
-
function dateInputType(format) {
|
|
45
|
-
if (format === "date") return "date";
|
|
46
|
-
if (format === "time") return "time";
|
|
47
|
-
if (format === "date-time" || format === "datetime") return "datetime-local";
|
|
48
|
-
}
|
|
49
50
|
/**
|
|
50
51
|
* Build a stable, unique input ID from the path.
|
|
51
|
-
* Used for `htmlFor`/`id` association between labels and inputs.
|
|
52
52
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
53
|
+
* Re-exported alias for {@link fieldDomId} so external themes (shadcn,
|
|
54
|
+
* MUI, mantine, radix) keep importing `inputId` from the React entry
|
|
55
|
+
* point. Both the React and HTML renderers must derive the same id from
|
|
56
|
+
* the same path — `fieldDomId` in `core/idPath.ts` is the single
|
|
57
|
+
* source-of-truth.
|
|
57
58
|
*
|
|
58
|
-
*
|
|
59
|
-
* id valid as a CSS selector and predictable in test queries.
|
|
59
|
+
* Throws on an empty path; see `fieldDomId` for the rationale.
|
|
60
60
|
*/
|
|
61
61
|
function inputId(path) {
|
|
62
|
-
|
|
63
|
-
return `sc-${path.replace(/[.[\]]+/g, "-").replace(/-+$/g, "")}`;
|
|
62
|
+
return fieldDomId(path);
|
|
64
63
|
}
|
|
65
64
|
function renderString(props) {
|
|
66
65
|
const id = inputId(props.path);
|
|
@@ -107,8 +106,7 @@ function renderString(props) {
|
|
|
107
106
|
}
|
|
108
107
|
const strValue = typeof props.value === "string" ? props.value : "";
|
|
109
108
|
const dateType = dateInputType(props.constraints.format);
|
|
110
|
-
const ariaAttrs =
|
|
111
|
-
if (props.tree.isOptional === false) ariaAttrs["aria-required"] = "true";
|
|
109
|
+
const ariaAttrs = buildAriaAttrs(props.tree);
|
|
112
110
|
if (dateType !== void 0) return /* @__PURE__ */ jsx("input", {
|
|
113
111
|
id,
|
|
114
112
|
type: dateType,
|
|
@@ -131,7 +129,7 @@ function renderString(props) {
|
|
|
131
129
|
value: "",
|
|
132
130
|
children: ["Select", "…"]
|
|
133
131
|
}), enumValues.map((v) => {
|
|
134
|
-
const display =
|
|
132
|
+
const display = displayJsonValue(v);
|
|
135
133
|
return /* @__PURE__ */ jsx("option", {
|
|
136
134
|
value: display,
|
|
137
135
|
children: display
|
|
@@ -167,8 +165,7 @@ function renderNumber(props) {
|
|
|
167
165
|
});
|
|
168
166
|
}
|
|
169
167
|
const numValue = typeof props.value === "number" ? props.value : "";
|
|
170
|
-
const ariaAttrs =
|
|
171
|
-
if (props.tree.isOptional === false) ariaAttrs["aria-required"] = "true";
|
|
168
|
+
const ariaAttrs = buildAriaAttrs(props.tree);
|
|
172
169
|
return /* @__PURE__ */ jsx("input", {
|
|
173
170
|
id,
|
|
174
171
|
type: "number",
|
|
@@ -195,9 +192,7 @@ function renderBoolean(props) {
|
|
|
195
192
|
children: props.value ? "Yes" : "No"
|
|
196
193
|
});
|
|
197
194
|
}
|
|
198
|
-
const ariaAttrs =
|
|
199
|
-
if (props.tree.isOptional === false) ariaAttrs["aria-required"] = "true";
|
|
200
|
-
if (typeof props.meta.description === "string") ariaAttrs["aria-label"] = props.meta.description;
|
|
195
|
+
const ariaAttrs = buildAriaAttrs(props.tree, props.meta.description);
|
|
201
196
|
return /* @__PURE__ */ jsx("input", {
|
|
202
197
|
id,
|
|
203
198
|
type: "checkbox",
|
|
@@ -216,8 +211,7 @@ function renderEnum(props) {
|
|
|
216
211
|
"aria-readonly": "true",
|
|
217
212
|
children: enumValue || "—"
|
|
218
213
|
});
|
|
219
|
-
const ariaAttrs =
|
|
220
|
-
if (props.tree.isOptional === false) ariaAttrs["aria-required"] = "true";
|
|
214
|
+
const ariaAttrs = buildAriaAttrs(props.tree);
|
|
221
215
|
const enumValues = props.tree.type === "enum" ? props.tree.enumValues : [];
|
|
222
216
|
return /* @__PURE__ */ jsxs("select", {
|
|
223
217
|
id,
|
|
@@ -230,7 +224,7 @@ function renderEnum(props) {
|
|
|
230
224
|
value: "",
|
|
231
225
|
children: ["Select", "…"]
|
|
232
226
|
}), enumValues.map((v) => {
|
|
233
|
-
const display =
|
|
227
|
+
const display = displayJsonValue(v);
|
|
234
228
|
return /* @__PURE__ */ jsx("option", {
|
|
235
229
|
value: display,
|
|
236
230
|
children: display
|
|
@@ -315,7 +309,7 @@ function renderRecord(props) {
|
|
|
315
309
|
});
|
|
316
310
|
return /* @__PURE__ */ jsx("div", {
|
|
317
311
|
role: "group",
|
|
318
|
-
"aria-label": props.meta.description
|
|
312
|
+
"aria-label": typeof props.meta.description === "string" ? props.meta.description : void 0,
|
|
319
313
|
children: entries.map(([key, value]) => {
|
|
320
314
|
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
|
|
321
315
|
htmlFor: inputId(`${props.path}.${key}`),
|
|
@@ -415,32 +409,16 @@ function renderUnion(props) {
|
|
|
415
409
|
return /* @__PURE__ */ jsx("span", { children: "—" });
|
|
416
410
|
}
|
|
417
411
|
function renderDiscriminatedUnion(props) {
|
|
418
|
-
|
|
419
|
-
const discriminator = props.tree.type === "discriminatedUnion" ? props.tree.discriminator : void 0;
|
|
420
|
-
if (options === void 0 || options.length === 0) {
|
|
412
|
+
if (props.tree.type !== "discriminatedUnion") {
|
|
421
413
|
if (props.value === void 0 || props.value === null) return /* @__PURE__ */ jsx("span", { children: "—" });
|
|
422
414
|
return /* @__PURE__ */ jsx("span", { children: JSON.stringify(props.value) });
|
|
423
415
|
}
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (opt.type === "object") {
|
|
429
|
-
const discriminatorField = opt.fields[discKey];
|
|
430
|
-
if (discriminatorField?.type === "literal") {
|
|
431
|
-
const constVal = discriminatorField.literalValues[0];
|
|
432
|
-
if (typeof constVal === "string") return constVal;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
return typeof opt.meta.title === "string" ? opt.meta.title : opt.type;
|
|
436
|
-
});
|
|
437
|
-
let activeIndex = 0;
|
|
438
|
-
if (currentDiscriminatorValue !== void 0) {
|
|
439
|
-
const found = optionLabels.indexOf(currentDiscriminatorValue);
|
|
440
|
-
if (found !== -1) activeIndex = found;
|
|
416
|
+
const { options, discriminator: discKey } = props.tree;
|
|
417
|
+
if (options.length === 0) {
|
|
418
|
+
if (props.value === void 0 || props.value === null) return /* @__PURE__ */ jsx("span", { children: "—" });
|
|
419
|
+
return /* @__PURE__ */ jsx("span", { children: JSON.stringify(props.value) });
|
|
441
420
|
}
|
|
442
|
-
const activeOption = options
|
|
443
|
-
const panelId = inputId(props.path);
|
|
421
|
+
const { optionLabels, activeIndex, activeOption } = resolveDiscriminatedActive(options, discKey, isObject(props.value) ? props.value : void 0);
|
|
444
422
|
if (props.readOnly) {
|
|
445
423
|
if (activeOption !== void 0) return toReactNode(props.renderChild(activeOption, props.value, props.onChange));
|
|
446
424
|
return /* @__PURE__ */ jsx("span", { children: "—" });
|
|
@@ -449,7 +427,7 @@ function renderDiscriminatedUnion(props) {
|
|
|
449
427
|
options,
|
|
450
428
|
optionLabels,
|
|
451
429
|
activeIndex,
|
|
452
|
-
|
|
430
|
+
path: props.path,
|
|
453
431
|
discKey,
|
|
454
432
|
props
|
|
455
433
|
});
|
|
@@ -479,7 +457,8 @@ function discriminatedUnionValueForTab(optionLabels, discKey, newIndex) {
|
|
|
479
457
|
* "Automatic activation" means each arrow key both moves focus and
|
|
480
458
|
* activates the new tab in one step — selection and focus stay aligned.
|
|
481
459
|
*/
|
|
482
|
-
function DiscriminatedUnionTabs({ options, optionLabels, activeIndex,
|
|
460
|
+
function DiscriminatedUnionTabs({ options, optionLabels, activeIndex, path, discKey, props }) {
|
|
461
|
+
const panelId = panelIdFor(path);
|
|
483
462
|
const tabRefs = useRef([]);
|
|
484
463
|
const pendingFocusRef = useRef(false);
|
|
485
464
|
const handleTabChange = useCallback((newIndex) => {
|
|
@@ -530,9 +509,9 @@ function DiscriminatedUnionTabs({ options, optionLabels, activeIndex, panelId, d
|
|
|
530
509
|
},
|
|
531
510
|
type: "button",
|
|
532
511
|
role: "tab",
|
|
533
|
-
id:
|
|
512
|
+
id: tabIdFor(path, i),
|
|
534
513
|
"aria-selected": i === activeIndex ? "true" : void 0,
|
|
535
|
-
"aria-controls":
|
|
514
|
+
"aria-controls": panelId,
|
|
536
515
|
tabIndex: i === activeIndex ? 0 : -1,
|
|
537
516
|
onClick: () => {
|
|
538
517
|
handleTabChange(i);
|
|
@@ -549,8 +528,8 @@ function DiscriminatedUnionTabs({ options, optionLabels, activeIndex, panelId, d
|
|
|
549
528
|
}, String(i)))
|
|
550
529
|
}), /* @__PURE__ */ jsx("div", {
|
|
551
530
|
role: "tabpanel",
|
|
552
|
-
id:
|
|
553
|
-
"aria-labelledby":
|
|
531
|
+
id: panelId,
|
|
532
|
+
"aria-labelledby": tabIdFor(path, activeIndex),
|
|
554
533
|
children: activeOption !== void 0 && toReactNode(props.renderChild(activeOption, props.value, props.onChange))
|
|
555
534
|
})] });
|
|
556
535
|
}
|
|
@@ -562,9 +541,6 @@ function renderFile(props) {
|
|
|
562
541
|
"aria-readonly": "true",
|
|
563
542
|
children: "File field"
|
|
564
543
|
});
|
|
565
|
-
const ariaAttrs = {};
|
|
566
|
-
if (props.tree.isOptional === false) ariaAttrs["aria-required"] = "true";
|
|
567
|
-
if (typeof props.meta.description === "string") ariaAttrs["aria-label"] = props.meta.description;
|
|
568
544
|
return /* @__PURE__ */ jsx("input", {
|
|
569
545
|
id,
|
|
570
546
|
type: "file",
|
|
@@ -573,7 +549,7 @@ function renderFile(props) {
|
|
|
573
549
|
const file = e.target.files?.[0];
|
|
574
550
|
if (file !== void 0) props.onChange(file);
|
|
575
551
|
},
|
|
576
|
-
...
|
|
552
|
+
...buildAriaAttrs(props.tree, props.meta.description)
|
|
577
553
|
});
|
|
578
554
|
}
|
|
579
555
|
/**
|
|
@@ -595,7 +571,7 @@ function renderLiteral(props) {
|
|
|
595
571
|
return /* @__PURE__ */ jsx("span", {
|
|
596
572
|
id,
|
|
597
573
|
"aria-readonly": "true",
|
|
598
|
-
children: values.map((v) =>
|
|
574
|
+
children: values.map((v) => displayJsonValue(v)).join(", ")
|
|
599
575
|
});
|
|
600
576
|
}
|
|
601
577
|
/**
|
|
@@ -624,7 +600,7 @@ function renderNever(props) {
|
|
|
624
600
|
return /* @__PURE__ */ jsx("span", {
|
|
625
601
|
id: inputId(props.path),
|
|
626
602
|
"aria-readonly": "true",
|
|
627
|
-
className:
|
|
603
|
+
className: SC_CLASSES.never,
|
|
628
604
|
children: /* @__PURE__ */ jsx("em", { children: "never matches" })
|
|
629
605
|
});
|
|
630
606
|
}
|
|
@@ -678,10 +654,10 @@ function renderConditional(props) {
|
|
|
678
654
|
if (props.tree.type !== "conditional") return null;
|
|
679
655
|
const { ifClause, thenClause, elseClause } = props.tree;
|
|
680
656
|
return /* @__PURE__ */ jsxs("fieldset", {
|
|
681
|
-
className:
|
|
657
|
+
className: SC_CLASSES.conditional,
|
|
682
658
|
children: [
|
|
683
659
|
/* @__PURE__ */ jsxs("div", {
|
|
684
|
-
className:
|
|
660
|
+
className: SC_CLASSES.conditionalIf,
|
|
685
661
|
children: [
|
|
686
662
|
/* @__PURE__ */ jsx("strong", { children: "if:" }),
|
|
687
663
|
" ",
|
|
@@ -689,7 +665,7 @@ function renderConditional(props) {
|
|
|
689
665
|
]
|
|
690
666
|
}),
|
|
691
667
|
thenClause !== void 0 && /* @__PURE__ */ jsxs("div", {
|
|
692
|
-
className:
|
|
668
|
+
className: SC_CLASSES.conditionalThen,
|
|
693
669
|
children: [
|
|
694
670
|
/* @__PURE__ */ jsx("strong", { children: "then:" }),
|
|
695
671
|
" ",
|
|
@@ -697,7 +673,7 @@ function renderConditional(props) {
|
|
|
697
673
|
]
|
|
698
674
|
}),
|
|
699
675
|
elseClause !== void 0 && /* @__PURE__ */ jsxs("div", {
|
|
700
|
-
className:
|
|
676
|
+
className: SC_CLASSES.conditionalElse,
|
|
701
677
|
children: [
|
|
702
678
|
/* @__PURE__ */ jsx("strong", { children: "else:" }),
|
|
703
679
|
" ",
|
|
@@ -717,7 +693,7 @@ function renderConditional(props) {
|
|
|
717
693
|
function renderNegation(props) {
|
|
718
694
|
if (props.tree.type !== "negation") return null;
|
|
719
695
|
return /* @__PURE__ */ jsxs("fieldset", {
|
|
720
|
-
className:
|
|
696
|
+
className: SC_CLASSES.negation,
|
|
721
697
|
children: [
|
|
722
698
|
/* @__PURE__ */ jsx("strong", { children: "Must NOT match:" }),
|
|
723
699
|
" ",
|
|
@@ -749,12 +725,5 @@ function renderUnknown(props) {
|
|
|
749
725
|
}
|
|
750
726
|
});
|
|
751
727
|
}
|
|
752
|
-
function matchUnionOption(options, value) {
|
|
753
|
-
if (typeof value === "string") return options.find((o) => o.type === "string" || o.type === "enum");
|
|
754
|
-
if (typeof value === "number") return options.find((o) => o.type === "number");
|
|
755
|
-
if (typeof value === "boolean") return options.find((o) => o.type === "boolean");
|
|
756
|
-
if (Array.isArray(value)) return options.find((o) => o.type === "array");
|
|
757
|
-
if (typeof value === "object" && value !== null) return options.find((o) => o.type === "object");
|
|
758
|
-
}
|
|
759
728
|
//#endregion
|
|
760
729
|
export { defaultRecordValue, discriminatedUnionValueForTab, inputId, nextRecordKey, renameRecordKey, renderArray, renderBoolean, renderConditional, renderDiscriminatedUnion, renderEnum, renderFile, renderLiteral, renderNegation, renderNever, renderNull, renderNumber, renderObject, renderRecord, renderString, renderTuple, renderUnion, renderUnknown, toReactNode };
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import { i as DiagnosticsOptions } from "./diagnostics-
|
|
1
|
+
import { i as DiagnosticsOptions } from "./diagnostics-Cbwak-ZX.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/core/ref.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The canonical recursive `$anchor` name synthesised by the Draft
|
|
6
|
+
* 2019-09 `$recursiveAnchor: true` rewrite. Re-exported here so the
|
|
7
|
+
* collision check in {@link findAnchor} stays aligned with the
|
|
8
|
+
* rewriter in `core/normalise.ts`.
|
|
9
|
+
*/
|
|
10
|
+
declare const RECURSIVE_ANCHOR_SENTINEL = "__recursive__";
|
|
4
11
|
/**
|
|
5
12
|
* Resolver function for external $ref URIs.
|
|
6
13
|
* Called with the URI portion (everything before `#`) of an external ref.
|
|
@@ -33,17 +40,45 @@ declare function resolveRef(schema: Record<string, unknown>, rootDocument: Recor
|
|
|
33
40
|
/**
|
|
34
41
|
* Dereference a JSON Pointer fragment (`#/path/to/schema`) or an
|
|
35
42
|
* `$anchor` (`#SomeName`) against a root document.
|
|
43
|
+
*
|
|
44
|
+
* Returns the resolved sub-schema, which may be a JSON object or — per
|
|
45
|
+
* Draft 06+ — a boolean (`true` for the always-valid schema, `false`
|
|
46
|
+
* for the never-valid schema). Returns `undefined` when the pointer or
|
|
47
|
+
* anchor cannot be resolved.
|
|
48
|
+
*
|
|
49
|
+
* JSON Pointer segments are percent-decoded per RFC 6901 §6 before the
|
|
50
|
+
* `~1`/`~0` token expansion; this allows pointers such as
|
|
51
|
+
* `#/paths/~1pets%20store` to resolve a path containing a literal space.
|
|
36
52
|
*/
|
|
37
|
-
declare function dereference(ref: string, root: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
53
|
+
declare function dereference(ref: string, root: Record<string, unknown>): Record<string, unknown> | boolean | undefined;
|
|
38
54
|
/**
|
|
39
55
|
* Recursively scan a schema document for a `$anchor` matching the given name.
|
|
40
56
|
* Returns the schema object containing the anchor, or undefined.
|
|
41
57
|
*
|
|
58
|
+
* Per JSON Schema 2020-12 §8.2, `$anchor` is scoped to the resource
|
|
59
|
+
* defined by the nearest enclosing `$id`. A bare DFS would happily
|
|
60
|
+
* cross resource boundaries and resolve to an anchor declared in an
|
|
61
|
+
* unrelated sub-resource — that violates the spec and produces wrong
|
|
62
|
+
* walker input when two sub-schemas use the same anchor name within
|
|
63
|
+
* their own `$id` scope.
|
|
64
|
+
*
|
|
65
|
+
* The walk skips into any sub-tree that introduces a new `$id` value:
|
|
66
|
+
* such a sub-tree is a separate resource and its `$anchor`s belong to
|
|
67
|
+
* that resource, not the caller's. Anchors declared at the same `$id`
|
|
68
|
+
* scope (or in nested sub-schemas without their own `$id`) remain
|
|
69
|
+
* reachable.
|
|
70
|
+
*
|
|
42
71
|
* The optional `visited` set guards against shared object references and
|
|
43
72
|
* cycles introduced by the OpenAPI bundler's `structuredClone`-based
|
|
44
73
|
* inlining of external refs. Without it a recursive document would stack
|
|
45
74
|
* overflow before reaching the matching anchor.
|
|
75
|
+
*
|
|
76
|
+
* When `crossResourceBoundary` is `true` the walker is currently
|
|
77
|
+
* recursing into a sub-tree that introduced its own `$id`; we still
|
|
78
|
+
* recurse so a nested `$anchor` declared inside that same sub-resource
|
|
79
|
+
* is reachable from the caller that owns that resource, but we skip
|
|
80
|
+
* further nested resources for the same reason as above.
|
|
46
81
|
*/
|
|
47
82
|
declare function findAnchor(node: unknown, anchorName: string, visited?: WeakSet<object>): Record<string, unknown> | undefined;
|
|
48
83
|
//#endregion
|
|
49
|
-
export {
|
|
84
|
+
export { dereference as a, countDistinctRefs as i, RECURSIVE_ANCHOR_SENTINEL as n, findAnchor as o, RefOptions as r, resolveRef as s, ExternalResolver as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as StringConstraints, f as FileConstraints, j as WalkedField, t as ArrayConstraints, w as SchemaMeta, x as ObjectConstraints, y as NumberConstraints } from "./types-
|
|
1
|
+
import { E as StringConstraints, f as FileConstraints, j as WalkedField, t as ArrayConstraints, w as SchemaMeta, x as ObjectConstraints, y as NumberConstraints } from "./types-BTB73MB8.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/core/renderer.d.ts
|
|
4
4
|
/**
|
package/dist/themes/mui.d.mts
CHANGED
package/dist/themes/radix.d.mts
CHANGED
package/dist/themes/shadcn.d.mts
CHANGED
package/dist/themes/shadcn.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { toRecord } from "../core/guards.mjs";
|
|
2
2
|
import { sortFieldsByOrder } from "../core/fieldOrder.mjs";
|
|
3
|
+
import { displayJsonValue } from "../core/walkBuilders.mjs";
|
|
3
4
|
import { inputId, toReactNode } from "../react/headlessRenderers.mjs";
|
|
4
5
|
import { headlessResolver } from "../react/headless.mjs";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -160,7 +161,7 @@ function renderEnumInput(props) {
|
|
|
160
161
|
value: "",
|
|
161
162
|
children: ["Select", "…"]
|
|
162
163
|
}), props.tree.type === "enum" ? props.tree.enumValues.map((v) => {
|
|
163
|
-
const display =
|
|
164
|
+
const display = displayJsonValue(v);
|
|
164
165
|
return /* @__PURE__ */ jsx("option", {
|
|
165
166
|
value: display,
|
|
166
167
|
children: display
|
|
@@ -86,8 +86,6 @@ interface ArrayConstraints {
|
|
|
86
86
|
uniqueItems?: boolean;
|
|
87
87
|
minContains?: number;
|
|
88
88
|
maxContains?: number;
|
|
89
|
-
/** Constraint schema for unevaluated items. */
|
|
90
|
-
unevaluatedItems?: Record<string, unknown>;
|
|
91
89
|
}
|
|
92
90
|
/** Constraints that apply to object schemas. */
|
|
93
91
|
interface ObjectConstraints {
|
|
@@ -138,12 +136,24 @@ interface NullField extends FieldBase {
|
|
|
138
136
|
interface EnumField extends FieldBase {
|
|
139
137
|
type: "enum";
|
|
140
138
|
constraints: Record<string, never>;
|
|
141
|
-
|
|
139
|
+
/**
|
|
140
|
+
* Enum values from JSON Schema `enum`. Per Draft 2020-12 §6.1.2,
|
|
141
|
+
* `enum` accepts an array of arbitrary JSON values — not only
|
|
142
|
+
* primitives. Object and array values are preserved verbatim.
|
|
143
|
+
*/
|
|
144
|
+
enumValues: unknown[];
|
|
142
145
|
}
|
|
143
146
|
interface LiteralField extends FieldBase {
|
|
144
147
|
type: "literal";
|
|
145
148
|
constraints: Record<string, never>;
|
|
146
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Const values from JSON Schema `const`. Per Draft 2020-12 §6.1.3,
|
|
151
|
+
* `const` accepts any JSON value (object or array included), not
|
|
152
|
+
* only primitives. The walker emits a single-element array because
|
|
153
|
+
* `const` is scalar by definition; the field shape mirrors
|
|
154
|
+
* `EnumField` for renderer symmetry.
|
|
155
|
+
*/
|
|
156
|
+
literalValues: unknown[];
|
|
147
157
|
}
|
|
148
158
|
interface ObjectField extends FieldBase {
|
|
149
159
|
type: "object";
|
|
@@ -182,6 +192,13 @@ interface ArrayField extends FieldBase {
|
|
|
182
192
|
contains?: WalkedField;
|
|
183
193
|
/** Walked schema for unevaluated items. */
|
|
184
194
|
unevaluatedItems?: WalkedField;
|
|
195
|
+
/**
|
|
196
|
+
* Whether `unevaluatedItems` is explicitly `false` (no extras
|
|
197
|
+
* permitted beyond the items evaluated by `items`/`prefixItems`/
|
|
198
|
+
* `contains`). Parallel to `additionalPropertiesClosed` and
|
|
199
|
+
* `unevaluatedPropertiesClosed` on `ObjectField`.
|
|
200
|
+
*/
|
|
201
|
+
unevaluatedItemsClosed?: boolean;
|
|
185
202
|
}
|
|
186
203
|
interface TupleField extends FieldBase {
|
|
187
204
|
type: "tuple";
|
|
@@ -200,6 +217,17 @@ interface TupleField extends FieldBase {
|
|
|
200
217
|
* element schemas to require the presence of a specific element.
|
|
201
218
|
*/
|
|
202
219
|
contains?: WalkedField;
|
|
220
|
+
/**
|
|
221
|
+
* Walked schema for `unevaluatedItems` adjacent to `prefixItems`.
|
|
222
|
+
* Permits additional items only when they satisfy this schema.
|
|
223
|
+
*/
|
|
224
|
+
unevaluatedItems?: WalkedField;
|
|
225
|
+
/**
|
|
226
|
+
* Whether `unevaluatedItems` is explicitly `false` on a tuple. With
|
|
227
|
+
* `prefixItems` declared, this forbids any items beyond the prefix
|
|
228
|
+
* length.
|
|
229
|
+
*/
|
|
230
|
+
unevaluatedItemsClosed?: boolean;
|
|
203
231
|
}
|
|
204
232
|
interface RecordField extends FieldBase {
|
|
205
233
|
type: "record";
|
|
@@ -56,7 +56,13 @@ interface OpenApiVersionInfo {
|
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
58
|
* Detect the OpenAPI/Swagger version from a document.
|
|
59
|
-
*
|
|
59
|
+
*
|
|
60
|
+
* Returns `undefined` when the document declares neither `swagger` nor
|
|
61
|
+
* `openapi` strings, or when the declared version string is malformed
|
|
62
|
+
* (missing parts or non-numeric segments). `Number("abc")` yields `NaN`,
|
|
63
|
+
* which `parts[i] ?? default` does NOT replace — nullish coalescing only
|
|
64
|
+
* substitutes `null`/`undefined` — so any unparseable segment surfaces
|
|
65
|
+
* as `undefined` rather than a silent fabricated default.
|
|
60
66
|
*/
|
|
61
67
|
declare function detectOpenApiVersion(doc: Record<string, unknown>): OpenApiVersionInfo | undefined;
|
|
62
68
|
/**
|