Skip to content

Commit 463aa85

Browse files
committed
feat: select multiple, typings fixes, refactor
1 parent 41ce40e commit 463aa85

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+639
-215
lines changed

README.md

+18-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +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/@jsfe/jsfe)
4-
[![ISC License](https://img.shields.io/npm/l/@jsfe/jsfe)](./LICENSE)
3+
[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/@jsfe/form)
4+
[![ISC License](https://img.shields.io/npm/l/@jsfe/form)](./LICENSE)
55
[![GitHub](https://img.shields.io/badge/Repository-222222?logo=github)](https://github.com/json-schema-form-element/jsfe)
66
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)](https://makeapullrequest.com)
77
[![TypeScript](https://img.shields.io/badge/TypeScript-333333?logo=typescript)](http://www.typescriptlang.org/)
@@ -11,27 +11,35 @@
1111
[![ESLint](https://img.shields.io/badge/ESLint-3A33D1?logo=eslint)](https://eslint.org)
1212
[![Stylelint](https://img.shields.io/badge/Stylelint-222222?logo=Stylelint)](https://stylelint.io)
1313

14-
<!-- ![Downloads](https://img.shields.io/npm/dt/@jsfe/jsfe) -->
14+
<!-- ![Downloads](https://img.shields.io/npm/dt/@jsfe/form) -->
1515

1616
Effortless forms, with standards.
1717

1818
**Features**:
1919

20-
- Instant **form generation** based on your JSON schemas
21-
- **Light**, and **interoperable**, by design
22-
- Integrate seamlessly with your **OpenAPI** / **JSON schema** stack
23-
- Comes with **sensible defaults**, but aims for **extensibility**
20+
- Instant **form generation** based on your JSON schemas.
21+
- Integrates within your **OpenAPI** / **JSON schema** / MongoDB (BSON) stack.
22+
- Comes with **sensible defaults**, while aiming for **extensibility** (themes, widgets…).
23+
- ⚡️ Fast, and light 🪶.
2424

2525
**Use cases**:
2626

2727
- Quick CRUDs for you backends (JS, Python, PHP, Ruby…).
2828
- Lightly interactive websites contact forms.
2929
- Building block for custom CMSes.
3030
- Building block for Markdown YAML frontmatter editors.
31+
- Form builders… builder (🪆)
32+
- _You name it_
33+
34+
Due to their **declarative** and **serializable** nature, JSON schemas are highly **interoperable** and **portable**.
35+
Moreover, **UI schemas** can be declared alongside to customize the view layer.
36+
You can also **override totally** one ore more widgets, or just **sprinkle some styles** on top of the included ones.
3137

3238
**Why?**
3339

3440
While there is a handful of project for major frontend frameworks, there wasn't any **Web Component** packing all the features above.
41+
Also if your are evaluating **Web Component design systems** or if you are building your own, this library is providing you a handy testbed.
42+
3543
See also the [inspirations](#acknowledgements) for this project.
3644

3745
<!-- **Theming**
@@ -917,13 +925,13 @@ See [./custom-elements.json](./custom-elements.json) & [./custom-elements.md](./
917925

918926
## Packages informations
919927

920-
With all external JS dependencies included, minus some CSS:
928+
With internal dependencies included, minus peer dependencies (UI libs.):
921929

922930
<div align="center">
923931

924932
| Package | Size | Version |
925933
| -------------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
926-
| @jsfe/form | ![form bundle size](https://deno.bundlejs.com/badge?q=@jsfe/core&treeshake=[*]) | [![NPM](https://img.shields.io/npm/v/@jsfe/form)](https://www.npmjs.com/package/@jsfe/form) |
934+
| @jsfe/form | ![form bundle size](https://deno.bundlejs.com/badge?q=@jsfe/form&treeshake=[*]) | [![NPM](https://img.shields.io/npm/v/@jsfe/form)](https://www.npmjs.com/package/@jsfe/form) |
927935
| @jsfe/shoelace | ![shoelace bundle size](https://deno.bundlejs.com/badge?q=@jsfe/shoelace&treeshake=[*]) | [![NPM](https://img.shields.io/npm/v/@jsfe/shoelace)](https://www.npmjs.com/package/@jsfe/shoelace) |
928936
| @jsfe/material | ![material bundle size](https://deno.bundlejs.com/badge?q=@jsfe/material&treeshake=[*]) | [![NPM](https://img.shields.io/npm/v/@jsfe/material)](https://www.npmjs.com/package/@jsfe/material) |
929937
| @jsfe/carbon | ![carbon bundle size](https://deno.bundlejs.com/badge?q=@jsfe/carbon&treeshake=[*]) | [![NPM](https://img.shields.io/npm/v/@jsfe/carbon)](https://www.npmjs.com/package/@jsfe/carbon) |
@@ -973,8 +981,7 @@ Actual **features flags** list:
973981
- Layout customizations
974982
- Tests, browser based (due to the WC nature).
975983
- Tests, tests, even more tests in the field to reveal shortcomings.
976-
- Support for other UI library (MWC? FAST? Bootstrap?)
977-
- Drag and drop for array items, using native API.
984+
- Drag and drop: improve the initial implementation (E.g. cross-nested arrays).
978985
- Autofocuses (for added array item, etc.)
979986
-
980987
- Have an idea? [Discussions are open](https://github.com/json-schema-form-element/form/discussions)!

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"// test": "cd tests && pnpm test",
2323
"// publish:dry": "pnpm lerna publish --dry-run",
2424
"util:scaffold": "plop --plopfile scripts/scaffold/plopfile.js",
25-
"util:sort": "keep-sorted packages/*/src/index.ts packages/*/src/styles.scss && sort-package-json packages/*/package.json"
25+
"util:sort": "keep-sorted packages/*/src/widgets/index.ts packages/*/src/styles.scss && sort-package-json packages/*/package.json"
2626
},
2727
"devDependencies": {
2828
"@custom-elements-manifest/analyzer": "^0.8.4",

packages/carbon/README.md

+12-11
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ See the [documentation](../../README.md).
1818

1919
### Superclass
2020

21-
| Name | Module | Package |
22-
| ----- | ------ | ------------------ |
23-
| `Jsf` | | @j\_c/jsfe\_\_form |
21+
| Name | Module | Package |
22+
| ----- | ------ | ---------- |
23+
| `Jsf` | | @jsfe/form |
2424

2525
### Fields
2626

@@ -41,19 +41,20 @@ See the [documentation](../../README.md).
4141

4242
## Exports
4343

44-
| Kind | Name | Declaration | Module | Package |
45-
| ---- | ----------- | ----------- | --------- | ------------------- |
46-
| `js` | `JsfCarbon` | JsfCarbon | ./form.js | |
47-
| `js` | `*` | \* | | ./widgets/index.js |
48-
| `js` | `*` | \* | | @j\_c/jsfe\_\_types |
44+
| Kind | Name | Declaration | Module | Package |
45+
| ---- | ----------- | ----------- | --------- | ------------------ |
46+
| `js` | `JsfCarbon` | JsfCarbon | ./form.js | |
47+
| `js` | `*` | \* | | ./widgets/index.js |
48+
| `js` | `*` | \* | | @jsfe/types |
49+
| `js` | `Jsf` | Jsf | | @jsfe/form |
4950

5051
# `packages/carbon/src/styles.ts`:
5152

5253
## Variables
5354

54-
| Name | Description | Type |
55-
| -------- | ----------- | -------- |
56-
| `styles` | | `string` |
55+
| Name | Description | Type |
56+
| -------- | ----------- | ---- |
57+
| `styles` | | |
5758

5859
<hr/>
5960

packages/carbon/custom-elements.json

+9-4
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@
8989
"name": "*",
9090
"package": "@jsfe/types"
9191
}
92+
},
93+
{
94+
"kind": "js",
95+
"name": "Jsf",
96+
"declaration": {
97+
"name": "Jsf",
98+
"package": "@jsfe/form"
99+
}
92100
}
93101
]
94102
},
@@ -99,10 +107,7 @@
99107
{
100108
"kind": "variable",
101109
"name": "styles",
102-
"type": {
103-
"text": "string"
104-
},
105-
"default": "''"
110+
"default": "css`\n\t/* STUB - Compiled SCSS goes here */\n`"
106111
}
107112
],
108113
"exports": [

packages/form/README.md

+19-18
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ See the [documentation](../../README.md).
88

99
## Exports
1010

11-
| Kind | Name | Declaration | Module | Package |
12-
| ---- | ----- | ----------- | --------------------- | ------------------- |
13-
| `js` | `Jsf` | Jsf | ./json-schema-form.js | |
14-
| `js` | `*` | \* | | @j\_c/jsfe\_\_types |
11+
| Kind | Name | Declaration | Module | Package |
12+
| ---- | ----- | ----------- | --------------------- | ----------- |
13+
| `js` | `Jsf` | Jsf | ./json-schema-form.js | |
14+
| `js` | `*` | \* | | @jsfe/types |
15+
| `js` | `Jsf` | Jsf | | @jsfe/form |
1516

1617
# `packages/form/src/json-schema-form.def.ts`:
1718

@@ -33,20 +34,20 @@ See the [documentation](../../README.md).
3334

3435
### Fields
3536

36-
| Name | Privacy | Type | Default | Description | Inherited From |
37-
| ---------------- | --------- | --------------------------- | ------- | ----------- | -------------- |
38-
| `schema` | public | `JSONSchema7` | `{}` | | |
39-
| `data` | public | `unknown` | `{}` | | |
40-
| `uiSchema` | public | `UiSchema` | `{}` | | |
41-
| `submitCallback` | public | `OnFormSubmit` | | | |
42-
| `onDataChange` | public | `OnDataChange` | | | |
43-
| `widgets` | public | `Widgets` | `{}` | | |
44-
| `styleSheets` | public | `string[]` | `[]` | | |
45-
| `experimental` | public | `FeatureFlags \| undefined` | `{}` | | |
46-
| `_uiState` | private | `unknown` | `{}` | | |
47-
| `_dig` | protected | | | | |
48-
| `#submit` | private | | | | |
49-
| `#formRef` | private | | | | |
37+
| Name | Privacy | Type | Default | Description | Inherited From |
38+
| -------------------- | --------- | --------------------------- | ------- | ----------- | -------------- |
39+
| `schema` | public | `JSONSchema7` | `{}` | | |
40+
| `data` | public | `unknown` | `{}` | | |
41+
| `uiSchema` | public | `UiSchema` | `{}` | | |
42+
| `submitCallback` | public | `OnFormSubmit` | | | |
43+
| `dataChangeCallback` | public | `DataChangeCallback` | | | |
44+
| `widgets` | public | `Widgets` | `{}` | | |
45+
| `styleSheets` | public | `CSSResult[]` | `[]` | | |
46+
| `experimental` | public | `FeatureFlags \| undefined` | `{}` | | |
47+
| `_uiState` | private | `unknown` | `{}` | | |
48+
| `_dig` | protected | | | | |
49+
| `#submit` | private | | | | |
50+
| `#formRef` | private | | | | |
5051

5152
### Methods
5253

packages/form/custom-elements.json

+12-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@
2222
"name": "*",
2323
"package": "@jsfe/types"
2424
}
25+
},
26+
{
27+
"kind": "js",
28+
"name": "Jsf",
29+
"declaration": {
30+
"name": "Jsf",
31+
"package": "@jsfe/form"
32+
}
2533
}
2634
]
2735
},
@@ -89,9 +97,9 @@
8997
},
9098
{
9199
"kind": "field",
92-
"name": "onDataChange",
100+
"name": "dataChangeCallback",
93101
"type": {
94-
"text": "OnDataChange"
102+
"text": "DataChangeCallback"
95103
},
96104
"privacy": "public"
97105
},
@@ -109,7 +117,7 @@
109117
"kind": "field",
110118
"name": "styleSheets",
111119
"type": {
112-
"text": "string[]"
120+
"text": "CSSResult[]"
113121
},
114122
"privacy": "public",
115123
"default": "[]",
@@ -268,7 +276,7 @@
268276
{
269277
"name": "styleSheets",
270278
"type": {
271-
"text": "string[]"
279+
"text": "CSSResult[]"
272280
},
273281
"default": "[]",
274282
"fieldName": "styleSheets"

packages/form/src/json-schema-form.ts

+45-14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { fieldArrayPrimitive } from './triage/array-primitive';
12
/* eslint-disable max-lines */
23
/* eslint-disable class-methods-use-this */
34
/* eslint-disable no-underscore-dangle */
@@ -19,12 +20,12 @@ import set from 'lodash-es/set';
1920
import type { JSONSchema7 } from '@jsfe/types';
2021

2122
// import { alternateField } from './triage/alternate.js';
22-
import { arrayField } from './triage/array.js';
23-
import { objectField } from './triage/object.js';
24-
import { field } from './triage/field.js';
23+
import { fieldArray } from './triage/array.js';
24+
import { fieldObject } from './triage/object.js';
25+
import { fieldPrimitive } from './triage/primitive.js';
2526

2627
import type {
27-
OnDataChange,
28+
DataChangeCallback,
2829
FeatureFlags,
2930
OnFormSubmit,
3031
Path,
@@ -41,7 +42,7 @@ export class Jsf extends LitElement {
4142

4243
public submitCallback: OnFormSubmit = () => {};
4344

44-
public onDataChange: OnDataChange = () => {};
45+
public dataChangeCallback: DataChangeCallback = () => {};
4546

4647
@property({ type: Object }) public widgets: Widgets = {};
4748

@@ -103,7 +104,7 @@ export class Jsf extends LitElement {
103104
// if (typeof propName !== 'undefined') schemaPathAugmented.push(propName);
104105
// schemaPathAugmented.push('properties');
105106

106-
result = field(
107+
result = fieldPrimitive(
107108
currentNode,
108109
dataLevel,
109110
path,
@@ -141,7 +142,7 @@ export class Jsf extends LitElement {
141142
schemaPathAugmented.push('properties');
142143
// schemaPathAugmented.push(path);
143144

144-
result = objectField(
145+
result = fieldObject(
145146
nodeParsed,
146147
dataLevel,
147148
path,
@@ -153,6 +154,33 @@ export class Jsf extends LitElement {
153154
);
154155
}
155156

157+
/* --- Arrays of primitives --- */
158+
if (
159+
currentNode.type === 'array' &&
160+
typeof currentNode.items === 'object' &&
161+
!Array.isArray(currentNode.items) &&
162+
currentNode.items.enum &&
163+
currentNode.uniqueItems &&
164+
(currentNode.items.type === 'string' ||
165+
currentNode.items.type === 'number' ||
166+
currentNode.items.type === 'integer' ||
167+
currentNode.items.type === 'boolean')
168+
) {
169+
const schemaPathAugmented = [...schemaPath];
170+
result = fieldArrayPrimitive(
171+
currentNode,
172+
dataLevel,
173+
path,
174+
uiState,
175+
uiSchema,
176+
required,
177+
this._handleChange.bind(this),
178+
// this._handleKeydown.bind(this),
179+
schemaPathAugmented,
180+
this.widgets,
181+
);
182+
}
183+
156184
/* --- Arrays --- */
157185
if (typeof currentNode.items === 'object') {
158186
/* --- Fixed Array --- */
@@ -169,14 +197,15 @@ export class Jsf extends LitElement {
169197
// if (typeof propName !== 'undefined') schemaPathAugmented.push(propName);
170198
// schemaPathAugmented.push('items');
171199

172-
result = objectField(
200+
result = fieldObject(
173201
newNode,
174202
dataLevel,
175203
path,
176204
uiState,
177205
uiSchema,
178206
this._dig.bind(this),
179207
schemaPathAugmented,
208+
this.widgets,
180209
);
181210

182211
/* --- Additionals Array items --- */
@@ -227,7 +256,7 @@ export class Jsf extends LitElement {
227256
// if (typeof propName !== 'undefined') schemaPathAugmented.push(propName);
228257
// schemaPathAugmented.push('items');
229258
dataLevel ||= [];
230-
result = arrayField(
259+
result = fieldArray(
231260
node,
232261
dataLevel,
233262
path,
@@ -259,17 +288,19 @@ export class Jsf extends LitElement {
259288
if (Object.entries(node).length === 0) {
260289
const error = `Empty schema`;
261290
return (
262-
this.widgets?.callout?.({ id: '', message: error }) ?? html`${error}`
291+
this.widgets?.callout?.({ id: '', message: error }) ??
292+
html`<p>${error}</p>`
263293
);
264294
}
265295

266296
if (result) return result;
267297

268-
const error = `Cannot dig this level:${path.join('/')}${String(
298+
const error = `Cannot dig this level: ${path.join('/')} - (${String(
269299
currentNode.type,
270-
)}`;
300+
)})`;
271301
return (
272-
this.widgets?.callout?.({ id: '', message: error }) ?? html`${error}`
302+
this.widgets?.callout?.({ id: '', message: error }) ??
303+
html`<p>${error}</p>`
273304
);
274305
};
275306

@@ -301,7 +332,7 @@ export class Jsf extends LitElement {
301332
// NOTE: May be debounced / throttled
302333
this.data = newData;
303334

304-
this.onDataChange(newData, path, value, schemaPath);
335+
this.dataChangeCallback(newData, path, value, schemaPath);
305336

306337
// TODO:
307338
// this.dispatchEvent(new CustomEvent('jsf-data', { detail: newData }));

0 commit comments

Comments
 (0)