Skip to content

Commit

Permalink
feat: select multiple, typings fixes, refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
JulianCataldo committed Oct 11, 2023
1 parent 41ce40e commit 463aa85
Show file tree
Hide file tree
Showing 51 changed files with 639 additions and 215 deletions.
29 changes: 18 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# 📝  JSON Schema Form Element

[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/@jsfe/jsfe)
[![ISC License](https://img.shields.io/npm/l/@jsfe/jsfe)](./LICENSE)
[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/@jsfe/form)
[![ISC License](https://img.shields.io/npm/l/@jsfe/form)](./LICENSE)
[![GitHub](https://img.shields.io/badge/Repository-222222?logo=github)](https://github.com/json-schema-form-element/jsfe)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)](https://makeapullrequest.com)
[![TypeScript](https://img.shields.io/badge/TypeScript-333333?logo=typescript)](http://www.typescriptlang.org/)
Expand All @@ -11,27 +11,35 @@
[![ESLint](https://img.shields.io/badge/ESLint-3A33D1?logo=eslint)](https://eslint.org)
[![Stylelint](https://img.shields.io/badge/Stylelint-222222?logo=Stylelint)](https://stylelint.io)

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

Effortless forms, with standards.

**Features**:

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

**Use cases**:

- Quick CRUDs for you backends (JS, Python, PHP, Ruby…).
- Lightly interactive websites contact forms.
- Building block for custom CMSes.
- Building block for Markdown YAML frontmatter editors.
- Form builders… builder (🪆)
- _You name it_

Due to their **declarative** and **serializable** nature, JSON schemas are highly **interoperable** and **portable**.
Moreover, **UI schemas** can be declared alongside to customize the view layer.
You can also **override totally** one ore more widgets, or just **sprinkle some styles** on top of the included ones.

**Why?**

While there is a handful of project for major frontend frameworks, there wasn't any **Web Component** packing all the features above.
Also if your are evaluating **Web Component design systems** or if you are building your own, this library is providing you a handy testbed.

See also the [inspirations](#acknowledgements) for this project.

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

## Packages informations

With all external JS dependencies included, minus some CSS:
With internal dependencies included, minus peer dependencies (UI libs.):

<div align="center">

| Package | Size | Version |
| -------------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| @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) |
| @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) |
| @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) |
| @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) |
| @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) |
Expand Down Expand Up @@ -973,8 +981,7 @@ Actual **features flags** list:
- Layout customizations
- Tests, browser based (due to the WC nature).
- Tests, tests, even more tests in the field to reveal shortcomings.
- Support for other UI library (MWC? FAST? Bootstrap?)
- Drag and drop for array items, using native API.
- Drag and drop: improve the initial implementation (E.g. cross-nested arrays).
- Autofocuses (for added array item, etc.)
-
- Have an idea? [Discussions are open](https://github.com/json-schema-form-element/form/discussions)!
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"// test": "cd tests && pnpm test",
"// publish:dry": "pnpm lerna publish --dry-run",
"util:scaffold": "plop --plopfile scripts/scaffold/plopfile.js",
"util:sort": "keep-sorted packages/*/src/index.ts packages/*/src/styles.scss && sort-package-json packages/*/package.json"
"util:sort": "keep-sorted packages/*/src/widgets/index.ts packages/*/src/styles.scss && sort-package-json packages/*/package.json"
},
"devDependencies": {
"@custom-elements-manifest/analyzer": "^0.8.4",
Expand Down
23 changes: 12 additions & 11 deletions packages/carbon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ See the [documentation](../../README.md).

### Superclass

| Name | Module | Package |
| ----- | ------ | ------------------ |
| `Jsf` | | @j\_c/jsfe\_\_form |
| Name | Module | Package |
| ----- | ------ | ---------- |
| `Jsf` | | @jsfe/form |

### Fields

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

## Exports

| Kind | Name | Declaration | Module | Package |
| ---- | ----------- | ----------- | --------- | ------------------- |
| `js` | `JsfCarbon` | JsfCarbon | ./form.js | |
| `js` | `*` | \* | | ./widgets/index.js |
| `js` | `*` | \* | | @j\_c/jsfe\_\_types |
| Kind | Name | Declaration | Module | Package |
| ---- | ----------- | ----------- | --------- | ------------------ |
| `js` | `JsfCarbon` | JsfCarbon | ./form.js | |
| `js` | `*` | \* | | ./widgets/index.js |
| `js` | `*` | \* | | @jsfe/types |
| `js` | `Jsf` | Jsf | | @jsfe/form |

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

## Variables

| Name | Description | Type |
| -------- | ----------- | -------- |
| `styles` | | `string` |
| Name | Description | Type |
| -------- | ----------- | ---- |
| `styles` | | |

<hr/>

Expand Down
13 changes: 9 additions & 4 deletions packages/carbon/custom-elements.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@
"name": "*",
"package": "@jsfe/types"
}
},
{
"kind": "js",
"name": "Jsf",
"declaration": {
"name": "Jsf",
"package": "@jsfe/form"
}
}
]
},
Expand All @@ -99,10 +107,7 @@
{
"kind": "variable",
"name": "styles",
"type": {
"text": "string"
},
"default": "''"
"default": "css`\n\t/* STUB - Compiled SCSS goes here */\n`"
}
],
"exports": [
Expand Down
37 changes: 19 additions & 18 deletions packages/form/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ See the [documentation](../../README.md).

## Exports

| Kind | Name | Declaration | Module | Package |
| ---- | ----- | ----------- | --------------------- | ------------------- |
| `js` | `Jsf` | Jsf | ./json-schema-form.js | |
| `js` | `*` | \* | | @j\_c/jsfe\_\_types |
| Kind | Name | Declaration | Module | Package |
| ---- | ----- | ----------- | --------------------- | ----------- |
| `js` | `Jsf` | Jsf | ./json-schema-form.js | |
| `js` | `*` | \* | | @jsfe/types |
| `js` | `Jsf` | Jsf | | @jsfe/form |

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

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

### Fields

| Name | Privacy | Type | Default | Description | Inherited From |
| ---------------- | --------- | --------------------------- | ------- | ----------- | -------------- |
| `schema` | public | `JSONSchema7` | `{}` | | |
| `data` | public | `unknown` | `{}` | | |
| `uiSchema` | public | `UiSchema` | `{}` | | |
| `submitCallback` | public | `OnFormSubmit` | | | |
| `onDataChange` | public | `OnDataChange` | | | |
| `widgets` | public | `Widgets` | `{}` | | |
| `styleSheets` | public | `string[]` | `[]` | | |
| `experimental` | public | `FeatureFlags \| undefined` | `{}` | | |
| `_uiState` | private | `unknown` | `{}` | | |
| `_dig` | protected | | | | |
| `#submit` | private | | | | |
| `#formRef` | private | | | | |
| Name | Privacy | Type | Default | Description | Inherited From |
| -------------------- | --------- | --------------------------- | ------- | ----------- | -------------- |
| `schema` | public | `JSONSchema7` | `{}` | | |
| `data` | public | `unknown` | `{}` | | |
| `uiSchema` | public | `UiSchema` | `{}` | | |
| `submitCallback` | public | `OnFormSubmit` | | | |
| `dataChangeCallback` | public | `DataChangeCallback` | | | |
| `widgets` | public | `Widgets` | `{}` | | |
| `styleSheets` | public | `CSSResult[]` | `[]` | | |
| `experimental` | public | `FeatureFlags \| undefined` | `{}` | | |
| `_uiState` | private | `unknown` | `{}` | | |
| `_dig` | protected | | | | |
| `#submit` | private | | | | |
| `#formRef` | private | | | | |

### Methods

Expand Down
16 changes: 12 additions & 4 deletions packages/form/custom-elements.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@
"name": "*",
"package": "@jsfe/types"
}
},
{
"kind": "js",
"name": "Jsf",
"declaration": {
"name": "Jsf",
"package": "@jsfe/form"
}
}
]
},
Expand Down Expand Up @@ -89,9 +97,9 @@
},
{
"kind": "field",
"name": "onDataChange",
"name": "dataChangeCallback",
"type": {
"text": "OnDataChange"
"text": "DataChangeCallback"
},
"privacy": "public"
},
Expand All @@ -109,7 +117,7 @@
"kind": "field",
"name": "styleSheets",
"type": {
"text": "string[]"
"text": "CSSResult[]"
},
"privacy": "public",
"default": "[]",
Expand Down Expand Up @@ -268,7 +276,7 @@
{
"name": "styleSheets",
"type": {
"text": "string[]"
"text": "CSSResult[]"
},
"default": "[]",
"fieldName": "styleSheets"
Expand Down
59 changes: 45 additions & 14 deletions packages/form/src/json-schema-form.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { fieldArrayPrimitive } from './triage/array-primitive';
/* eslint-disable max-lines */
/* eslint-disable class-methods-use-this */
/* eslint-disable no-underscore-dangle */
Expand All @@ -19,12 +20,12 @@ import set from 'lodash-es/set';
import type { JSONSchema7 } from '@jsfe/types';

// import { alternateField } from './triage/alternate.js';
import { arrayField } from './triage/array.js';
import { objectField } from './triage/object.js';
import { field } from './triage/field.js';
import { fieldArray } from './triage/array.js';
import { fieldObject } from './triage/object.js';
import { fieldPrimitive } from './triage/primitive.js';

import type {
OnDataChange,
DataChangeCallback,
FeatureFlags,
OnFormSubmit,
Path,
Expand All @@ -41,7 +42,7 @@ export class Jsf extends LitElement {

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

public onDataChange: OnDataChange = () => {};
public dataChangeCallback: DataChangeCallback = () => {};

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

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

result = field(
result = fieldPrimitive(
currentNode,
dataLevel,
path,
Expand Down Expand Up @@ -141,7 +142,7 @@ export class Jsf extends LitElement {
schemaPathAugmented.push('properties');
// schemaPathAugmented.push(path);

result = objectField(
result = fieldObject(
nodeParsed,
dataLevel,
path,
Expand All @@ -153,6 +154,33 @@ export class Jsf extends LitElement {
);
}

/* --- Arrays of primitives --- */
if (
currentNode.type === 'array' &&
typeof currentNode.items === 'object' &&
!Array.isArray(currentNode.items) &&
currentNode.items.enum &&
currentNode.uniqueItems &&
(currentNode.items.type === 'string' ||
currentNode.items.type === 'number' ||
currentNode.items.type === 'integer' ||
currentNode.items.type === 'boolean')
) {
const schemaPathAugmented = [...schemaPath];
result = fieldArrayPrimitive(
currentNode,
dataLevel,
path,
uiState,
uiSchema,
required,
this._handleChange.bind(this),
// this._handleKeydown.bind(this),
schemaPathAugmented,
this.widgets,
);
}

/* --- Arrays --- */
if (typeof currentNode.items === 'object') {
/* --- Fixed Array --- */
Expand All @@ -169,14 +197,15 @@ export class Jsf extends LitElement {
// if (typeof propName !== 'undefined') schemaPathAugmented.push(propName);
// schemaPathAugmented.push('items');

result = objectField(
result = fieldObject(
newNode,
dataLevel,
path,
uiState,
uiSchema,
this._dig.bind(this),
schemaPathAugmented,
this.widgets,
);

/* --- Additionals Array items --- */
Expand Down Expand Up @@ -227,7 +256,7 @@ export class Jsf extends LitElement {
// if (typeof propName !== 'undefined') schemaPathAugmented.push(propName);
// schemaPathAugmented.push('items');
dataLevel ||= [];
result = arrayField(
result = fieldArray(
node,
dataLevel,
path,
Expand Down Expand Up @@ -259,17 +288,19 @@ export class Jsf extends LitElement {
if (Object.entries(node).length === 0) {
const error = `Empty schema`;
return (
this.widgets?.callout?.({ id: '', message: error }) ?? html`${error}`
this.widgets?.callout?.({ id: '', message: error }) ??
html`<p>${error}</p>`
);
}

if (result) return result;

const error = `Cannot dig this level:${path.join('/')}${String(
const error = `Cannot dig this level: ${path.join('/')} - (${String(
currentNode.type,
)}`;
)})`;
return (
this.widgets?.callout?.({ id: '', message: error }) ?? html`${error}`
this.widgets?.callout?.({ id: '', message: error }) ??
html`<p>${error}</p>`
);
};

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

this.onDataChange(newData, path, value, schemaPath);
this.dataChangeCallback(newData, path, value, schemaPath);

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

0 comments on commit 463aa85

Please sign in to comment.