schema-components 0.0.0 → 1.1.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/CHANGELOG.md +59 -0
- package/LICENSE +21 -0
- package/README.md +526 -0
- package/dist/core/adapter.d.mts +19 -0
- package/dist/core/adapter.mjs +140 -0
- package/dist/core/errors.d.mts +2 -0
- package/dist/core/errors.mjs +74 -0
- package/dist/core/guards.d.mts +44 -0
- package/dist/core/guards.mjs +58 -0
- package/dist/core/renderer.d.mts +2 -0
- package/dist/core/renderer.mjs +71 -0
- package/dist/core/types.d.mts +3 -0
- package/dist/core/types.mjs +40 -0
- package/dist/core/walker.d.mts +14 -0
- package/dist/core/walker.mjs +366 -0
- package/dist/errors-DIKI2C78.d.mts +57 -0
- package/dist/html/a11y.d.mts +47 -0
- package/dist/html/a11y.mjs +81 -0
- package/dist/html/html.d.mts +135 -0
- package/dist/html/html.mjs +168 -0
- package/dist/html/renderToHtml.d.mts +32 -0
- package/dist/html/renderToHtml.mjs +352 -0
- package/dist/html/renderToHtmlStream.d.mts +58 -0
- package/dist/html/renderToHtmlStream.mjs +285 -0
- package/dist/html/styles.css +151 -0
- package/dist/openapi/components.d.mts +76 -0
- package/dist/openapi/components.mjs +223 -0
- package/dist/openapi/parser.d.mts +45 -0
- package/dist/openapi/parser.mjs +159 -0
- package/dist/react/SchemaComponent.d.mts +96 -0
- package/dist/react/SchemaComponent.mjs +283 -0
- package/dist/react/SchemaErrorBoundary.d.mts +26 -0
- package/dist/react/SchemaErrorBoundary.mjs +47 -0
- package/dist/react/headless.d.mts +13 -0
- package/dist/react/headless.mjs +163 -0
- package/dist/themes/shadcn.d.mts +6 -0
- package/dist/themes/shadcn.mjs +166 -0
- package/dist/types-BU0ETFHk.d.mts +326 -0
- package/package.json +113 -3
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { isObject } from "../core/guards.mjs";
|
|
2
|
+
import { normaliseSchema } from "../core/adapter.mjs";
|
|
3
|
+
import { getHtmlRenderFn, mergeHtmlResolvers } from "../core/renderer.mjs";
|
|
4
|
+
import { walk } from "../core/walker.mjs";
|
|
5
|
+
import { VOID_ELEMENTS, h, raw, serialize, serializeAttributes } from "./html.mjs";
|
|
6
|
+
import { ariaLabelAttrs, buildHintElement, buildInputId, requiredIndicator } from "./a11y.mjs";
|
|
7
|
+
import { defaultHtmlResolver } from "./renderToHtml.mjs";
|
|
8
|
+
//#region src/html/renderToHtmlStream.ts
|
|
9
|
+
/**
|
|
10
|
+
* Streaming HTML renderer — yields HTML chunks incrementally.
|
|
11
|
+
*
|
|
12
|
+
* Same rendering pipeline as `renderToHtml` but yields string fragments
|
|
13
|
+
* as each field/element is produced instead of building the entire string
|
|
14
|
+
* in memory. Use for server-side rendering where you want to start
|
|
15
|
+
* flushing the response before the full schema is rendered.
|
|
16
|
+
*
|
|
17
|
+
* Three output formats:
|
|
18
|
+
*
|
|
19
|
+
* - `renderToHtmlChunks(schema, options)` → sync `Iterable<string>`
|
|
20
|
+
* - `renderToHtmlStream(schema, options)` → async `AsyncIterable<string>`
|
|
21
|
+
* - `renderToHtmlReadable(schema, options)` → web `ReadableStream<string>`
|
|
22
|
+
*
|
|
23
|
+
* Chunk boundaries:
|
|
24
|
+
* - Object: opening tag, one chunk per field, closing tag
|
|
25
|
+
* - Array: opening tag, one chunk per item, closing tag
|
|
26
|
+
* - Record: opening tag, one chunk per entry, closing tag
|
|
27
|
+
* - Leaf types (string, number, boolean, enum, literal, unknown):
|
|
28
|
+
* rendered entirely as one chunk
|
|
29
|
+
*
|
|
30
|
+
* All HTML construction uses `h()` from `html.ts` — the streaming module
|
|
31
|
+
* manually yields the opening tag, then children, then the closing tag.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Yield the opening tag of an element (e.g. `<fieldset class="sc-object">`).
|
|
35
|
+
* For void elements, yields the complete self-closing tag.
|
|
36
|
+
*/
|
|
37
|
+
function yieldOpen(el) {
|
|
38
|
+
const attrs = serializeAttributes(el.attributes);
|
|
39
|
+
return `<${el.tag}${attrs}>`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Yield the closing tag of an element (e.g. `</fieldset>`).
|
|
43
|
+
* Returns empty string for void elements.
|
|
44
|
+
*/
|
|
45
|
+
function yieldClose(el) {
|
|
46
|
+
if (VOID_ELEMENTS.has(el.tag)) return "";
|
|
47
|
+
return `</${el.tag}>`;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Render a schema to HTML string chunks, yielded incrementally.
|
|
51
|
+
*
|
|
52
|
+
* Each yielded chunk is a self-contained HTML fragment. Concatenating
|
|
53
|
+
* all chunks produces the same output as `renderToHtml`.
|
|
54
|
+
*
|
|
55
|
+
* @returns Sync iterable of HTML string chunks
|
|
56
|
+
*/
|
|
57
|
+
function* renderToHtmlChunks(schema, options = {}) {
|
|
58
|
+
const tree = prepareTree(schema, options);
|
|
59
|
+
const resolver = options.resolver ?? defaultHtmlResolver;
|
|
60
|
+
const mergedResolver = mergeHtmlResolvers(resolver, defaultHtmlResolver);
|
|
61
|
+
yield* streamField(tree, options.value, mergedResolver, "", resolver);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Render a schema to HTML string chunks asynchronously.
|
|
65
|
+
*
|
|
66
|
+
* Identical chunk boundaries to `renderToHtmlChunks` but yields via
|
|
67
|
+
* an async generator. Use with `for await...of` or pipe to a response.
|
|
68
|
+
*
|
|
69
|
+
* @returns Async iterable of HTML string chunks
|
|
70
|
+
*/
|
|
71
|
+
async function* renderToHtmlStream(schema, options = {}) {
|
|
72
|
+
const tree = prepareTree(schema, options);
|
|
73
|
+
const resolver = options.resolver ?? defaultHtmlResolver;
|
|
74
|
+
const mergedResolver = mergeHtmlResolvers(resolver, defaultHtmlResolver);
|
|
75
|
+
for (const chunk of streamField(tree, options.value, mergedResolver, "", resolver)) {
|
|
76
|
+
yield chunk;
|
|
77
|
+
await schedulerYield();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* No-op await that yields control to the event loop.
|
|
82
|
+
*/
|
|
83
|
+
function schedulerYield() {
|
|
84
|
+
return Promise.resolve(void 0);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Render a schema to a web `ReadableStream<string>`.
|
|
88
|
+
*
|
|
89
|
+
* ```ts
|
|
90
|
+
* return new Response(renderToHtmlReadable(schema, { value }), {
|
|
91
|
+
* headers: { "Content-Type": "text/html" },
|
|
92
|
+
* });
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
function renderToHtmlReadable(schema, options = {}) {
|
|
96
|
+
const iterator = renderToHtmlChunks(schema, options)[Symbol.iterator]();
|
|
97
|
+
return new ReadableStream({
|
|
98
|
+
pull(controller) {
|
|
99
|
+
const result = iterator.next();
|
|
100
|
+
if (result.done) controller.close();
|
|
101
|
+
else controller.enqueue(result.value);
|
|
102
|
+
},
|
|
103
|
+
cancel() {
|
|
104
|
+
if (iterator.return !== void 0) iterator.return();
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function prepareTree(schema, options) {
|
|
109
|
+
const mergedMeta = { ...options.meta };
|
|
110
|
+
if (options.readOnly === true) mergedMeta.readOnly = true;
|
|
111
|
+
if (options.writeOnly === true) mergedMeta.writeOnly = true;
|
|
112
|
+
if (options.description !== void 0) mergedMeta.description = options.description;
|
|
113
|
+
const { jsonSchema, rootMeta, rootDocument } = normaliseSchema(schema, options.ref);
|
|
114
|
+
return walk(jsonSchema, {
|
|
115
|
+
componentMeta: mergedMeta,
|
|
116
|
+
rootMeta,
|
|
117
|
+
fieldOverrides: options.fields,
|
|
118
|
+
rootDocument
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
function* streamField(tree, value, mergedResolver, path, rawResolver) {
|
|
122
|
+
const type = tree.type;
|
|
123
|
+
if (type === "string" || type === "number" || type === "boolean" || type === "enum" || type === "literal" || type === "file" || type === "unknown") {
|
|
124
|
+
yield renderLeaf(tree, value, mergedResolver, path);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (type === "union" || type === "discriminatedUnion") {
|
|
128
|
+
yield* streamUnion(tree, value, mergedResolver, path, rawResolver);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (type === "object") {
|
|
132
|
+
yield* streamObject(tree, value, mergedResolver, path, rawResolver);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (type === "array") {
|
|
136
|
+
yield* streamArray(tree, value, mergedResolver, path, rawResolver);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (type === "record") {
|
|
140
|
+
yield* streamRecord(tree, value, mergedResolver, path, rawResolver);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
yield renderLeaf(tree, value, mergedResolver, path);
|
|
144
|
+
}
|
|
145
|
+
function* streamObject(tree, value, mergedResolver, path, rawResolver) {
|
|
146
|
+
const fields = tree.fields;
|
|
147
|
+
if (fields === void 0) return;
|
|
148
|
+
const obj = isObject(value) ? value : {};
|
|
149
|
+
const readOnly = tree.editability === "presentation";
|
|
150
|
+
const descriptionText = typeof tree.meta.description === "string" ? tree.meta.description : void 0;
|
|
151
|
+
const labelAttrs = ariaLabelAttrs(descriptionText);
|
|
152
|
+
if (readOnly) {
|
|
153
|
+
const dlAttrs = { class: "sc-object" };
|
|
154
|
+
Object.assign(dlAttrs, labelAttrs);
|
|
155
|
+
const dl = h("dl", dlAttrs);
|
|
156
|
+
const legend = descriptionText !== void 0 ? serialize(h("legend", {}, descriptionText)) : "";
|
|
157
|
+
yield `${yieldOpen(dl)}${legend}`;
|
|
158
|
+
for (const [key, field] of Object.entries(fields)) {
|
|
159
|
+
const label = typeof field.meta.description === "string" ? field.meta.description : key;
|
|
160
|
+
const childValue = obj[key];
|
|
161
|
+
const childHtml = renderFieldSync(field, childValue, mergedResolver, key, rawResolver);
|
|
162
|
+
yield `${serialize(h("dt", { class: "sc-label" }, label))}${serialize(h("dd", { class: "sc-value" }, raw(childHtml)))}`;
|
|
163
|
+
}
|
|
164
|
+
yield yieldClose(dl);
|
|
165
|
+
} else {
|
|
166
|
+
const fieldsetAttrs = { class: "sc-object" };
|
|
167
|
+
Object.assign(fieldsetAttrs, labelAttrs);
|
|
168
|
+
const fieldset = h("fieldset", fieldsetAttrs);
|
|
169
|
+
const legend = descriptionText !== void 0 ? serialize(h("legend", {}, descriptionText)) : "";
|
|
170
|
+
yield `${yieldOpen(fieldset)}${legend}`;
|
|
171
|
+
for (const [key, field] of Object.entries(fields)) {
|
|
172
|
+
const label = typeof field.meta.description === "string" ? field.meta.description : key;
|
|
173
|
+
const fieldId = buildInputId(path, key);
|
|
174
|
+
const childValue = obj[key];
|
|
175
|
+
const childChunks = [...streamField(field, childValue, mergedResolver, key, rawResolver)].join("");
|
|
176
|
+
const required = requiredIndicator(field);
|
|
177
|
+
const labelContent = [label];
|
|
178
|
+
if (required !== void 0) labelContent.push(required);
|
|
179
|
+
const fieldChildren = [h("label", {
|
|
180
|
+
class: "sc-label",
|
|
181
|
+
for: fieldId
|
|
182
|
+
}, ...labelContent), raw(childChunks)];
|
|
183
|
+
const hint = buildHintElement(key, field.constraints);
|
|
184
|
+
if (hint !== void 0) fieldChildren.push(hint);
|
|
185
|
+
yield serialize(h("div", { class: "sc-field" }, ...fieldChildren));
|
|
186
|
+
}
|
|
187
|
+
yield yieldClose(fieldset);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function* streamArray(tree, value, mergedResolver, path, rawResolver) {
|
|
191
|
+
const arr = Array.isArray(value) ? value : [];
|
|
192
|
+
const element = tree.element;
|
|
193
|
+
if (element === void 0) return;
|
|
194
|
+
const readOnly = tree.editability === "presentation";
|
|
195
|
+
const elementPath = typeof element.meta.description === "string" ? element.meta.description : "";
|
|
196
|
+
if (readOnly) {
|
|
197
|
+
const ul = h("ul", { class: "sc-array" });
|
|
198
|
+
yield yieldOpen(ul);
|
|
199
|
+
for (const item of arr) yield serialize(h("li", { class: "sc-item" }, raw(renderFieldSync(element, item, mergedResolver, elementPath, rawResolver))));
|
|
200
|
+
yield yieldClose(ul);
|
|
201
|
+
} else {
|
|
202
|
+
const div = h("div", { class: "sc-array" });
|
|
203
|
+
yield yieldOpen(div);
|
|
204
|
+
for (const item of arr) yield serialize(h("div", {}, raw(renderFieldSync(element, item, mergedResolver, elementPath, rawResolver))));
|
|
205
|
+
yield yieldClose(div);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function* streamRecord(tree, value, mergedResolver, path, rawResolver) {
|
|
209
|
+
const obj = isObject(value) ? value : {};
|
|
210
|
+
const valueType = tree.valueType;
|
|
211
|
+
if (valueType === void 0) return;
|
|
212
|
+
const readOnly = tree.editability === "presentation";
|
|
213
|
+
const attrs = {
|
|
214
|
+
class: "sc-record",
|
|
215
|
+
role: "group"
|
|
216
|
+
};
|
|
217
|
+
if (readOnly) {
|
|
218
|
+
const dl = h("dl", attrs);
|
|
219
|
+
yield yieldOpen(dl);
|
|
220
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
221
|
+
const childHtml = renderFieldSync(valueType, val, mergedResolver, key, rawResolver);
|
|
222
|
+
yield `${serialize(h("dt", { class: "sc-label" }, key))}${serialize(h("dd", { class: "sc-value" }, raw(childHtml)))}`;
|
|
223
|
+
}
|
|
224
|
+
yield yieldClose(dl);
|
|
225
|
+
} else {
|
|
226
|
+
const container = h("div", attrs);
|
|
227
|
+
yield yieldOpen(container);
|
|
228
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
229
|
+
const childHtml = renderFieldSync(valueType, val, mergedResolver, key, rawResolver);
|
|
230
|
+
yield serialize(h("div", { class: "sc-field" }, h("label", { class: "sc-label" }, key), raw(childHtml)));
|
|
231
|
+
}
|
|
232
|
+
yield yieldClose(container);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function* streamUnion(tree, value, mergedResolver, path, rawResolver) {
|
|
236
|
+
const options = tree.options;
|
|
237
|
+
if (options === void 0 || options.length === 0) {
|
|
238
|
+
if (value === void 0 || value === null) yield serialize(h("span", { class: "sc-value sc-value--empty" }, "—"));
|
|
239
|
+
else yield serialize(h("span", { class: "sc-value" }, JSON.stringify(value)));
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const target = matchUnionOption(options, value) ?? options[0];
|
|
243
|
+
if (target !== void 0) yield* streamField(target, value, mergedResolver, typeof target.meta.description === "string" ? target.meta.description : "", rawResolver);
|
|
244
|
+
else yield serialize(h("span", { class: "sc-value sc-value--empty" }, "—"));
|
|
245
|
+
}
|
|
246
|
+
function renderLeaf(tree, value, mergedResolver, path) {
|
|
247
|
+
const renderFn = getHtmlRenderFn(tree.type, mergedResolver);
|
|
248
|
+
if (renderFn !== void 0) {
|
|
249
|
+
const props = {
|
|
250
|
+
value,
|
|
251
|
+
readOnly: tree.editability === "presentation",
|
|
252
|
+
writeOnly: tree.editability === "input",
|
|
253
|
+
meta: tree.meta,
|
|
254
|
+
constraints: tree.constraints,
|
|
255
|
+
path,
|
|
256
|
+
tree,
|
|
257
|
+
renderChild: () => ""
|
|
258
|
+
};
|
|
259
|
+
if (tree.enumValues !== void 0) props.enumValues = tree.enumValues;
|
|
260
|
+
if (tree.element !== void 0) props.element = tree.element;
|
|
261
|
+
if (tree.fields !== void 0) props.fields = tree.fields;
|
|
262
|
+
if (tree.options !== void 0) props.options = tree.options;
|
|
263
|
+
if (tree.discriminator !== void 0) props.discriminator = tree.discriminator;
|
|
264
|
+
if (tree.keyType !== void 0) props.keyType = tree.keyType;
|
|
265
|
+
if (tree.valueType !== void 0) props.valueType = tree.valueType;
|
|
266
|
+
return renderFn(props);
|
|
267
|
+
}
|
|
268
|
+
if (value === void 0 || value === null) return serialize(h("span", { class: "sc-value sc-value--empty" }, "—"));
|
|
269
|
+
return serialize(h("span", { class: "sc-value" }, typeof value === "string" ? value : JSON.stringify(value)));
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Render a field synchronously to a string, recursively streaming children.
|
|
273
|
+
*/
|
|
274
|
+
function renderFieldSync(tree, value, mergedResolver, path, rawResolver) {
|
|
275
|
+
return [...streamField(tree, value, mergedResolver, path, rawResolver)].join("");
|
|
276
|
+
}
|
|
277
|
+
function matchUnionOption(options, value) {
|
|
278
|
+
if (typeof value === "string") return options.find((o) => o.type === "string" || o.type === "enum");
|
|
279
|
+
if (typeof value === "number") return options.find((o) => o.type === "number");
|
|
280
|
+
if (typeof value === "boolean") return options.find((o) => o.type === "boolean");
|
|
281
|
+
if (Array.isArray(value)) return options.find((o) => o.type === "array");
|
|
282
|
+
if (typeof value === "object" && value !== null) return options.find((o) => o.type === "object");
|
|
283
|
+
}
|
|
284
|
+
//#endregion
|
|
285
|
+
export { renderToHtmlChunks, renderToHtmlReadable, renderToHtmlStream };
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default styles for Schema Components HTML output.
|
|
3
|
+
*
|
|
4
|
+
* All classes use the `sc-` prefix to avoid collisions.
|
|
5
|
+
* Import this stylesheet when using the HTML renderer without
|
|
6
|
+
* a custom theme adapter.
|
|
7
|
+
*
|
|
8
|
+
* ```html
|
|
9
|
+
* <link rel="stylesheet" href="node_modules/@scalar/schema-components/dist/styles.css">
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/* ---------------------------------------------------------------------- */
|
|
14
|
+
/* Object containers */
|
|
15
|
+
/* ---------------------------------------------------------------------- */
|
|
16
|
+
|
|
17
|
+
.sc-object {
|
|
18
|
+
border: 1px solid #e2e8f0;
|
|
19
|
+
border-radius: 0.375rem;
|
|
20
|
+
padding: 1rem;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.sc-object legend {
|
|
24
|
+
font-weight: 600;
|
|
25
|
+
font-size: 0.875rem;
|
|
26
|
+
color: #334155;
|
|
27
|
+
padding: 0 0.25rem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* ---------------------------------------------------------------------- */
|
|
31
|
+
/* Fields */
|
|
32
|
+
/* ---------------------------------------------------------------------- */
|
|
33
|
+
|
|
34
|
+
.sc-field {
|
|
35
|
+
margin-bottom: 0.75rem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.sc-field:last-child {
|
|
39
|
+
margin-bottom: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.sc-label {
|
|
43
|
+
display: block;
|
|
44
|
+
font-size: 0.875rem;
|
|
45
|
+
font-weight: 500;
|
|
46
|
+
color: #374151;
|
|
47
|
+
margin-bottom: 0.25rem;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.sc-required {
|
|
51
|
+
color: #dc2626;
|
|
52
|
+
font-weight: 600;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* ---------------------------------------------------------------------- */
|
|
56
|
+
/* Inputs */
|
|
57
|
+
/* ---------------------------------------------------------------------- */
|
|
58
|
+
|
|
59
|
+
.sc-input {
|
|
60
|
+
width: 100%;
|
|
61
|
+
padding: 0.375rem 0.5rem;
|
|
62
|
+
border: 1px solid #d1d5db;
|
|
63
|
+
border-radius: 0.25rem;
|
|
64
|
+
font-size: 0.875rem;
|
|
65
|
+
line-height: 1.25rem;
|
|
66
|
+
color: #111827;
|
|
67
|
+
background-color: #fff;
|
|
68
|
+
box-sizing: border-box;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.sc-input:focus {
|
|
72
|
+
outline: 2px solid #3b82f6;
|
|
73
|
+
outline-offset: -1px;
|
|
74
|
+
border-color: transparent;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.sc-input[type="checkbox"] {
|
|
78
|
+
width: auto;
|
|
79
|
+
margin: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* ---------------------------------------------------------------------- */
|
|
83
|
+
/* Read-only values */
|
|
84
|
+
/* ---------------------------------------------------------------------- */
|
|
85
|
+
|
|
86
|
+
.sc-value {
|
|
87
|
+
font-size: 0.875rem;
|
|
88
|
+
color: #111827;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.sc-value--empty {
|
|
92
|
+
color: #9ca3af;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.sc-value--boolean {
|
|
96
|
+
font-weight: 500;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.sc-value[href] {
|
|
100
|
+
color: #2563eb;
|
|
101
|
+
text-decoration: none;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.sc-value[href]:hover {
|
|
105
|
+
text-decoration: underline;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* ---------------------------------------------------------------------- */
|
|
109
|
+
/* Arrays */
|
|
110
|
+
/* ---------------------------------------------------------------------- */
|
|
111
|
+
|
|
112
|
+
.sc-array {
|
|
113
|
+
list-style: none;
|
|
114
|
+
padding: 0;
|
|
115
|
+
margin: 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.sc-array > div {
|
|
119
|
+
margin-bottom: 0.375rem;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.sc-array > div:last-child {
|
|
123
|
+
margin-bottom: 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.sc-item {
|
|
127
|
+
margin-bottom: 0.375rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.sc-item:last-child {
|
|
131
|
+
margin-bottom: 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* ---------------------------------------------------------------------- */
|
|
135
|
+
/* Records */
|
|
136
|
+
/* ---------------------------------------------------------------------- */
|
|
137
|
+
|
|
138
|
+
.sc-record {
|
|
139
|
+
margin: 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* ---------------------------------------------------------------------- */
|
|
143
|
+
/* Constraint hints */
|
|
144
|
+
/* ---------------------------------------------------------------------- */
|
|
145
|
+
|
|
146
|
+
.sc-hint {
|
|
147
|
+
display: block;
|
|
148
|
+
font-size: 0.75rem;
|
|
149
|
+
color: #6b7280;
|
|
150
|
+
margin-top: 0.25rem;
|
|
151
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { c as InferResponseFields, m as SchemaMeta, o as InferParameterOverrides, r as FieldOverride, s as InferRequestBodyFields } from "../types-BU0ETFHk.mjs";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/openapi/components.d.ts
|
|
5
|
+
interface ApiOperationProps<Doc = unknown, Path extends string = string, Method extends string = string> {
|
|
6
|
+
schema: Doc;
|
|
7
|
+
path: Path;
|
|
8
|
+
method: Method;
|
|
9
|
+
requestBodyValue?: unknown;
|
|
10
|
+
onRequestBodyChange?: (value: unknown) => void;
|
|
11
|
+
responseValue?: unknown;
|
|
12
|
+
meta?: SchemaMeta;
|
|
13
|
+
requestBodyFields?: Doc extends Record<string, unknown> ? InferRequestBodyFields<Doc, Path, Method> : Record<string, FieldOverride>;
|
|
14
|
+
}
|
|
15
|
+
declare function ApiOperation<Doc = unknown, Path extends string = string, Method extends string = string>({
|
|
16
|
+
schema: doc,
|
|
17
|
+
path,
|
|
18
|
+
method,
|
|
19
|
+
requestBodyValue,
|
|
20
|
+
onRequestBodyChange,
|
|
21
|
+
responseValue,
|
|
22
|
+
meta,
|
|
23
|
+
requestBodyFields
|
|
24
|
+
}: ApiOperationProps<Doc, Path, Method>): ReactNode;
|
|
25
|
+
interface ApiParametersProps<Doc = unknown, Path extends string = string, Method extends string = string> {
|
|
26
|
+
schema: Doc;
|
|
27
|
+
path: Path;
|
|
28
|
+
method: Method;
|
|
29
|
+
meta?: SchemaMeta;
|
|
30
|
+
overrides?: Doc extends Record<string, unknown> ? InferParameterOverrides<Doc, Path, Method> : Record<string, FieldOverride>;
|
|
31
|
+
}
|
|
32
|
+
declare function ApiParameters<Doc = unknown, Path extends string = string, Method extends string = string>({
|
|
33
|
+
schema: doc,
|
|
34
|
+
path,
|
|
35
|
+
method,
|
|
36
|
+
meta,
|
|
37
|
+
overrides
|
|
38
|
+
}: ApiParametersProps<Doc, Path, Method>): ReactNode;
|
|
39
|
+
interface ApiRequestBodyProps<Doc = unknown, Path extends string = string, Method extends string = string> {
|
|
40
|
+
schema: Doc;
|
|
41
|
+
path: Path;
|
|
42
|
+
method: Method;
|
|
43
|
+
value?: unknown;
|
|
44
|
+
onChange?: (value: unknown) => void;
|
|
45
|
+
meta?: SchemaMeta;
|
|
46
|
+
fields?: Doc extends Record<string, unknown> ? InferRequestBodyFields<Doc, Path, Method> : Record<string, FieldOverride>;
|
|
47
|
+
}
|
|
48
|
+
declare function ApiRequestBody<Doc = unknown, Path extends string = string, Method extends string = string>({
|
|
49
|
+
schema: doc,
|
|
50
|
+
path,
|
|
51
|
+
method,
|
|
52
|
+
value,
|
|
53
|
+
onChange,
|
|
54
|
+
meta,
|
|
55
|
+
fields
|
|
56
|
+
}: ApiRequestBodyProps<Doc, Path, Method>): ReactNode;
|
|
57
|
+
interface ApiResponseProps<Doc = unknown, Path extends string = string, Method extends string = string, Status extends string = string> {
|
|
58
|
+
schema: Doc;
|
|
59
|
+
path: Path;
|
|
60
|
+
method: Method;
|
|
61
|
+
status: Status;
|
|
62
|
+
value?: unknown;
|
|
63
|
+
meta?: SchemaMeta;
|
|
64
|
+
fields?: Doc extends Record<string, unknown> ? InferResponseFields<Doc, Path, Method, Status> : Record<string, FieldOverride>;
|
|
65
|
+
}
|
|
66
|
+
declare function ApiResponse<Doc = unknown, Path extends string = string, Method extends string = string, Status extends string = string>({
|
|
67
|
+
schema: doc,
|
|
68
|
+
path,
|
|
69
|
+
method,
|
|
70
|
+
status,
|
|
71
|
+
value,
|
|
72
|
+
meta,
|
|
73
|
+
fields
|
|
74
|
+
}: ApiResponseProps<Doc, Path, Method, Status>): ReactNode;
|
|
75
|
+
//#endregion
|
|
76
|
+
export { ApiOperation, ApiOperationProps, ApiParameters, ApiParametersProps, ApiRequestBody, ApiRequestBodyProps, ApiResponse, ApiResponseProps };
|