Skip to content

Commit f9d9a58

Browse files
committed
docs: add pure html example + update manifests
1 parent a7eaf00 commit f9d9a58

File tree

6 files changed

+195
-141
lines changed

6 files changed

+195
-141
lines changed

README.md

Lines changed: 140 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# 📝  JSON Schema Form Element
22

3+
[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/owner/my-element)
4+
35
Effortless forms, with standards.
46

57
**Features**:
@@ -48,53 +50,58 @@ Jump to **implementations**:
4850
<details>
4951
<summary align="center"><strong>Table of Contents</strong></summary>
5052

51-
- [📝  JSON Schema Form Element](#json-schema-form-element)
52-
- [Field types](#field-types)
53-
- [Primitives](#primitives)
54-
- [String](#string)
55-
- [Number](#number)
56-
- [Boolean](#boolean)
57-
- [Enumeration](#enumeration)
58-
- [Date](#date)
59-
- [Object](#object)
60-
- [Additional properties](#additional-properties)
61-
- [Arrays](#arrays)
62-
- [Basic](#basic)
63-
- [Fixed](#fixed)
64-
- [Nested](#nested)
65-
- [Multiple choices (enums.)](#multiple-choices-enums)
66-
- [Additional items](#additional-items)
67-
- [Subschemas](#subschemas)
68-
- [allOf](#allof)
69-
- [oneOf](#oneof)
70-
- [anyOf](#anyof)
71-
- [Conditionals](#conditionals)
72-
- [Dependencies](#dependencies)
73-
- [If, then, else](#if-then-else)
74-
- [Miscellaneous](#miscellaneous) - [References](#references) - [Recursivity](#recursivity) - [Nullable values](#nullable-values)
75-
- [User Interface](#user-interface)
76-
- [Schema](#schema)
77-
- [Usage](#usage)
78-
- [Installation](#installation)
79-
- [Implementation](#implementation)
80-
- [TypeScript (no framework)](#typescript-no-framework)
81-
- [Astro (SSR)](#astro-ssr)
82-
- [Lit](#lit)
83-
- [Extended example](#extended-example)
84-
- [Solid](#solid)
85-
- [Vue](#vue)
86-
- [Svelte](#svelte)
87-
- [React](#react)
88-
- [CSS](#css)
89-
- [Component libraries](#component-libraries)
90-
- [Shoelace](#shoelace)
91-
- [Custom widgets](#custom-widgets)
92-
- [Validation](#validation)
93-
- [Schema massaging](#schema-massaging)
94-
- [Custom Elements Manifests](#custom-elements-manifests)
95-
- [Experimental features](#experimental-features)
96-
- [Improvements](#improvements)
97-
- [Acknowledgements](#acknowledgements)
53+
- [Field types](#field-types)
54+
- [Primitives](#primitives)
55+
- [String](#string)
56+
- [Number](#number)
57+
- [Boolean](#boolean)
58+
- [Enumeration](#enumeration)
59+
- [Date](#date)
60+
- [Object](#object)
61+
- [Additional properties](#additional-properties)
62+
- [Arrays](#arrays)
63+
- [Basic](#basic)
64+
- [Fixed](#fixed)
65+
- [Nested](#nested)
66+
- [Multiple choices (enums.)](#multiple-choices-enums)
67+
- [Additional items](#additional-items)
68+
- [Subschemas](#subschemas)
69+
- [allOf](#allof)
70+
- [oneOf](#oneof)
71+
- [anyOf](#anyof)
72+
- [Conditionals](#conditionals)
73+
- [Dependencies](#dependencies)
74+
- [If, then, else](#if-then-else)
75+
- [Miscellaneous](#miscellaneous)
76+
- [References](#references)
77+
- [Recursivity](#recursivity)
78+
- [Nullable values](#nullable-values)
79+
- [User Interface](#user-interface)
80+
- [Schema](#schema)
81+
- [Usage](#usage)
82+
- [Installation](#installation)
83+
- [Implementation](#implementation)
84+
- [All examples](#all-examples)
85+
- [Pure HTML with CDN](#pure-html-with-cdn)
86+
- [TypeScript (no framework)](#typescript-no-framework)
87+
- [Astro (SSR)](#astro-ssr)
88+
- [Lit](#lit)
89+
- [Solid](#solid)
90+
- [Vue](#vue)
91+
- [Svelte](#svelte)
92+
- [React](#react)
93+
- [CSS](#css)
94+
- [TypeScript](#typescript)
95+
- [Support for each implementation](#support-for-each-implementation)
96+
- [Component libraries](#component-libraries)
97+
- [Shoelace](#shoelace)
98+
- [Custom widgets](#custom-widgets)
99+
- [Validation](#validation)
100+
- [Schema massaging](#schema-massaging)
101+
- [Custom Elements Manifests](#custom-elements-manifests)
102+
- [Experimental features](#experimental-features)
103+
- [Improvements](#improvements)
104+
- [Acknowledgements](#acknowledgements)
98105

99106
</details>
100107

@@ -520,7 +527,9 @@ See also the [CSS section](#CSS).
520527
### Implementation
521528

522529
> **Note**
523-
> As the project is fresh, API is subject to changes
530+
> This project is new, API is subject to changes
531+
532+
#### All examples
524533

525534
You can try the [multi-frameworks examples](https://github.com/json-schema-form-element/examples) like this:
526535

@@ -533,107 +542,90 @@ npm i
533542
npm run dev
534543
```
535544

545+
#### Pure HTML with CDN
546+
547+
<!-- TODO: for WebComponents.org -->
548+
<!--
549+
```
550+
<custom-element-demo>
551+
<template>
552+
<link rel="import" href="my-element.html">
553+
<link rel="import" href="../other-element/other-element.html">
554+
<next-code-block></next-code-block>
555+
</template>
556+
</custom-element-demo>
557+
```
558+
-->
559+
<!-- ```html
560+
<other-element></other-element>
561+
<my-element></my-element>
562+
``` -->
563+
564+
See [examples/src/pages/pure-html.html](https://github.com/json-schema-form-element/examples/blob/main/src/pages/pure-html.html)
565+
566+
-OR-
567+
568+
[Open in **CodePen.io**](https://codepen.io/JulianCataldo/pen/KKbBepN?editors=1001)
569+
570+
-OR-
571+
572+
[Open in **StackBlitz.com**](https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fpages%2Fpure-html.html)
573+
536574
#### TypeScript (no framework)
537575

538576
See [examples/src/components/TypeScriptOnly.ts](https://github.com/json-schema-form-element/examples/blob/main/src/components/TypeScriptOnly.ts)
539577

540-
**TypeScript** inference: YES.
578+
-OR-
579+
580+
[Open in **StackBlitz.com**](https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FTypeScriptOnly.ts)
541581

542582
#### Astro (SSR)
543583

544584
See [examples/src/components/AstroJs.astro](https://github.com/json-schema-form-element/examples/blob/main/src/components/AstroJs.astro)
545585

546-
**TypeScript** inference: NO.
586+
-OR-
587+
588+
[Open in **StackBlitz.com**](https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FAstroJs.astro)
547589

548590
#### Lit
549591

550592
See [examples/src/components/LitJs.ts](https://github.com/json-schema-form-element/examples/blob/main/src/components/LitJs.ts)
551593

552-
**TypeScript** inference: YES.
594+
-OR-
553595

554-
> **Note**
555-
> Inside template literals, **methods are type-checked** correctly,
556-
> but **arguments are not inferred** automatically.
596+
[Open in **StackBlitz.com**](https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FLitJs.ts)
557597

558-
##### Extended example
598+
#### Solid
559599

560-
```ts
561-
// src/my-app.ts
562-
import { LitElement, html } from 'lit';
563-
import { customElement, state } from 'lit/decorators.js';
600+
See [examples/src/components/SolidJs.solid.tsx](https://github.com/json-schema-form-element/examples/blob/main/src/components/SolidJs.solid.tsx)
564601

565-
import type { JSONSchema7 } from 'json-schema';
566-
import { petSchema, type Pet } from '@my-models/Pet.js';
602+
-OR-
567603

568-
import 'json-schema-form-element';
569-
import type { UiSchema } from 'json-schema-form-element';
604+
[Open in **StackBlitz.com**](https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FSolidJs.solid.tsx)
570605

571-
// Shoelace namespaced custom properties (see notes on CSS below)
572-
import '@shoelace-style/shoelace/dist/themes/light.css';
573-
import '@shoelace-style/shoelace/dist/themes/dark.css';
606+
#### Vue
574607

575-
@customElement('my-app')
576-
class MyApp extends LitElement {
577-
@state() private schema: JSONSchema7 = { ...petSchema };
578-
579-
@state() private data: Pet = {};
580-
581-
@state() private uiSchema: UiSchema = {
582-
/* ... */
583-
};
584-
585-
#form = () =>
586-
html`<json-schema-form
587-
.schema=${this.schema}
588-
.uiSchema=${this.uiSchema}
589-
.data=${this.data}
590-
.onDataChange=${(newData: Pet) => {
591-
this.data = data;
592-
}}
593-
.onFormSubmit=${(newData: Pet, valid: boolean) => {
594-
console.info(data, errors);
595-
}}
596-
></json-schema-form>`;
597-
598-
render() {
599-
const debug = {
600-
Schema: this.currentSchema,
601-
'UI schema': this.currentUiSchema,
602-
Data: this.currentData,
603-
};
604-
605-
return html`
606-
<h1>My App</h1>
607-
608-
<main>${this.#form()}</main>
609-
610-
<footer>
611-
<pre>${JSON.stringify(debug, null, 2)}</pre>
612-
</footer>
613-
`;
614-
}
615-
}
616-
```
608+
See [examples/src/components/VueJs.vue](https://github.com/json-schema-form-element/examples/blob/main/src/components/VueJs.vue)
617609

618-
#### Solid
610+
-OR-
619611

620-
See [examples/src/components/SolidJs.tsx](https://github.com/json-schema-form-element/examples/blob/main/src/components/SolidJs.tsx)
612+
[Open in **StackBlitz.com**](https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FVueJs.vue)
621613

622-
**TypeScript** inference: YES.
614+
#### Svelte
623615

624-
#### Vue
616+
See [examples/src/components/SvelteJs.svelte](https://github.com/json-schema-form-element/examples/blob/main/src/components/SvelteJs.svelte)
625617

626-
See [examples/src/components/VueJs.vue](https://github.com/json-schema-form-element/examples/blob/main/src/components/VueJs.vue)
618+
-OR-
627619

628-
**TypeScript** inference: NO.
620+
[Open in **StackBlitz.com**](https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FSvelteJs.svelte)
629621

630-
#### Svelte
622+
#### React
631623

632-
🚧……🚧
624+
See [examples/src/components/ReactJs18.react.tsx](https://github.com/json-schema-form-element/examples/blob/main/src/components/ReactJs18.react.tsx)
633625

634-
#### React
626+
-OR-
635627

636-
🚧……🚧
628+
[Open in **StackBlitz.com**](https://stackblitz.com/github/json-schema-form-element/examples?file=src%2Fcomponents%2FReactJs18.react.tsx)
637629

638630
#### CSS
639631

@@ -651,6 +643,36 @@ are injected globally.
651643

652644
<!-- TODO -->
653645

646+
### TypeScript
647+
648+
#### Support for each implementation
649+
650+
| API | No framework | Astro (SSR) | Lit | Solid | Vue | React / Preact | Svelte |
651+
| ------------------------- | ----------------- | ----------------- | ----------------- | -------------- | ------------ | -------------- | ----------------- |
652+
| Declarative control |||| ✅ via `prop:` ||| ❌ <sup>(4)</sup> |
653+
| Declarative inference | ❌ <sup>(1)</sup> | ❌ <sup>(2)</sup> | ❌ <sup>(3)</sup> | ✅ via `prop:` ||||
654+
| Declarative type-checking | ❌ <sup>(1)</sup> | ❌ <sup>(2)</sup> || ✅ via `prop:` ||||
655+
| Imperative control | ✅ via DOM | - | ✅ via `ref` | ✅ via `ref` | ✅ via `ref` | ✅ via `ref` | ✅ via `use:` |
656+
| Imperative inference | ✅ via DOM | - | ✅ via `ref` | ✅ via `ref` | ✅ via `ref` | ✅ via `ref` | ✅ via `use:` |
657+
| Imperative type-checking | ✅ via DOM | - | ✅ via `ref` | ✅ via `ref` | ✅ via `ref` | ✅ via `ref` | ✅ via `use:` |
658+
659+
1. HTML language servers can't support TypeScript obviously. But IDE can leverage Custom Element metadata.
660+
2. Astro JSX namespace / LSP are not handling `HTMLElementTagNameMap` or Custom Element metadata, yet.
661+
3. Template literals are preventing automatic properties inference, but at least, you can't assign wrong argument types without knowing it.
662+
4. Svelte heuristics are not clear regarding _attributes_ versus _properties_ handling. Better be safe than sorry. Also the `use:` directive is neat.
663+
664+
There might be changes regarding support for Web Components accross various the various UI frameworks above.
665+
Please file an issue if an info is wrong or missing.
666+
667+
Each implementation examples are trying to show off the most type-safe way to use JSFE, with the least trade-offs.
668+
669+
Using it more **declaratively** or **imperatively** is up to you, your framework ability and you coding style.
670+
Bot usages are valid and can be mixed. Typically when you want to use the schema elsewhere in your app., or
671+
when your callbacks are getting too beefy, you'll better extract them from templates.
672+
673+
Generally, imperative usage get perfect TypeScript support (you just handle the class), whereas declaratively, you'll have
674+
to deal with various template languages limitations (this is an universal problem).
675+
654676
## Component libraries
655677

656678
### Shoelace

custom-elements-manifest.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { generateCustomData } from 'cem-plugin-vs-code-custom-data-generator';
2+
3+
export default {
4+
plugins: [generateCustomData()],
5+
};

0 commit comments

Comments
 (0)