schema-components 2.0.1 → 2.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/README.md +98 -1
- package/dist/SchemaComponent-B__6-5-E.d.mts +277 -0
- package/dist/SchemaComponent-BxzzsHsK.mjs +668 -0
- package/dist/adapter-ktQaheWB.d.mts +213 -0
- package/dist/constructorTypes-BdCiMS6e.d.mts +30 -0
- package/dist/core/adapter.d.mts +3 -213
- package/dist/core/adapter.mjs +33 -25
- package/dist/core/constraintHint.d.mts +1 -1
- package/dist/core/constraints.d.mts +2 -2
- package/dist/core/contexts.d.mts +71 -0
- package/dist/core/contexts.mjs +1 -0
- package/dist/core/diagnostics.d.mts +1 -1
- package/dist/core/errors.d.mts +1 -1
- package/dist/core/fieldOrder.d.mts +1 -1
- package/dist/{react → core}/fieldPath.d.mts +2 -2
- package/dist/{react → core}/fieldPath.mjs +3 -3
- package/dist/core/formats.d.mts +1 -1
- package/dist/core/guards.d.mts +2 -2
- package/dist/core/guards.mjs +2 -2
- package/dist/core/inferValue.d.mts +1 -1
- package/dist/core/limits.d.mts +1 -1
- package/dist/core/merge.d.mts +1 -1
- package/dist/core/normalise.d.mts +6 -6
- package/dist/core/normalise.mjs +1 -1
- package/dist/core/openapi30.d.mts +1 -1
- package/dist/core/openapi30.mjs +1 -1
- package/dist/core/ref.d.mts +1 -1
- package/dist/core/renderField.d.mts +147 -0
- package/dist/core/renderField.mjs +81 -0
- package/dist/core/renderer.d.mts +2 -199
- package/dist/core/swagger2.d.mts +1 -1
- package/dist/core/swagger2.mjs +1 -1
- package/dist/core/typeInference.d.mts +1 -981
- package/dist/core/types.d.mts +1 -1
- package/dist/core/unionMatch.d.mts +1 -1
- package/dist/core/uri.d.mts +2 -2
- package/dist/core/uri.mjs +2 -2
- package/dist/core/version.d.mts +1 -1
- package/dist/core/walkBuilders.d.mts +4 -4
- package/dist/core/walkBuilders.mjs +1 -1
- package/dist/core/walker.d.mts +1 -1
- package/dist/core/walker.mjs +3 -3
- package/dist/{errors-Dki7tji4.d.mts → errors-DbaI04x2.d.mts} +1 -1
- package/dist/html/a11y.d.mts +2 -2
- package/dist/html/html.d.mts +10 -8
- package/dist/html/renderToHtml.d.mts +5 -5
- package/dist/html/renderToHtml.mjs +45 -24
- package/dist/html/renderToHtmlStream.d.mts +5 -5
- package/dist/html/renderers.d.mts +1 -1
- package/dist/html/streamRenderers.d.mts +3 -3
- package/dist/{inferValue-PPXWJpbN.d.mts → inferValue-eAnh50EM.d.mts} +6 -6
- package/dist/lit/SchemaComponent.d.mts +125 -0
- package/dist/lit/SchemaComponent.mjs +2 -0
- package/dist/lit/SchemaField.d.mts +65 -0
- package/dist/lit/SchemaField.mjs +2 -0
- package/dist/lit/SchemaView.d.mts +14 -0
- package/dist/lit/SchemaView.mjs +2 -0
- package/dist/lit/constructorTypes.d.mts +2 -0
- package/dist/lit/constructorTypes.mjs +1 -0
- package/dist/lit/contexts.d.mts +78 -0
- package/dist/lit/contexts.mjs +238 -0
- package/dist/lit/defaultResolver.d.mts +33 -0
- package/dist/lit/defaultResolver.mjs +2 -0
- package/dist/lit/registry.d.mts +66 -0
- package/dist/lit/registry.mjs +2 -0
- package/dist/lit/renderers/baseElement.d.mts +131 -0
- package/dist/lit/renderers/baseElement.mjs +109 -0
- package/dist/lit/renderers/recordHelpers.d.mts +25 -0
- package/dist/lit/renderers/recordHelpers.mjs +55 -0
- package/dist/lit/renderers/scArray.d.mts +14 -0
- package/dist/lit/renderers/scArray.mjs +86 -0
- package/dist/lit/renderers/scBoolean.d.mts +15 -0
- package/dist/lit/renderers/scBoolean.mjs +47 -0
- package/dist/lit/renderers/scConditional.d.mts +23 -0
- package/dist/lit/renderers/scConditional.mjs +65 -0
- package/dist/lit/renderers/scDiscriminated.d.mts +23 -0
- package/dist/lit/renderers/scDiscriminated.mjs +138 -0
- package/dist/lit/renderers/scEnum.d.mts +16 -0
- package/dist/lit/renderers/scEnum.mjs +66 -0
- package/dist/lit/renderers/scFile.d.mts +15 -0
- package/dist/lit/renderers/scFile.mjs +53 -0
- package/dist/lit/renderers/scLiteralNullNever.d.mts +30 -0
- package/dist/lit/renderers/scLiteralNullNever.mjs +57 -0
- package/dist/lit/renderers/scNumber.d.mts +15 -0
- package/dist/lit/renderers/scNumber.mjs +64 -0
- package/dist/lit/renderers/scObject.d.mts +14 -0
- package/dist/lit/renderers/scObject.mjs +57 -0
- package/dist/lit/renderers/scRecord.d.mts +14 -0
- package/dist/lit/renderers/scRecord.mjs +112 -0
- package/dist/lit/renderers/scString.d.mts +19 -0
- package/dist/lit/renderers/scString.mjs +165 -0
- package/dist/lit/renderers/scTuple.d.mts +14 -0
- package/dist/lit/renderers/scTuple.mjs +58 -0
- package/dist/lit/renderers/scUnion.d.mts +14 -0
- package/dist/lit/renderers/scUnion.mjs +44 -0
- package/dist/lit/renderers/scUnknown.d.mts +15 -0
- package/dist/lit/renderers/scUnknown.mjs +45 -0
- package/dist/lit/ssr.d.mts +37 -0
- package/dist/lit/ssr.mjs +9565 -0
- package/dist/lit/types.d.mts +2 -0
- package/dist/lit/types.mjs +1 -0
- package/dist/lit/widget.d.mts +71 -0
- package/dist/lit/widget.mjs +87 -0
- package/dist/{normalise-DB-Xtjmn.mjs → normalise-BkePrJ4v.mjs} +6 -6
- 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 +5 -5
- package/dist/openapi/components.mjs +1 -1
- package/dist/openapi/parser.d.mts +2 -2
- package/dist/openapi/resolve.d.mts +1 -1
- package/dist/openapi/resolve.mjs +1 -1
- package/dist/preact/SchemaComponent.d.mts +3 -0
- package/dist/preact/SchemaComponent.mjs +26 -0
- package/dist/preact/SchemaErrorBoundary.d.mts +2 -0
- package/dist/preact/SchemaErrorBoundary.mjs +20 -0
- package/dist/preact/SchemaView.d.mts +2 -0
- package/dist/preact/SchemaView.mjs +22 -0
- package/dist/preact/headless.d.mts +2 -0
- package/dist/preact/headless.mjs +18 -0
- package/dist/react/SchemaComponent.d.mts +3 -270
- package/dist/react/SchemaComponent.mjs +48 -39
- package/dist/react/SchemaErrorBoundary.mjs +7 -4
- package/dist/react/SchemaView.d.mts +11 -10
- package/dist/react/SchemaView.mjs +32 -29
- package/dist/react/a11y.d.mts +2 -2
- package/dist/react/fieldShell.d.mts +1 -1
- package/dist/react/headless.d.mts +1 -1
- package/dist/react/headlessRenderers.d.mts +2 -2
- package/dist/{ref-DdsbekXX.d.mts → ref-DWrQG1Er.d.mts} +1 -1
- package/dist/renderer-ab9E52Bp.d.mts +245 -0
- package/dist/solid/SchemaComponent.d.mts +136 -0
- package/dist/solid/SchemaComponent.mjs +391 -0
- package/dist/solid/SchemaErrorBoundary.d.mts +38 -0
- package/dist/solid/SchemaErrorBoundary.mjs +57 -0
- package/dist/solid/SchemaField.d.mts +40 -0
- package/dist/solid/SchemaField.mjs +113 -0
- package/dist/solid/SchemaView.d.mts +54 -0
- package/dist/solid/SchemaView.mjs +168 -0
- package/dist/solid/a11y.d.mts +70 -0
- package/dist/solid/a11y.mjs +71 -0
- package/dist/solid/contexts.d.mts +37 -0
- package/dist/solid/contexts.mjs +66 -0
- package/dist/solid/headless.d.mts +10 -0
- package/dist/solid/headless.mjs +27 -0
- package/dist/solid/renderers.d.mts +79 -0
- package/dist/solid/renderers.mjs +840 -0
- package/dist/solid/types.d.mts +90 -0
- package/dist/solid/types.mjs +1 -0
- package/dist/solid/widget.d.mts +29 -0
- package/dist/solid/widget.mjs +35 -0
- 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/typeInference-Y8tNEQJk.d.mts +983 -0
- package/dist/types-BCy7K3nk.d.mts +125 -0
- package/package.json +71 -1
- package/src/svelte/SchemaComponent.svelte +427 -0
- package/src/svelte/SchemaErrorBoundary.svelte +66 -0
- package/src/svelte/SchemaField.svelte +216 -0
- package/src/svelte/SchemaProvider.svelte +46 -0
- package/src/svelte/SchemaView.svelte +244 -0
- package/src/svelte/a11y.ts +112 -0
- package/src/svelte/contexts.ts +79 -0
- package/src/svelte/dispatch.ts +267 -0
- package/src/svelte/headless.ts +73 -0
- package/src/svelte/headlessFns.ts +124 -0
- package/src/svelte/renderers/Array.svelte +98 -0
- package/src/svelte/renderers/Boolean.svelte +43 -0
- package/src/svelte/renderers/Conditional.svelte +67 -0
- package/src/svelte/renderers/DiscriminatedUnion.svelte +197 -0
- package/src/svelte/renderers/Enum.svelte +53 -0
- package/src/svelte/renderers/Fallback.svelte +24 -0
- package/src/svelte/renderers/File.svelte +46 -0
- package/src/svelte/renderers/Literal.svelte +29 -0
- package/src/svelte/renderers/Mount.svelte +24 -0
- package/src/svelte/renderers/Negation.svelte +35 -0
- package/src/svelte/renderers/Never.svelte +24 -0
- package/src/svelte/renderers/Null.svelte +19 -0
- package/src/svelte/renderers/Number.svelte +68 -0
- package/src/svelte/renderers/Object.svelte +74 -0
- package/src/svelte/renderers/Record.svelte +134 -0
- package/src/svelte/renderers/RecursionSentinel.svelte +27 -0
- package/src/svelte/renderers/String.svelte +152 -0
- package/src/svelte/renderers/Tuple.svelte +84 -0
- package/src/svelte/renderers/Union.svelte +49 -0
- package/src/svelte/renderers/Unknown.svelte +42 -0
- package/src/svelte/svelte-modules.d.ts +25 -0
- package/src/svelte/types.ts +238 -0
- package/src/svelte/widget.ts +62 -0
- /package/dist/{diagnostics-BTrm3O6J.d.mts → diagnostics-mftUZI7c.d.mts} +0 -0
- /package/dist/{limits-x4OiyJxh.d.mts → limits-Vv9hUbI_.d.mts} +0 -0
- /package/dist/{types-BrYbjC7_.d.mts → types-BBQaEPfE.d.mts} +0 -0
- /package/dist/{version-DL8U5RuA.d.mts → version-BEBx10ND.d.mts} +0 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { defaultRecordValueLit } from "./recordHelpers.mjs";
|
|
3
|
+
import { html } from "lit";
|
|
4
|
+
//#region src/lit/renderers/scArray.ts
|
|
5
|
+
/**
|
|
6
|
+
* `<sc-array>` — Custom Element renderer for `ArrayField`.
|
|
7
|
+
*
|
|
8
|
+
* Mirrors React's `renderArray`: an ordered list in read-only mode,
|
|
9
|
+
* an editable list with per-item remove and footer add buttons in
|
|
10
|
+
* editable mode. Uses the same `defaultRecordValue()` helper as the
|
|
11
|
+
* record renderer for new entries — the resolver-agnostic default
|
|
12
|
+
* lives in `lit/recordHelpers.ts`.
|
|
13
|
+
*
|
|
14
|
+
* Parts: `list`, `item`, `remove`, `add`.
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
function ariaLabel(description) {
|
|
19
|
+
return typeof description === "string" ? description : void 0;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Lit Custom Element rendering an array schema field.
|
|
23
|
+
*
|
|
24
|
+
* Tag: `<sc-array>` (registered by `registerSchemaComponents`).
|
|
25
|
+
*/
|
|
26
|
+
var ScArray = class extends BaseScElement {
|
|
27
|
+
render() {
|
|
28
|
+
if (this.tree.type !== "array") return html``;
|
|
29
|
+
const arr = Array.isArray(this.value) ? this.value : [];
|
|
30
|
+
const element = this.tree.element;
|
|
31
|
+
if (element === void 0) return html``;
|
|
32
|
+
const label = ariaLabel(this.meta.description);
|
|
33
|
+
if (this.readOnly) {
|
|
34
|
+
if (arr.length === 0) return html``;
|
|
35
|
+
return html`<ul part="list" role="group" aria-label=${label ?? ""}>
|
|
36
|
+
${arr.map((item, i) => html`<li part="item">
|
|
37
|
+
${this.renderChild(element, item, () => {}, `[${String(i)}]`)}
|
|
38
|
+
</li>`)}
|
|
39
|
+
</ul>`;
|
|
40
|
+
}
|
|
41
|
+
const handleRemove = (index) => {
|
|
42
|
+
const next = arr.slice();
|
|
43
|
+
next.splice(index, 1);
|
|
44
|
+
this.emitChange(next);
|
|
45
|
+
};
|
|
46
|
+
const handleAdd = () => {
|
|
47
|
+
const next = arr.slice();
|
|
48
|
+
next.push(defaultRecordValueLit(element));
|
|
49
|
+
this.emitChange(next);
|
|
50
|
+
};
|
|
51
|
+
return html`<div role="group" aria-label=${label ?? ""}>
|
|
52
|
+
<ul part="list">
|
|
53
|
+
${arr.map((item, i) => {
|
|
54
|
+
const childChange = (v) => {
|
|
55
|
+
const nextArr = arr.slice();
|
|
56
|
+
nextArr[i] = v;
|
|
57
|
+
this.emitChange(nextArr);
|
|
58
|
+
};
|
|
59
|
+
return html`<li part="item">
|
|
60
|
+
${this.renderChild(element, item, childChange, `[${String(i)}]`)}
|
|
61
|
+
<button
|
|
62
|
+
part="remove"
|
|
63
|
+
type="button"
|
|
64
|
+
aria-label="Remove item ${String(i)}"
|
|
65
|
+
@click=${() => {
|
|
66
|
+
handleRemove(i);
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
Remove
|
|
70
|
+
</button>
|
|
71
|
+
</li>`;
|
|
72
|
+
})}
|
|
73
|
+
</ul>
|
|
74
|
+
<button
|
|
75
|
+
part="add"
|
|
76
|
+
type="button"
|
|
77
|
+
aria-label="Add item"
|
|
78
|
+
@click=${handleAdd}
|
|
79
|
+
>
|
|
80
|
+
Add
|
|
81
|
+
</button>
|
|
82
|
+
</div>`;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
//#endregion
|
|
86
|
+
export { ScArray };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scBoolean.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering a boolean-valued schema field.
|
|
7
|
+
*
|
|
8
|
+
* Tag: `<sc-boolean>` (registered by `registerSchemaComponents`).
|
|
9
|
+
*/
|
|
10
|
+
declare class ScBoolean extends BaseScElement {
|
|
11
|
+
render(): TemplateResult;
|
|
12
|
+
private handleChange;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ScBoolean };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import "../../core/cssClasses.mjs";
|
|
2
|
+
import { fieldDomId } from "../../core/idPath.mjs";
|
|
3
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
4
|
+
import { html } from "lit";
|
|
5
|
+
//#region src/lit/renderers/scBoolean.ts
|
|
6
|
+
/**
|
|
7
|
+
* `<sc-boolean>` — Custom Element renderer for `BooleanField`.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors React's `renderBoolean`: `<input type="checkbox">` in
|
|
10
|
+
* editable mode, `Yes` / `No` text in read-only mode.
|
|
11
|
+
*
|
|
12
|
+
* Parts: `input`, `value`.
|
|
13
|
+
*
|
|
14
|
+
* @packageDocumentation
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Lit Custom Element rendering a boolean-valued schema field.
|
|
18
|
+
*
|
|
19
|
+
* Tag: `<sc-boolean>` (registered by `registerSchemaComponents`).
|
|
20
|
+
*/
|
|
21
|
+
var ScBoolean = class extends BaseScElement {
|
|
22
|
+
render() {
|
|
23
|
+
const id = fieldDomId(this.path);
|
|
24
|
+
if (this.readOnly) {
|
|
25
|
+
if (typeof this.value !== "boolean") return html`<span part="value" id=${id}>${"—"}</span>`;
|
|
26
|
+
return html`<span part="value" id=${id}
|
|
27
|
+
>${this.value ? "Yes" : "No"}</span
|
|
28
|
+
>`;
|
|
29
|
+
}
|
|
30
|
+
const ariaLabel = typeof this.meta.description === "string" ? this.meta.description : void 0;
|
|
31
|
+
return html`<input
|
|
32
|
+
part="input"
|
|
33
|
+
id=${id}
|
|
34
|
+
type="checkbox"
|
|
35
|
+
.checked=${this.writeOnly ? false : this.value === true}
|
|
36
|
+
aria-label=${ariaLabel ?? ""}
|
|
37
|
+
@change=${this.handleChange}
|
|
38
|
+
/>`;
|
|
39
|
+
}
|
|
40
|
+
handleChange = (e) => {
|
|
41
|
+
const target = e.target;
|
|
42
|
+
if (!(target instanceof HTMLInputElement)) return;
|
|
43
|
+
this.emitChange(target.checked);
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { ScBoolean };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scConditional.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering a JSON Schema `if`/`then`/`else`
|
|
7
|
+
* conditional field.
|
|
8
|
+
*
|
|
9
|
+
* Tag: `<sc-conditional>` (registered by `registerSchemaComponents`).
|
|
10
|
+
*/
|
|
11
|
+
declare class ScConditional extends BaseScElement {
|
|
12
|
+
render(): TemplateResult;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Lit Custom Element rendering a JSON Schema `not` (negation) field.
|
|
16
|
+
*
|
|
17
|
+
* Tag: `<sc-negation>` (registered by `registerSchemaComponents`).
|
|
18
|
+
*/
|
|
19
|
+
declare class ScNegation extends BaseScElement {
|
|
20
|
+
render(): TemplateResult;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { ScConditional, ScNegation };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { SC_CLASSES } from "../../core/cssClasses.mjs";
|
|
2
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
3
|
+
import { html } from "lit";
|
|
4
|
+
//#region src/lit/renderers/scConditional.ts
|
|
5
|
+
/**
|
|
6
|
+
* `<sc-conditional>` and `<sc-negation>` — Custom Element renderers
|
|
7
|
+
* for the two JSON-Schema-composition variants.
|
|
8
|
+
*
|
|
9
|
+
* Mirror React's `renderConditional` and `renderNegation`: each clause
|
|
10
|
+
* is surfaced as a labelled `<fieldset>` with a discoverable structure
|
|
11
|
+
* so theme adapters and assistive tech can interpret the schema
|
|
12
|
+
* constraint as well as the rendered value.
|
|
13
|
+
*
|
|
14
|
+
* Parts: `fieldset`, `clause`.
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Lit Custom Element rendering a JSON Schema `if`/`then`/`else`
|
|
20
|
+
* conditional field.
|
|
21
|
+
*
|
|
22
|
+
* Tag: `<sc-conditional>` (registered by `registerSchemaComponents`).
|
|
23
|
+
*/
|
|
24
|
+
var ScConditional = class extends BaseScElement {
|
|
25
|
+
render() {
|
|
26
|
+
if (this.tree.type !== "conditional") return html``;
|
|
27
|
+
const { ifClause, thenClause, elseClause } = this.tree;
|
|
28
|
+
const onChange = (next) => {
|
|
29
|
+
this.emitChange(next);
|
|
30
|
+
};
|
|
31
|
+
return html`<fieldset part="fieldset" class=${SC_CLASSES.conditional}>
|
|
32
|
+
<div part="clause" class=${SC_CLASSES.conditionalIf}>
|
|
33
|
+
<strong>if:</strong>
|
|
34
|
+
${this.renderChild(ifClause, this.value, onChange)}
|
|
35
|
+
</div>
|
|
36
|
+
${thenClause === void 0 ? html`` : html`<div part="clause" class=${SC_CLASSES.conditionalThen}>
|
|
37
|
+
<strong>then:</strong>
|
|
38
|
+
${this.renderChild(thenClause, this.value, onChange)}
|
|
39
|
+
</div>`}
|
|
40
|
+
${elseClause === void 0 ? html`` : html`<div part="clause" class=${SC_CLASSES.conditionalElse}>
|
|
41
|
+
<strong>else:</strong>
|
|
42
|
+
${this.renderChild(elseClause, this.value, onChange)}
|
|
43
|
+
</div>`}
|
|
44
|
+
</fieldset>`;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Lit Custom Element rendering a JSON Schema `not` (negation) field.
|
|
49
|
+
*
|
|
50
|
+
* Tag: `<sc-negation>` (registered by `registerSchemaComponents`).
|
|
51
|
+
*/
|
|
52
|
+
var ScNegation = class extends BaseScElement {
|
|
53
|
+
render() {
|
|
54
|
+
if (this.tree.type !== "negation") return html``;
|
|
55
|
+
const onChange = (next) => {
|
|
56
|
+
this.emitChange(next);
|
|
57
|
+
};
|
|
58
|
+
return html`<fieldset part="fieldset" class=${SC_CLASSES.negation}>
|
|
59
|
+
<strong>Must NOT match:</strong>
|
|
60
|
+
${this.renderChild(this.tree.negated, this.value, onChange)}
|
|
61
|
+
</fieldset>`;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
//#endregion
|
|
65
|
+
export { ScConditional, ScNegation };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scDiscriminated.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Pure helper: convert a tab index into the new value the discriminated
|
|
7
|
+
* union should emit. Mirrors React's
|
|
8
|
+
* `discriminatedUnionValueForTab` so the contract is unit-testable
|
|
9
|
+
* without instantiating the Custom Element.
|
|
10
|
+
*/
|
|
11
|
+
declare function discriminatedUnionValueForTabLit(optionLabels: readonly string[], discKey: string, newIndex: number): Record<string, string> | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Lit Custom Element rendering a discriminated-union schema field.
|
|
14
|
+
*
|
|
15
|
+
* Tag: `<sc-discriminated>` (registered by `registerSchemaComponents`).
|
|
16
|
+
*/
|
|
17
|
+
declare class ScDiscriminated extends BaseScElement {
|
|
18
|
+
private pendingFocus;
|
|
19
|
+
render(): TemplateResult;
|
|
20
|
+
updated(): void;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { ScDiscriminated, discriminatedUnionValueForTabLit };
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { isObject } from "../../core/guards.mjs";
|
|
2
|
+
import "../../core/cssClasses.mjs";
|
|
3
|
+
import { panelIdFor, tabIdFor } from "../../core/idPath.mjs";
|
|
4
|
+
import { resolveDiscriminatedActive } from "../../core/unionMatch.mjs";
|
|
5
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
6
|
+
import { html } from "lit";
|
|
7
|
+
//#region src/lit/renderers/scDiscriminated.ts
|
|
8
|
+
/**
|
|
9
|
+
* `<sc-discriminated>` — Custom Element renderer for
|
|
10
|
+
* `DiscriminatedUnionField`.
|
|
11
|
+
*
|
|
12
|
+
* Implements the WAI-ARIA "Tabs with Automatic Activation" pattern in
|
|
13
|
+
* parity with React's `DiscriminatedUnionTabs`:
|
|
14
|
+
*
|
|
15
|
+
* - `ArrowRight` / `ArrowLeft` move between tabs with wrap-around
|
|
16
|
+
* - `Home` / `End` jump to the first / last tab
|
|
17
|
+
* - `role="tablist"` / `"tab"` / `"tabpanel"`, `aria-selected`,
|
|
18
|
+
* `aria-controls`, `aria-labelledby`
|
|
19
|
+
* - Roving tabindex: the active tab carries `tabindex="0"`, the rest
|
|
20
|
+
* `tabindex="-1"`
|
|
21
|
+
* - Selection and focus stay aligned on every keystroke
|
|
22
|
+
*
|
|
23
|
+
* Parts: `tablist`, `tab`, `tab-active`, `panel`.
|
|
24
|
+
*
|
|
25
|
+
* @packageDocumentation
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Pure helper: convert a tab index into the new value the discriminated
|
|
29
|
+
* union should emit. Mirrors React's
|
|
30
|
+
* `discriminatedUnionValueForTab` so the contract is unit-testable
|
|
31
|
+
* without instantiating the Custom Element.
|
|
32
|
+
*/
|
|
33
|
+
function discriminatedUnionValueForTabLit(optionLabels, discKey, newIndex) {
|
|
34
|
+
const label = optionLabels[newIndex];
|
|
35
|
+
if (label === void 0) return void 0;
|
|
36
|
+
return { [discKey]: label };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Lit Custom Element rendering a discriminated-union schema field.
|
|
40
|
+
*
|
|
41
|
+
* Tag: `<sc-discriminated>` (registered by `registerSchemaComponents`).
|
|
42
|
+
*/
|
|
43
|
+
var ScDiscriminated = class extends BaseScElement {
|
|
44
|
+
pendingFocus = false;
|
|
45
|
+
render() {
|
|
46
|
+
if (this.tree.type !== "discriminatedUnion") {
|
|
47
|
+
if (this.value === void 0 || this.value === null) return html`<span part="value">${"—"}</span>`;
|
|
48
|
+
return html`<span part="value"
|
|
49
|
+
>${JSON.stringify(this.value)}</span
|
|
50
|
+
>`;
|
|
51
|
+
}
|
|
52
|
+
const { options, discriminator: discKey } = this.tree;
|
|
53
|
+
if (options.length === 0) {
|
|
54
|
+
if (this.value === void 0 || this.value === null) return html`<span part="value">${"—"}</span>`;
|
|
55
|
+
return html`<span part="value"
|
|
56
|
+
>${JSON.stringify(this.value)}</span
|
|
57
|
+
>`;
|
|
58
|
+
}
|
|
59
|
+
const { optionLabels, activeIndex, activeOption } = resolveDiscriminatedActive(options, discKey, isObject(this.value) ? this.value : void 0);
|
|
60
|
+
if (this.readOnly) {
|
|
61
|
+
if (activeOption !== void 0) return this.renderChild(activeOption, this.value, (next) => {
|
|
62
|
+
this.emitChange(next);
|
|
63
|
+
});
|
|
64
|
+
return html`<span part="value">${"—"}</span>`;
|
|
65
|
+
}
|
|
66
|
+
const panelId = panelIdFor(this.path);
|
|
67
|
+
const wrapIndex = (index) => (index % options.length + options.length) % options.length;
|
|
68
|
+
const handleTabChange = (newIndex) => {
|
|
69
|
+
const next = discriminatedUnionValueForTabLit(optionLabels, discKey, newIndex);
|
|
70
|
+
if (next === void 0) return;
|
|
71
|
+
this.emitChange(next);
|
|
72
|
+
};
|
|
73
|
+
const handleKeyDown = (e) => {
|
|
74
|
+
let target;
|
|
75
|
+
if (e.key === "ArrowRight") target = wrapIndex(activeIndex + 1);
|
|
76
|
+
else if (e.key === "ArrowLeft") target = wrapIndex(activeIndex - 1);
|
|
77
|
+
else if (e.key === "Home") target = 0;
|
|
78
|
+
else if (e.key === "End") target = options.length - 1;
|
|
79
|
+
if (target === void 0) return;
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
if (target === activeIndex) return;
|
|
82
|
+
this.pendingFocus = true;
|
|
83
|
+
handleTabChange(target);
|
|
84
|
+
};
|
|
85
|
+
return html`<div part="container">
|
|
86
|
+
<div
|
|
87
|
+
part="tablist"
|
|
88
|
+
role="tablist"
|
|
89
|
+
aria-label="Select variant"
|
|
90
|
+
aria-orientation="horizontal"
|
|
91
|
+
@keydown=${handleKeyDown}
|
|
92
|
+
>
|
|
93
|
+
${options.map((_opt, i) => {
|
|
94
|
+
const tabId = tabIdFor(this.path, i);
|
|
95
|
+
const isActive = i === activeIndex;
|
|
96
|
+
return html`<button
|
|
97
|
+
part=${isActive ? "tab tab-active" : "tab"}
|
|
98
|
+
type="button"
|
|
99
|
+
role="tab"
|
|
100
|
+
id=${tabId}
|
|
101
|
+
aria-selected=${isActive ? "true" : "false"}
|
|
102
|
+
aria-controls=${panelId}
|
|
103
|
+
tabindex=${isActive ? 0 : -1}
|
|
104
|
+
@click=${() => {
|
|
105
|
+
handleTabChange(i);
|
|
106
|
+
}}
|
|
107
|
+
>
|
|
108
|
+
${optionLabels[i]}
|
|
109
|
+
</button>`;
|
|
110
|
+
})}
|
|
111
|
+
</div>
|
|
112
|
+
<div
|
|
113
|
+
part="panel"
|
|
114
|
+
role="tabpanel"
|
|
115
|
+
id=${panelId}
|
|
116
|
+
aria-labelledby=${tabIdFor(this.path, activeIndex)}
|
|
117
|
+
>
|
|
118
|
+
${activeOption === void 0 ? html`` : this.renderChild(activeOption, this.value, (next) => {
|
|
119
|
+
this.emitChange(next);
|
|
120
|
+
})}
|
|
121
|
+
</div>
|
|
122
|
+
</div>`;
|
|
123
|
+
}
|
|
124
|
+
updated() {
|
|
125
|
+
if (!this.pendingFocus) return;
|
|
126
|
+
this.pendingFocus = false;
|
|
127
|
+
if (this.tree.type !== "discriminatedUnion") return;
|
|
128
|
+
const { options, discriminator: discKey } = this.tree;
|
|
129
|
+
const { activeIndex } = resolveDiscriminatedActive(options, discKey, isObject(this.value) ? this.value : void 0);
|
|
130
|
+
const id = tabIdFor(this.path, activeIndex);
|
|
131
|
+
const root = this.shadowRoot;
|
|
132
|
+
if (root === null) return;
|
|
133
|
+
const tab = root.getElementById(id);
|
|
134
|
+
if (tab !== null && tab instanceof HTMLElement) tab.focus();
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
//#endregion
|
|
138
|
+
export { ScDiscriminated, discriminatedUnionValueForTabLit };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scEnum.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering an enumerated string-valued schema
|
|
7
|
+
* field.
|
|
8
|
+
*
|
|
9
|
+
* Tag: `<sc-enum>` (registered by `registerSchemaComponents`).
|
|
10
|
+
*/
|
|
11
|
+
declare class ScEnum extends BaseScElement {
|
|
12
|
+
render(): TemplateResult;
|
|
13
|
+
private handleChange;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { ScEnum };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { constraintHint } from "../../core/constraintHint.mjs";
|
|
2
|
+
import "../../core/cssClasses.mjs";
|
|
3
|
+
import { fieldDomId, hintIdFor } from "../../core/idPath.mjs";
|
|
4
|
+
import { displayJsonValue } from "../../core/walkBuilders.mjs";
|
|
5
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
6
|
+
import { html } from "lit";
|
|
7
|
+
//#region src/lit/renderers/scEnum.ts
|
|
8
|
+
/**
|
|
9
|
+
* `<sc-enum>` — Custom Element renderer for `EnumField`.
|
|
10
|
+
*
|
|
11
|
+
* Mirrors React's `renderEnum`: `<select>` listing each option, with
|
|
12
|
+
* a hint advertising any pattern / format constraints.
|
|
13
|
+
*
|
|
14
|
+
* Parts: `input`, `value`, `hint`.
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Lit Custom Element rendering an enumerated string-valued schema
|
|
20
|
+
* field.
|
|
21
|
+
*
|
|
22
|
+
* Tag: `<sc-enum>` (registered by `registerSchemaComponents`).
|
|
23
|
+
*/
|
|
24
|
+
var ScEnum = class extends BaseScElement {
|
|
25
|
+
render() {
|
|
26
|
+
const id = fieldDomId(this.path);
|
|
27
|
+
const enumValue = typeof this.value === "string" ? this.value : "";
|
|
28
|
+
if (this.readOnly) return html`<span part="value" id=${id}
|
|
29
|
+
>${enumValue.length === 0 ? "—" : enumValue}</span
|
|
30
|
+
>`;
|
|
31
|
+
const enumValues = this.tree.type === "enum" ? this.tree.enumValues : [];
|
|
32
|
+
const hint = constraintHint(this.constraints);
|
|
33
|
+
const describedBy = hint !== void 0 ? hintIdFor(id) : void 0;
|
|
34
|
+
const selected = this.writeOnly ? "" : enumValue;
|
|
35
|
+
return html`
|
|
36
|
+
<select
|
|
37
|
+
part="input"
|
|
38
|
+
id=${id}
|
|
39
|
+
.value=${selected}
|
|
40
|
+
aria-describedby=${describedBy ?? ""}
|
|
41
|
+
@change=${this.handleChange}
|
|
42
|
+
>
|
|
43
|
+
<option value="">Select${"…"}</option>
|
|
44
|
+
${enumValues.map((v) => {
|
|
45
|
+
const display = displayJsonValue(v);
|
|
46
|
+
return html`<option
|
|
47
|
+
value=${display}
|
|
48
|
+
?selected=${display === selected}
|
|
49
|
+
>
|
|
50
|
+
${display}
|
|
51
|
+
</option>`;
|
|
52
|
+
})}
|
|
53
|
+
</select>
|
|
54
|
+
${hint === void 0 ? html`` : html`<small part="hint" id=${hintIdFor(id)} class="sc-hint"
|
|
55
|
+
>${hint}</small
|
|
56
|
+
>`}
|
|
57
|
+
`;
|
|
58
|
+
}
|
|
59
|
+
handleChange = (e) => {
|
|
60
|
+
const target = e.target;
|
|
61
|
+
if (!(target instanceof HTMLSelectElement)) return;
|
|
62
|
+
this.emitChange(target.value);
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
//#endregion
|
|
66
|
+
export { ScEnum };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scFile.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering a file-upload schema field.
|
|
7
|
+
*
|
|
8
|
+
* Tag: `<sc-file>` (registered by `registerSchemaComponents`).
|
|
9
|
+
*/
|
|
10
|
+
declare class ScFile extends BaseScElement {
|
|
11
|
+
render(): TemplateResult;
|
|
12
|
+
private handleChange;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ScFile };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { constraintHint } from "../../core/constraintHint.mjs";
|
|
2
|
+
import { fieldDomId, hintIdFor } from "../../core/idPath.mjs";
|
|
3
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
4
|
+
import { html } from "lit";
|
|
5
|
+
//#region src/lit/renderers/scFile.ts
|
|
6
|
+
/**
|
|
7
|
+
* `<sc-file>` — Custom Element renderer for `FileField`.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors React's `renderFile`: `<input type="file">` honouring the
|
|
10
|
+
* schema's `contentMediaType` constraint via the `accept` attribute,
|
|
11
|
+
* plus a constraint hint.
|
|
12
|
+
*
|
|
13
|
+
* Parts: `input`, `hint`.
|
|
14
|
+
*
|
|
15
|
+
* @packageDocumentation
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Lit Custom Element rendering a file-upload schema field.
|
|
19
|
+
*
|
|
20
|
+
* Tag: `<sc-file>` (registered by `registerSchemaComponents`).
|
|
21
|
+
*/
|
|
22
|
+
var ScFile = class extends BaseScElement {
|
|
23
|
+
render() {
|
|
24
|
+
const id = fieldDomId(this.path);
|
|
25
|
+
const accept = this.constraints.mimeTypes?.join(",");
|
|
26
|
+
if (this.readOnly) return html`<span part="value" id=${id}>File field</span>`;
|
|
27
|
+
const hint = constraintHint(this.constraints);
|
|
28
|
+
const describedBy = hint !== void 0 ? hintIdFor(id) : void 0;
|
|
29
|
+
const ariaLabel = typeof this.meta.description === "string" ? this.meta.description : void 0;
|
|
30
|
+
return html`
|
|
31
|
+
<input
|
|
32
|
+
part="input"
|
|
33
|
+
id=${id}
|
|
34
|
+
type="file"
|
|
35
|
+
accept=${accept ?? ""}
|
|
36
|
+
aria-describedby=${describedBy ?? ""}
|
|
37
|
+
aria-label=${ariaLabel ?? ""}
|
|
38
|
+
@change=${this.handleChange}
|
|
39
|
+
/>
|
|
40
|
+
${hint === void 0 ? html`` : html`<small part="hint" id=${hintIdFor(id)} class="sc-hint"
|
|
41
|
+
>${hint}</small
|
|
42
|
+
>`}
|
|
43
|
+
`;
|
|
44
|
+
}
|
|
45
|
+
handleChange = (e) => {
|
|
46
|
+
const target = e.target;
|
|
47
|
+
if (!(target instanceof HTMLInputElement)) return;
|
|
48
|
+
const file = target.files?.[0];
|
|
49
|
+
if (file !== void 0) this.emitChange(file);
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
//#endregion
|
|
53
|
+
export { ScFile };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scLiteralNullNever.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering a `literal` schema field.
|
|
7
|
+
*
|
|
8
|
+
* Tag: `<sc-literal>` (registered by `registerSchemaComponents`).
|
|
9
|
+
*/
|
|
10
|
+
declare class ScLiteral extends BaseScElement {
|
|
11
|
+
render(): TemplateResult;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Lit Custom Element rendering a `null` schema field.
|
|
15
|
+
*
|
|
16
|
+
* Tag: `<sc-null>` (registered by `registerSchemaComponents`).
|
|
17
|
+
*/
|
|
18
|
+
declare class ScNull extends BaseScElement {
|
|
19
|
+
render(): TemplateResult;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Lit Custom Element rendering a `never` schema field.
|
|
23
|
+
*
|
|
24
|
+
* Tag: `<sc-never>` (registered by `registerSchemaComponents`).
|
|
25
|
+
*/
|
|
26
|
+
declare class ScNever extends BaseScElement {
|
|
27
|
+
render(): TemplateResult;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { ScLiteral, ScNever, ScNull };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { SC_CLASSES } from "../../core/cssClasses.mjs";
|
|
2
|
+
import { fieldDomId } from "../../core/idPath.mjs";
|
|
3
|
+
import { displayJsonValue } from "../../core/walkBuilders.mjs";
|
|
4
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
5
|
+
import { html } from "lit";
|
|
6
|
+
//#region src/lit/renderers/scLiteralNullNever.ts
|
|
7
|
+
/**
|
|
8
|
+
* `<sc-literal>`, `<sc-null>`, `<sc-never>` — Custom Element renderers
|
|
9
|
+
* for the three non-editable leaf types.
|
|
10
|
+
*
|
|
11
|
+
* Each emits a single `<span>` placeholder. The literal renderer
|
|
12
|
+
* displays the literal value (or comma-separated list); the null and
|
|
13
|
+
* never renderers display the em-dash and a `never matches` italic
|
|
14
|
+
* note respectively. Mirrors the React headless renderers.
|
|
15
|
+
*
|
|
16
|
+
* Parts: `value`.
|
|
17
|
+
*
|
|
18
|
+
* @packageDocumentation
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Lit Custom Element rendering a `literal` schema field.
|
|
22
|
+
*
|
|
23
|
+
* Tag: `<sc-literal>` (registered by `registerSchemaComponents`).
|
|
24
|
+
*/
|
|
25
|
+
var ScLiteral = class extends BaseScElement {
|
|
26
|
+
render() {
|
|
27
|
+
const id = fieldDomId(this.path);
|
|
28
|
+
if (this.tree.type !== "literal") return html`<span part="value" id=${id}>${"—"}</span>`;
|
|
29
|
+
const values = this.tree.literalValues;
|
|
30
|
+
if (values.length === 0) return html`<span part="value" id=${id}>${"—"}</span>`;
|
|
31
|
+
return html`<span part="value" id=${id}>${values.map((v) => displayJsonValue(v)).join(", ")}</span>`;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Lit Custom Element rendering a `null` schema field.
|
|
36
|
+
*
|
|
37
|
+
* Tag: `<sc-null>` (registered by `registerSchemaComponents`).
|
|
38
|
+
*/
|
|
39
|
+
var ScNull = class extends BaseScElement {
|
|
40
|
+
render() {
|
|
41
|
+
return html`<span part="value" id=${fieldDomId(this.path)}>${"—"}</span>`;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Lit Custom Element rendering a `never` schema field.
|
|
46
|
+
*
|
|
47
|
+
* Tag: `<sc-never>` (registered by `registerSchemaComponents`).
|
|
48
|
+
*/
|
|
49
|
+
var ScNever = class extends BaseScElement {
|
|
50
|
+
render() {
|
|
51
|
+
return html`<span part="value" id=${fieldDomId(this.path)} class=${SC_CLASSES.never}
|
|
52
|
+
><em>never matches</em></span
|
|
53
|
+
>`;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
57
|
+
export { ScLiteral, ScNever, ScNull };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scNumber.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering a number-valued schema field.
|
|
7
|
+
*
|
|
8
|
+
* Tag: `<sc-number>` (registered by `registerSchemaComponents`).
|
|
9
|
+
*/
|
|
10
|
+
declare class ScNumber extends BaseScElement {
|
|
11
|
+
render(): TemplateResult;
|
|
12
|
+
private handleInput;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ScNumber };
|