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,64 @@
|
|
|
1
|
+
import { constraintHint } from "../../core/constraintHint.mjs";
|
|
2
|
+
import "../../core/cssClasses.mjs";
|
|
3
|
+
import { fieldDomId, hintIdFor } from "../../core/idPath.mjs";
|
|
4
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
5
|
+
import { html } from "lit";
|
|
6
|
+
//#region src/lit/renderers/scNumber.ts
|
|
7
|
+
/**
|
|
8
|
+
* `<sc-number>` — Custom Element renderer for `NumberField`.
|
|
9
|
+
*
|
|
10
|
+
* Mirrors React's `renderNumber`: `<input type="number">` with
|
|
11
|
+
* integer-vs-decimal `step` and `inputmode` selection. The host
|
|
12
|
+
* element narrows on `tree.type === "number"` to read `isInteger`.
|
|
13
|
+
*
|
|
14
|
+
* Parts: `input`, `value`, `hint`.
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Lit Custom Element rendering a number-valued schema field.
|
|
20
|
+
*
|
|
21
|
+
* Tag: `<sc-number>` (registered by `registerSchemaComponents`).
|
|
22
|
+
*/
|
|
23
|
+
var ScNumber = class extends BaseScElement {
|
|
24
|
+
render() {
|
|
25
|
+
const id = fieldDomId(this.path);
|
|
26
|
+
if (this.readOnly) {
|
|
27
|
+
if (typeof this.value !== "number") return html`<span part="value" id=${id}>${"—"}</span>`;
|
|
28
|
+
return html`<span part="value" id=${id}
|
|
29
|
+
>${this.value.toLocaleString()}</span
|
|
30
|
+
>`;
|
|
31
|
+
}
|
|
32
|
+
const numValue = typeof this.value === "number" ? this.value : "";
|
|
33
|
+
const isInteger = this.tree.type === "number" ? this.tree.isInteger : false;
|
|
34
|
+
const inputMode = isInteger ? "numeric" : "decimal";
|
|
35
|
+
const multipleOf = this.constraints.multipleOf;
|
|
36
|
+
const step = multipleOf !== void 0 ? String(multipleOf) : isInteger ? "1" : void 0;
|
|
37
|
+
const hint = constraintHint(this.constraints);
|
|
38
|
+
const describedBy = hint !== void 0 ? hintIdFor(id) : void 0;
|
|
39
|
+
return html`
|
|
40
|
+
<input
|
|
41
|
+
part="input"
|
|
42
|
+
id=${id}
|
|
43
|
+
type="number"
|
|
44
|
+
inputmode=${inputMode}
|
|
45
|
+
step=${step ?? ""}
|
|
46
|
+
.value=${String(this.writeOnly ? "" : numValue)}
|
|
47
|
+
min=${this.constraints.minimum ?? ""}
|
|
48
|
+
max=${this.constraints.maximum ?? ""}
|
|
49
|
+
aria-describedby=${describedBy ?? ""}
|
|
50
|
+
@input=${this.handleInput}
|
|
51
|
+
/>
|
|
52
|
+
${hint === void 0 ? html`` : html`<small part="hint" id=${hintIdFor(id)} class="sc-hint"
|
|
53
|
+
>${hint}</small
|
|
54
|
+
>`}
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
handleInput = (e) => {
|
|
58
|
+
const target = e.target;
|
|
59
|
+
if (!(target instanceof HTMLInputElement)) return;
|
|
60
|
+
this.emitChange(Number(target.value));
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
//#endregion
|
|
64
|
+
export { ScNumber };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scObject.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering an object schema field.
|
|
7
|
+
*
|
|
8
|
+
* Tag: `<sc-object>` (registered by `registerSchemaComponents`).
|
|
9
|
+
*/
|
|
10
|
+
declare class ScObject extends BaseScElement {
|
|
11
|
+
render(): TemplateResult;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { ScObject };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { isObject } from "../../core/guards.mjs";
|
|
2
|
+
import { sortFieldsByOrder } from "../../core/fieldOrder.mjs";
|
|
3
|
+
import { fieldDomId } from "../../core/idPath.mjs";
|
|
4
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
5
|
+
import { html } from "lit";
|
|
6
|
+
//#region src/lit/renderers/scObject.ts
|
|
7
|
+
/**
|
|
8
|
+
* `<sc-object>` — Custom Element renderer for `ObjectField`.
|
|
9
|
+
*
|
|
10
|
+
* Mirrors React's `renderObject`: a `<fieldset>` with one `<label>`
|
|
11
|
+
* plus child renderer per property. Visibility / field-order respects
|
|
12
|
+
* the same `meta.visible === false` skip and `sortFieldsByOrder()`
|
|
13
|
+
* ordering as the React side.
|
|
14
|
+
*
|
|
15
|
+
* Parts: `fieldset`, `legend`, `field`, `label`.
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Lit Custom Element rendering an object schema field.
|
|
21
|
+
*
|
|
22
|
+
* Tag: `<sc-object>` (registered by `registerSchemaComponents`).
|
|
23
|
+
*/
|
|
24
|
+
var ScObject = class extends BaseScElement {
|
|
25
|
+
render() {
|
|
26
|
+
if (this.tree.type !== "object") return html``;
|
|
27
|
+
const obj = isObject(this.value) ? this.value : {};
|
|
28
|
+
const sortedEntries = sortFieldsByOrder(this.tree.fields);
|
|
29
|
+
return html`<fieldset part="fieldset">
|
|
30
|
+
${typeof this.meta.description === "string" ? html`<legend part="legend">${this.meta.description}</legend>` : html``}
|
|
31
|
+
${sortedEntries.filter(([, field]) => field.meta.visible !== false).map(([key, field]) => {
|
|
32
|
+
const childValue = obj[key];
|
|
33
|
+
const childId = fieldDomId(`${this.path}.${key}`);
|
|
34
|
+
const childChange = (v) => {
|
|
35
|
+
const updated = {};
|
|
36
|
+
for (const [k, val] of Object.entries(obj)) updated[k] = val;
|
|
37
|
+
updated[key] = v;
|
|
38
|
+
this.emitChange(updated);
|
|
39
|
+
};
|
|
40
|
+
return html`<div part="field">
|
|
41
|
+
<label part="label" for=${childId}>
|
|
42
|
+
${typeof field.meta.description === "string" ? field.meta.description : key}
|
|
43
|
+
${field.isOptional === false ? html`<span
|
|
44
|
+
aria-hidden="true"
|
|
45
|
+
class="sc-required"
|
|
46
|
+
>
|
|
47
|
+
*
|
|
48
|
+
</span>` : html``}
|
|
49
|
+
</label>
|
|
50
|
+
${this.renderChild(field, childValue, childChange, key)}
|
|
51
|
+
</div>`;
|
|
52
|
+
})}
|
|
53
|
+
</fieldset>`;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
//#endregion
|
|
57
|
+
export { ScObject };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scRecord.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering a record schema field.
|
|
7
|
+
*
|
|
8
|
+
* Tag: `<sc-record>` (registered by `registerSchemaComponents`).
|
|
9
|
+
*/
|
|
10
|
+
declare class ScRecord extends BaseScElement {
|
|
11
|
+
render(): TemplateResult;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { ScRecord };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { isObject } from "../../core/guards.mjs";
|
|
2
|
+
import "../../core/cssClasses.mjs";
|
|
3
|
+
import { fieldDomId } from "../../core/idPath.mjs";
|
|
4
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
5
|
+
import { defaultRecordValueLit, nextRecordKeyLit, renameRecordKeyLit } from "./recordHelpers.mjs";
|
|
6
|
+
import { html } from "lit";
|
|
7
|
+
//#region src/lit/renderers/scRecord.ts
|
|
8
|
+
/**
|
|
9
|
+
* `<sc-record>` — Custom Element renderer for `RecordField`.
|
|
10
|
+
*
|
|
11
|
+
* Mirrors React's `renderRecord`: editable key/value rows with rename
|
|
12
|
+
* (on input blur), per-row remove, and footer add. Read-only mode
|
|
13
|
+
* collapses to a labelled list with no controls.
|
|
14
|
+
*
|
|
15
|
+
* Parts: `list`, `item`, `key`, `remove`, `add`.
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
function ariaLabel(description) {
|
|
20
|
+
return typeof description === "string" ? description : void 0;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Lit Custom Element rendering a record schema field.
|
|
24
|
+
*
|
|
25
|
+
* Tag: `<sc-record>` (registered by `registerSchemaComponents`).
|
|
26
|
+
*/
|
|
27
|
+
var ScRecord = class extends BaseScElement {
|
|
28
|
+
render() {
|
|
29
|
+
if (this.tree.type !== "record") return html``;
|
|
30
|
+
const obj = isObject(this.value) ? this.value : {};
|
|
31
|
+
const valueType = this.tree.valueType;
|
|
32
|
+
const entries = Object.entries(obj);
|
|
33
|
+
const label = ariaLabel(this.meta.description);
|
|
34
|
+
if (this.readOnly) {
|
|
35
|
+
if (entries.length === 0) return html`<span part="value">${"—"}</span>`;
|
|
36
|
+
return html`<div role="group" aria-label=${label ?? ""}>
|
|
37
|
+
${entries.map(([key, value]) => {
|
|
38
|
+
return html`<div part="item">
|
|
39
|
+
<label for=${fieldDomId(`${this.path}.${key}`)}>${key}</label>
|
|
40
|
+
${this.renderChild(valueType, value, () => {}, key)}
|
|
41
|
+
</div>`;
|
|
42
|
+
})}
|
|
43
|
+
</div>`;
|
|
44
|
+
}
|
|
45
|
+
const handleRename = (oldKey, newKey) => {
|
|
46
|
+
const renamed = renameRecordKeyLit(obj, oldKey, newKey);
|
|
47
|
+
if (renamed === obj) return;
|
|
48
|
+
this.emitChange(renamed);
|
|
49
|
+
};
|
|
50
|
+
const handleValueChange = (key, next) => {
|
|
51
|
+
const updated = {};
|
|
52
|
+
for (const [k, val] of Object.entries(obj)) updated[k] = val;
|
|
53
|
+
updated[key] = next;
|
|
54
|
+
this.emitChange(updated);
|
|
55
|
+
};
|
|
56
|
+
const handleRemove = (key) => {
|
|
57
|
+
const next = {};
|
|
58
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
59
|
+
if (k === key) continue;
|
|
60
|
+
next[k] = v;
|
|
61
|
+
}
|
|
62
|
+
this.emitChange(next);
|
|
63
|
+
};
|
|
64
|
+
const handleAdd = () => {
|
|
65
|
+
const newKey = nextRecordKeyLit(Object.keys(obj));
|
|
66
|
+
const next = { ...obj };
|
|
67
|
+
next[newKey] = defaultRecordValueLit(valueType);
|
|
68
|
+
this.emitChange(next);
|
|
69
|
+
};
|
|
70
|
+
return html`<div part="list" role="group" aria-label=${label ?? ""}>
|
|
71
|
+
${entries.map(([key, value]) => {
|
|
72
|
+
return html`<div part="item">
|
|
73
|
+
<input
|
|
74
|
+
part="key"
|
|
75
|
+
id=${`${fieldDomId(`${this.path}.${key}`)}-key`}
|
|
76
|
+
type="text"
|
|
77
|
+
aria-label="Entry key"
|
|
78
|
+
.defaultValue=${key}
|
|
79
|
+
@blur=${(e) => {
|
|
80
|
+
const target = e.target;
|
|
81
|
+
if (!(target instanceof HTMLInputElement)) return;
|
|
82
|
+
handleRename(key, target.value);
|
|
83
|
+
}}
|
|
84
|
+
/>
|
|
85
|
+
${this.renderChild(valueType, value, (nextValue) => {
|
|
86
|
+
handleValueChange(key, nextValue);
|
|
87
|
+
}, key)}
|
|
88
|
+
<button
|
|
89
|
+
part="remove"
|
|
90
|
+
type="button"
|
|
91
|
+
aria-label="Remove entry ${key}"
|
|
92
|
+
@click=${() => {
|
|
93
|
+
handleRemove(key);
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
Remove
|
|
97
|
+
</button>
|
|
98
|
+
</div>`;
|
|
99
|
+
})}
|
|
100
|
+
<button
|
|
101
|
+
part="add"
|
|
102
|
+
type="button"
|
|
103
|
+
aria-label="Add entry"
|
|
104
|
+
@click=${handleAdd}
|
|
105
|
+
>
|
|
106
|
+
Add
|
|
107
|
+
</button>
|
|
108
|
+
</div>`;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
//#endregion
|
|
112
|
+
export { ScRecord };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scString.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering a string-valued schema field.
|
|
7
|
+
*
|
|
8
|
+
* Tag: `<sc-string>` (registered by `registerSchemaComponents`).
|
|
9
|
+
*/
|
|
10
|
+
declare class ScString extends BaseScElement {
|
|
11
|
+
render(): TemplateResult;
|
|
12
|
+
private renderReadOnly;
|
|
13
|
+
private renderEditable;
|
|
14
|
+
private renderHintMaybe;
|
|
15
|
+
private handleInput;
|
|
16
|
+
private handleSelect;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { ScString };
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { dateInputType } from "../../core/formats.mjs";
|
|
2
|
+
import { isSafeHyperlink, isSafeMailtoAddress } from "../../core/uri.mjs";
|
|
3
|
+
import { constraintHint } from "../../core/constraintHint.mjs";
|
|
4
|
+
import "../../core/cssClasses.mjs";
|
|
5
|
+
import { fieldDomId, hintIdFor } from "../../core/idPath.mjs";
|
|
6
|
+
import { displayJsonValue } from "../../core/walkBuilders.mjs";
|
|
7
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
8
|
+
import { html } from "lit";
|
|
9
|
+
//#region src/lit/renderers/scString.ts
|
|
10
|
+
/**
|
|
11
|
+
* `<sc-string>` — Custom Element renderer for `StringField`.
|
|
12
|
+
*
|
|
13
|
+
* Mirrors the React `renderString` headless renderer:
|
|
14
|
+
* `<input type="…">` in editable mode with `format`-aware type
|
|
15
|
+
* selection (`email`, `url`, `password`, date/time variants), or a
|
|
16
|
+
* `<span>` in read-only mode that linkifies safe `mailto:` / `http(s)`
|
|
17
|
+
* URLs and locale-formats date/time strings.
|
|
18
|
+
*
|
|
19
|
+
* Exposes the following CSS parts so consumers can theme without
|
|
20
|
+
* piercing the Shadow DOM:
|
|
21
|
+
*
|
|
22
|
+
* - `input` — the inner `<input>` element
|
|
23
|
+
* - `value` — the read-only `<span>` (or `<a>` for safe link formats)
|
|
24
|
+
* - `hint` — the constraint hint `<small>` element
|
|
25
|
+
*
|
|
26
|
+
* @packageDocumentation
|
|
27
|
+
*/
|
|
28
|
+
function formatDateTime(value) {
|
|
29
|
+
if (typeof value !== "string" || value.length === 0) return void 0;
|
|
30
|
+
const date = new Date(value);
|
|
31
|
+
if (isNaN(date.getTime())) return void 0;
|
|
32
|
+
return date.toLocaleString();
|
|
33
|
+
}
|
|
34
|
+
function formatDate(value) {
|
|
35
|
+
if (typeof value !== "string" || value.length === 0) return void 0;
|
|
36
|
+
const date = new Date(value);
|
|
37
|
+
if (isNaN(date.getTime())) return void 0;
|
|
38
|
+
return date.toLocaleDateString();
|
|
39
|
+
}
|
|
40
|
+
function formatTime(value) {
|
|
41
|
+
if (typeof value !== "string" || value.length === 0) return void 0;
|
|
42
|
+
const date = new Date(value);
|
|
43
|
+
if (isNaN(date.getTime())) return void 0;
|
|
44
|
+
return date.toLocaleTimeString();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Lit Custom Element rendering a string-valued schema field.
|
|
48
|
+
*
|
|
49
|
+
* Tag: `<sc-string>` (registered by `registerSchemaComponents`).
|
|
50
|
+
*/
|
|
51
|
+
var ScString = class extends BaseScElement {
|
|
52
|
+
render() {
|
|
53
|
+
const id = fieldDomId(this.path);
|
|
54
|
+
const strValue = typeof this.value === "string" ? this.value : "";
|
|
55
|
+
if (this.readOnly) return this.renderReadOnly(id, strValue);
|
|
56
|
+
return this.renderEditable(id, strValue);
|
|
57
|
+
}
|
|
58
|
+
renderReadOnly(id, strValue) {
|
|
59
|
+
if (strValue.length === 0) return html`<span part="value" id=${id}>${"—"}</span>`;
|
|
60
|
+
const format = this.constraints.format;
|
|
61
|
+
if (format === "email" && isSafeMailtoAddress(strValue)) return html`<a
|
|
62
|
+
part="value"
|
|
63
|
+
href=${`mailto:${strValue}`}
|
|
64
|
+
id=${id}
|
|
65
|
+
aria-readonly="true"
|
|
66
|
+
>${strValue}</a
|
|
67
|
+
>`;
|
|
68
|
+
if ((format === "uri" || format === "url") && isSafeHyperlink(strValue)) return html`<a
|
|
69
|
+
part="value"
|
|
70
|
+
href=${strValue}
|
|
71
|
+
id=${id}
|
|
72
|
+
aria-readonly="true"
|
|
73
|
+
>${strValue}</a
|
|
74
|
+
>`;
|
|
75
|
+
if (format === "date") return html`<span part="value" id=${id}
|
|
76
|
+
>${formatDate(strValue) ?? strValue}</span
|
|
77
|
+
>`;
|
|
78
|
+
if (format === "time") return html`<span part="value" id=${id}
|
|
79
|
+
>${formatTime(strValue) ?? strValue}</span
|
|
80
|
+
>`;
|
|
81
|
+
if (format === "date-time" || format === "datetime") return html`<span part="value" id=${id}
|
|
82
|
+
>${formatDateTime(strValue) ?? strValue}</span
|
|
83
|
+
>`;
|
|
84
|
+
return html`<span part="value" id=${id}>${strValue}</span>`;
|
|
85
|
+
}
|
|
86
|
+
renderEditable(id, strValue) {
|
|
87
|
+
const dateType = dateInputType(this.constraints.format);
|
|
88
|
+
const hint = constraintHint(this.constraints);
|
|
89
|
+
const hintTpl = this.renderHintMaybe(id, hint);
|
|
90
|
+
const describedBy = hint !== void 0 ? hintIdFor(id) : void 0;
|
|
91
|
+
if (dateType !== void 0) return html`
|
|
92
|
+
<input
|
|
93
|
+
part="input"
|
|
94
|
+
id=${id}
|
|
95
|
+
type=${dateType}
|
|
96
|
+
.value=${this.writeOnly ? "" : strValue}
|
|
97
|
+
aria-describedby=${describedBy ?? ""}
|
|
98
|
+
@input=${this.handleInput}
|
|
99
|
+
/>
|
|
100
|
+
${hintTpl}
|
|
101
|
+
`;
|
|
102
|
+
if (this.tree.type === "enum" && this.tree.enumValues.length > 0) {
|
|
103
|
+
const enumValues = this.tree.enumValues;
|
|
104
|
+
const selected = this.writeOnly ? "" : strValue;
|
|
105
|
+
return html`
|
|
106
|
+
<select
|
|
107
|
+
part="input"
|
|
108
|
+
id=${id}
|
|
109
|
+
.value=${selected}
|
|
110
|
+
aria-describedby=${describedBy ?? ""}
|
|
111
|
+
@change=${this.handleSelect}
|
|
112
|
+
>
|
|
113
|
+
<option value="">Select${"…"}</option>
|
|
114
|
+
${enumValues.map((v) => {
|
|
115
|
+
const display = displayJsonValue(v);
|
|
116
|
+
return html`<option
|
|
117
|
+
value=${display}
|
|
118
|
+
?selected=${display === selected}
|
|
119
|
+
>
|
|
120
|
+
${display}
|
|
121
|
+
</option>`;
|
|
122
|
+
})}
|
|
123
|
+
</select>
|
|
124
|
+
${hintTpl}
|
|
125
|
+
`;
|
|
126
|
+
}
|
|
127
|
+
const isCredential = this.writeOnly && this.constraints.format === "password";
|
|
128
|
+
const inputType = isCredential ? "password" : this.constraints.format === "email" ? "email" : this.constraints.format === "uri" ? "url" : "text";
|
|
129
|
+
const autoComplete = isCredential ? strValue.length > 0 ? "current-password" : "new-password" : void 0;
|
|
130
|
+
const placeholder = typeof this.meta.description === "string" ? this.meta.description : void 0;
|
|
131
|
+
return html`
|
|
132
|
+
<input
|
|
133
|
+
part="input"
|
|
134
|
+
id=${id}
|
|
135
|
+
type=${inputType}
|
|
136
|
+
autocomplete=${autoComplete ?? ""}
|
|
137
|
+
.value=${this.writeOnly ? "" : strValue}
|
|
138
|
+
placeholder=${placeholder ?? ""}
|
|
139
|
+
minlength=${this.constraints.minLength ?? ""}
|
|
140
|
+
maxlength=${this.constraints.maxLength ?? ""}
|
|
141
|
+
aria-describedby=${describedBy ?? ""}
|
|
142
|
+
@input=${this.handleInput}
|
|
143
|
+
/>
|
|
144
|
+
${hintTpl}
|
|
145
|
+
`;
|
|
146
|
+
}
|
|
147
|
+
renderHintMaybe(id, hint) {
|
|
148
|
+
if (hint === void 0) return html``;
|
|
149
|
+
return html`<small part="hint" id=${hintIdFor(id)} class="sc-hint"
|
|
150
|
+
>${hint}</small
|
|
151
|
+
>`;
|
|
152
|
+
}
|
|
153
|
+
handleInput = (e) => {
|
|
154
|
+
const target = e.target;
|
|
155
|
+
if (!(target instanceof HTMLInputElement)) return;
|
|
156
|
+
this.emitChange(target.value);
|
|
157
|
+
};
|
|
158
|
+
handleSelect = (e) => {
|
|
159
|
+
const target = e.target;
|
|
160
|
+
if (!(target instanceof HTMLSelectElement)) return;
|
|
161
|
+
this.emitChange(target.value);
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
//#endregion
|
|
165
|
+
export { ScString };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scTuple.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering a tuple schema field.
|
|
7
|
+
*
|
|
8
|
+
* Tag: `<sc-tuple>` (registered by `registerSchemaComponents`).
|
|
9
|
+
*/
|
|
10
|
+
declare class ScTuple extends BaseScElement {
|
|
11
|
+
render(): TemplateResult;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { ScTuple };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { html } from "lit";
|
|
3
|
+
//#region src/lit/renderers/scTuple.ts
|
|
4
|
+
/**
|
|
5
|
+
* `<sc-tuple>` — Custom Element renderer for `TupleField`.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors React's `renderTuple`: positional rendering of every
|
|
8
|
+
* `prefixItems` entry, plus rest items when present. Each entry is
|
|
9
|
+
* threaded with a `[i]` path suffix so child DOM ids remain unique.
|
|
10
|
+
*
|
|
11
|
+
* Parts: `tuple`, `item`, `rest-item`.
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
15
|
+
function ariaLabel(description) {
|
|
16
|
+
return typeof description === "string" ? description : void 0;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Lit Custom Element rendering a tuple schema field.
|
|
20
|
+
*
|
|
21
|
+
* Tag: `<sc-tuple>` (registered by `registerSchemaComponents`).
|
|
22
|
+
*/
|
|
23
|
+
var ScTuple = class extends BaseScElement {
|
|
24
|
+
render() {
|
|
25
|
+
if (this.tree.type !== "tuple") return html``;
|
|
26
|
+
const { prefixItems, restItems } = this.tree;
|
|
27
|
+
const arr = Array.isArray(this.value) ? this.value : [];
|
|
28
|
+
if (prefixItems.length === 0 && restItems === void 0 && arr.length === 0) return html``;
|
|
29
|
+
const restCount = restItems !== void 0 ? Math.max(arr.length - prefixItems.length, 0) : 0;
|
|
30
|
+
return html`<div part="tuple" role="group" aria-label=${ariaLabel(this.meta.description) ?? ""}>
|
|
31
|
+
${prefixItems.map((element, i) => {
|
|
32
|
+
const itemValue = arr[i];
|
|
33
|
+
const childChange = (v) => {
|
|
34
|
+
const next = arr.slice();
|
|
35
|
+
next[i] = v;
|
|
36
|
+
this.emitChange(next);
|
|
37
|
+
};
|
|
38
|
+
return html`<div part="item">
|
|
39
|
+
${this.renderChild(element, itemValue, childChange, `[${String(i)}]`)}
|
|
40
|
+
</div>`;
|
|
41
|
+
})}
|
|
42
|
+
${restItems === void 0 ? html`` : Array.from({ length: restCount }, (_, j) => {
|
|
43
|
+
const i = prefixItems.length + j;
|
|
44
|
+
const itemValue = arr[i];
|
|
45
|
+
const childChange = (v) => {
|
|
46
|
+
const next = arr.slice();
|
|
47
|
+
next[i] = v;
|
|
48
|
+
this.emitChange(next);
|
|
49
|
+
};
|
|
50
|
+
return html`<div part="rest-item">
|
|
51
|
+
${this.renderChild(restItems, itemValue, childChange, `[${String(i)}]`)}
|
|
52
|
+
</div>`;
|
|
53
|
+
})}
|
|
54
|
+
</div>`;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
//#endregion
|
|
58
|
+
export { ScTuple };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scUnion.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering a plain union schema field.
|
|
7
|
+
*
|
|
8
|
+
* Tag: `<sc-union>` (registered by `registerSchemaComponents`).
|
|
9
|
+
*/
|
|
10
|
+
declare class ScUnion extends BaseScElement {
|
|
11
|
+
render(): TemplateResult;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { ScUnion };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import "../../core/cssClasses.mjs";
|
|
2
|
+
import { matchUnionOption } from "../../core/unionMatch.mjs";
|
|
3
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
4
|
+
import { html } from "lit";
|
|
5
|
+
//#region src/lit/renderers/scUnion.ts
|
|
6
|
+
/**
|
|
7
|
+
* `<sc-union>` — Custom Element renderer for plain `UnionField`.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors React's `renderUnion`: picks the structurally matching option
|
|
10
|
+
* via {@link matchUnionOption} and delegates to `renderChild`. Falls
|
|
11
|
+
* back to the first option when no match is found, or to the em-dash
|
|
12
|
+
* placeholder when the union has no options.
|
|
13
|
+
*
|
|
14
|
+
* Parts: `value`.
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Lit Custom Element rendering a plain union schema field.
|
|
20
|
+
*
|
|
21
|
+
* Tag: `<sc-union>` (registered by `registerSchemaComponents`).
|
|
22
|
+
*/
|
|
23
|
+
var ScUnion = class extends BaseScElement {
|
|
24
|
+
render() {
|
|
25
|
+
const options = this.tree.type === "union" || this.tree.type === "discriminatedUnion" ? this.tree.options : void 0;
|
|
26
|
+
if (options === void 0 || options.length === 0) {
|
|
27
|
+
if (this.value === void 0 || this.value === null) return html`<span part="value">${"—"}</span>`;
|
|
28
|
+
return html`<span part="value"
|
|
29
|
+
>${JSON.stringify(this.value)}</span
|
|
30
|
+
>`;
|
|
31
|
+
}
|
|
32
|
+
const matched = matchUnionOption(options, this.value);
|
|
33
|
+
if (matched !== void 0) return this.renderChild(matched, this.value, (next) => {
|
|
34
|
+
this.emitChange(next);
|
|
35
|
+
});
|
|
36
|
+
const firstOption = options[0];
|
|
37
|
+
if (firstOption !== void 0) return this.renderChild(firstOption, this.value, (next) => {
|
|
38
|
+
this.emitChange(next);
|
|
39
|
+
});
|
|
40
|
+
return html`<span part="value">${"—"}</span>`;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
//#endregion
|
|
44
|
+
export { ScUnion };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseScElement } from "./baseElement.mjs";
|
|
2
|
+
import { TemplateResult } from "lit";
|
|
3
|
+
|
|
4
|
+
//#region src/lit/renderers/scUnknown.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Lit Custom Element rendering an unconstrained (`unknown`) schema field.
|
|
7
|
+
*
|
|
8
|
+
* Tag: `<sc-unknown>` (registered by `registerSchemaComponents`).
|
|
9
|
+
*/
|
|
10
|
+
declare class ScUnknown extends BaseScElement {
|
|
11
|
+
render(): TemplateResult;
|
|
12
|
+
private handleInput;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ScUnknown };
|
|
@@ -0,0 +1,45 @@
|
|
|
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/scUnknown.ts
|
|
6
|
+
/**
|
|
7
|
+
* `<sc-unknown>` — Custom Element renderer for `UnknownField`.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors React's `renderUnknown`: a JSON-encoded fallback for
|
|
10
|
+
* unconstrained values — `<input type="text">` in editable mode, a
|
|
11
|
+
* `<span>` showing the stringified value in read-only mode.
|
|
12
|
+
*
|
|
13
|
+
* Parts: `input`, `value`.
|
|
14
|
+
*
|
|
15
|
+
* @packageDocumentation
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Lit Custom Element rendering an unconstrained (`unknown`) schema field.
|
|
19
|
+
*
|
|
20
|
+
* Tag: `<sc-unknown>` (registered by `registerSchemaComponents`).
|
|
21
|
+
*/
|
|
22
|
+
var ScUnknown = class extends BaseScElement {
|
|
23
|
+
render() {
|
|
24
|
+
const id = fieldDomId(this.path);
|
|
25
|
+
if (this.readOnly) {
|
|
26
|
+
if (this.value === void 0 || this.value === null) return html`<span part="value" id=${id}>${"—"}</span>`;
|
|
27
|
+
return html`<span part="value" id=${id}>${typeof this.value === "string" ? this.value : JSON.stringify(this.value)}</span>`;
|
|
28
|
+
}
|
|
29
|
+
const strValue = typeof this.value === "string" ? this.value : "";
|
|
30
|
+
return html`<input
|
|
31
|
+
part="input"
|
|
32
|
+
id=${id}
|
|
33
|
+
type="text"
|
|
34
|
+
.value=${this.writeOnly ? "" : strValue}
|
|
35
|
+
@input=${this.handleInput}
|
|
36
|
+
/>`;
|
|
37
|
+
}
|
|
38
|
+
handleInput = (e) => {
|
|
39
|
+
const target = e.target;
|
|
40
|
+
if (!(target instanceof HTMLInputElement)) return;
|
|
41
|
+
this.emitChange(target.value);
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
//#endregion
|
|
45
|
+
export { ScUnknown };
|