Merge pull request #749 from ing-bank/chore/storybook-cleanup
Chore/storybook cleanup
This commit is contained in:
commit
eb02b27010
8 changed files with 6 additions and 276 deletions
|
|
@ -5,6 +5,7 @@ module.exports = {
|
||||||
stories: [
|
stories: [
|
||||||
'../packages/*/README.md',
|
'../packages/*/README.md',
|
||||||
'../packages/*/docs/*.md',
|
'../packages/*/docs/*.md',
|
||||||
|
'../packages/*/docs/!(assets)**/*.md',
|
||||||
'../docs/README.md',
|
'../docs/README.md',
|
||||||
'../docs/**/*.md',
|
'../docs/**/*.md',
|
||||||
'../README.md',
|
'../README.md',
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,5 @@ Fieldsets are the basis for:
|
||||||
|
|
||||||
## Other Resources
|
## Other Resources
|
||||||
|
|
||||||
- [Form fundamentals](?path=/docs/forms-field-fundaments--page)
|
|
||||||
- [Formatting and parsing](?path=/docs/forms-field-formatting-and-parsing--page)
|
- [Formatting and parsing](?path=/docs/forms-field-formatting-and-parsing--page)
|
||||||
- [Custom Fields](?path=/docs/forms-field-custom-fields-tutorial--page)
|
- [Custom Fields](?path=/docs/forms-field-custom-fields-tutorial--page)
|
||||||
|
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
|
|
||||||
|
|
||||||
# Creating a custom field
|
|
||||||
|
|
||||||
```js script
|
|
||||||
export default {
|
|
||||||
title: 'Forms/Field/Custom fields tutorial',
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Custom fields can be created in just a few steps. All you need is an interaction element
|
|
||||||
(like for instance a slider, a listbox or a combobox) and connect it to the [Field](../README.md)
|
|
||||||
functionality.
|
|
||||||
|
|
||||||
## Prerequisite: an interaction element
|
|
||||||
|
|
||||||
An interaction element provides the means for the end user to enter a certain value, just like
|
|
||||||
native elements provide in this (think of `<input>`, `<textarea>` and `<select>`).
|
|
||||||
An example of a non native element is the [slider design pattern](https://www.w3.org/TR/2017/NOTE-wai-aria-practices-1.1-20171214/#slider) described here.
|
|
||||||
|
|
||||||
For this tutorial, we assume we have a component `<my-slider>` that exposes its value via property
|
|
||||||
`mySliderValue` and sends an event `my-slider-changed` on every value change. To make it focusable,
|
|
||||||
it has a tabindex=“0” applied.
|
|
||||||
|
|
||||||
## Connecting the interaction element to the field
|
|
||||||
|
|
||||||
Now we want to integrate the slider in our form framework to enrich the user interface, get
|
|
||||||
validation support and get all the other [benefits of LionField](?path=/docs/forms-field-overview--page).
|
|
||||||
We start of by creating a component `<lion-slider>` that extends from `LionField`.
|
|
||||||
Then we follow the steps below:
|
|
||||||
|
|
||||||
- ### 1. Add your interaction element as ‘input slot'
|
|
||||||
|
|
||||||
Here you return the element the user interacts with. By configuring it as a slot, it will end up
|
|
||||||
in light DOM, ensuring the best accessibility for the end user.
|
|
||||||
|
|
||||||
- ### 2. Proxy event `my-slider-changed` to `user-input-changed` event
|
|
||||||
|
|
||||||
The `user-input-changed` event is listened to by the FormatMixin: it should be regarded as the
|
|
||||||
equivalent of the `input` event of the platform, but for custom built interaction elements.
|
|
||||||
|
|
||||||
- ### 3. Proxy property `<my-slider>.mySliderValue` to `<lion-slider>.value`
|
|
||||||
|
|
||||||
Every time the `user-input-changed` fires, the value of `<my-slider>` is synchronized with the
|
|
||||||
[`modelValue`](./modelValue.md) of `<my-slider>`. Now the cycle is complete: the modelValue connects
|
|
||||||
your interaction element to all logic inside the LionField.
|
|
||||||
|
|
||||||
Steps as described can be implemented with the following javascript:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { LionField } from '@lion/form-core';
|
|
||||||
import './my-slider.js';
|
|
||||||
|
|
||||||
export class LionSlider extends LionField {
|
|
||||||
// 1. Add your interaction element as ‘input slot'
|
|
||||||
get slots() {
|
|
||||||
return {
|
|
||||||
...super.slots,
|
|
||||||
input: () => document.createElement(‘my-slider’),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Proxy event `my-slider-changed` to `user-input-changed` event
|
|
||||||
connectedCallback() {
|
|
||||||
super.connectedCallback();
|
|
||||||
this.addEventListener('my-slider-changed', this._proxyChangeEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
_proxyChangeEvent() {
|
|
||||||
this._inputNode.dispatchEvent(
|
|
||||||
new CustomEvent('user-input-changed', { bubbles: true, composed: true }),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Proxy property `<my-slider>.mySliderValue` to `<lion-slider>.value`
|
|
||||||
get value() {
|
|
||||||
return Array.from(this.children).find(child => child.slot === 'input').mySliderValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
set value(newV) {
|
|
||||||
Array.from(this.children).find(child => child.slot === 'input').mySliderValue = newV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
That was all. Now you can enhance your slider by writing custom validators for it
|
|
||||||
or by writing a parser to get a custom modelValue type.
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
|
|
||||||
|
|
||||||
# Form Fundaments
|
|
||||||
|
|
||||||
```js script
|
|
||||||
export default {
|
|
||||||
title: 'Forms/Field/Fundaments',
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
`Form control`s are the most fundamental building block of the Forms. They are the basis of
|
|
||||||
both `field`s and `fieldset`s, and the `form` itself.
|
|
||||||
|
|
||||||
## Fields
|
|
||||||
|
|
||||||
Fields are the actual form controls the end user interacts with.
|
|
||||||
They extend the `Field`(), which on its turn uses the `FormControlMixin`.
|
|
||||||
Fields provide a normalized, predictable API for platform components and custom made form controls.
|
|
||||||
On top of this, they feature:
|
|
||||||
|
|
||||||
- data synchronization with models
|
|
||||||
- formatting of view values
|
|
||||||
- advanced validation possibilities
|
|
||||||
- creation of advanced user interaction scenarios via `interaction states`
|
|
||||||
- provision of labels and help texts in an easy, declarative manner
|
|
||||||
- better focus management
|
|
||||||
- accessibility out of the box
|
|
||||||
- advanced styling possibilities: map your own Design System to the internal HTML structure
|
|
||||||
|
|
||||||
### Platform fields (wrappers)
|
|
||||||
|
|
||||||
- [`LionInput`](../../input/), a wrapper for `<input>`
|
|
||||||
- [`LionTextarea`](../../textarea/), a wrapper for `<textarea>`
|
|
||||||
- [`LionSelect`](../../select/), a wrapper for `<select>`
|
|
||||||
- [`LionRadio`](../../radio/), a wrapper for `<input type="radio">`
|
|
||||||
- [`LionCheckbox`](../../checkbox/), a wrapper for `<input type="checkbox">`
|
|
||||||
|
|
||||||
### Custom fields (wrappers)
|
|
||||||
|
|
||||||
Whenever a native form control doesn't exist or is not sufficient, a custom form control should
|
|
||||||
be created. One could think of components like:
|
|
||||||
|
|
||||||
- slider
|
|
||||||
- combobox
|
|
||||||
- autocomplete
|
|
||||||
- etc...
|
|
||||||
|
|
||||||
## Fieldsets
|
|
||||||
|
|
||||||
Fieldsets are groups of fields. They can be considered fields on their own as well, since they
|
|
||||||
partly share the normalized api via `FormControlMixin`.
|
|
||||||
Fieldsets are the basis for:
|
|
||||||
|
|
||||||
- [`LionFieldset`](../../fieldset/)
|
|
||||||
- [`LionForm`](../../form/)
|
|
||||||
- [`LionRadioGroup`](../../radio-group/)
|
|
||||||
- [`LionCheckboxGroup`](../../checkbox-group/)
|
|
||||||
|
|
||||||
## Other Resources
|
|
||||||
|
|
||||||
- [Model Value](./modelValue.md)
|
|
||||||
- [Formatting and parsing](./FormattingAndParsing.md)
|
|
||||||
- [Interaction states](./InteractionStates.md)
|
|
||||||
- [Validation System](../../validate/docs/ValidationSystem.md)
|
|
||||||
- [FieldCustomMixin](./FieldCustomMixin.md)
|
|
||||||
|
|
@ -1,118 +0,0 @@
|
||||||
[//]: # 'AUTO INSERT HEADER PREPUBLISH'
|
|
||||||
|
|
||||||
# Formatting and parsing
|
|
||||||
|
|
||||||
```js script
|
|
||||||
export default {
|
|
||||||
title: 'Forms/Field/Formatting and parsing',
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
The `FormatMixin` keeps track of the `modelValue`, `formattedValue` and `serializedValue`.
|
|
||||||
It is designed to work in conjunction with `LionField`.
|
|
||||||
|
|
||||||
## Concepts of different values
|
|
||||||
|
|
||||||
### modelValue
|
|
||||||
|
|
||||||
The model value is the result of the parser function.
|
|
||||||
It should be considered as the internal value used for validation and reasoning/logic.
|
|
||||||
The model value is 'ready for consumption' by the outside world (think of a Date object
|
|
||||||
or a float). The modelValue can (and is recommended to) be used as both input value and
|
|
||||||
output value of the `<lion-field>`.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
- For a date input: a String '20/01/1999' will be converted to new Date('1999/01/20')
|
|
||||||
- For a number input: a formatted String '1.234,56' will be converted to a Number: 1234.56
|
|
||||||
|
|
||||||
### formattedValue
|
|
||||||
|
|
||||||
The view value is the result of the formatter function (when available).
|
|
||||||
The result will be stored in the native \_inputNode (usually an input[type=text]).
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
- For a date input, this would be '20/01/1999' (dependent on locale).
|
|
||||||
- For a number input, this could be '1,234.56' (a String representation of modelValue
|
|
||||||
1234.56).
|
|
||||||
|
|
||||||
A value will not get formatted if it is invalid, so the user won't get rewarded for a falsy input.
|
|
||||||
|
|
||||||
### serializedValue
|
|
||||||
|
|
||||||
The serialized version of the model value.
|
|
||||||
This value exists for maximal compatibility with the platform API.
|
|
||||||
The serialized value can be an interface in context where data binding is not supported
|
|
||||||
and a serialized string needs to be set.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
- For a date input, this would be the iso format of a date, e.g. '1999-01-20'.
|
|
||||||
- For a number input this would be the String representation of a float ('1234.56' instead
|
|
||||||
of 1234.56)
|
|
||||||
|
|
||||||
When no parser is available, the value is usually the same as the formattedValue (being \_inputNode.value)
|
|
||||||
|
|
||||||
## Formatters, parsers and (de)serializers
|
|
||||||
|
|
||||||
In order to create advanced user experiences (automatically formatting a user input or an input
|
|
||||||
set imperatively by an Application Developer).
|
|
||||||
|
|
||||||
Below some concrete examples can be found of implementations of formatters and parsers,
|
|
||||||
extrapolating the example of a date input.
|
|
||||||
|
|
||||||
### Formatters
|
|
||||||
|
|
||||||
A formatter should return a `formattedValue`:
|
|
||||||
|
|
||||||
```js
|
|
||||||
function formatDate(modelValue, options) {
|
|
||||||
if (!(modelValue instanceof Date)) {
|
|
||||||
return options.formattedValue;
|
|
||||||
}
|
|
||||||
return formatDateLocalized(modelValue, options);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: the options object holds a fallback value that shows what should be presented on
|
|
||||||
screen when the user input resulted in an invalid modelValue
|
|
||||||
|
|
||||||
### Parsers
|
|
||||||
|
|
||||||
A parser should return a `modelValue`:
|
|
||||||
|
|
||||||
```js
|
|
||||||
function parseDate(formattedValue, options) {
|
|
||||||
return formattedValue === '' ? undefined : parseDateLocalized(formattedValue);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice that when it's not possible to create a valid modelValue based on the formattedValue,
|
|
||||||
one should return `undefined`.
|
|
||||||
|
|
||||||
### Serializers and deserializers
|
|
||||||
|
|
||||||
A serializer should return a `serializedValue`:
|
|
||||||
|
|
||||||
```js
|
|
||||||
function serializeDate(modelValue, options) {
|
|
||||||
return modelValue.toISOString();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
A deserializer should return a `modelValue`:
|
|
||||||
|
|
||||||
```js
|
|
||||||
function deserializeDate(serializeValue, options) {
|
|
||||||
return new Date(serializeValue);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Flow diagram
|
|
||||||
|
|
||||||
The following flow diagram is based on both end user input and interaction programmed by the
|
|
||||||
developer. It shows how the 'computation loop' for modelValue, formattedValue and serializedValue
|
|
||||||
is triggered.
|
|
||||||
|
|
||||||
[Flow diagram](./formatterParserFlow.svg)
|
|
||||||
|
|
@ -29,10 +29,10 @@ Our validation system is designed to:
|
||||||
- allow for advanced UX scenarios by updating validation state on every value change
|
- allow for advanced UX scenarios by updating validation state on every value change
|
||||||
- provide a powerful way of writing validations via classes
|
- provide a powerful way of writing validations via classes
|
||||||
|
|
||||||
Validation is applied by default to all [form controls](../form-core/docs/FormFundaments.md) via the
|
Validation is applied by default to all [form controls](?path=/docs/forms-field-overview--page) via the
|
||||||
ValidateMixin.
|
ValidateMixin.
|
||||||
|
|
||||||
For a detailed description of the validation system and the `ValidateMixin`, please see [ValidationSystem](./docs/ValidationSystem.md).
|
For a detailed description of the validation system and the `ValidateMixin`, please see [ValidationSystem](?path=/docs/forms-validation-system--page).
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ On top of default validators, application developers can write their own by exte
|
||||||
|
|
||||||
### Localization
|
### Localization
|
||||||
|
|
||||||
The `ValidateMixin` supports localization out of the box via the [localize system](../../localize/).
|
The `ValidateMixin` supports localization out of the box via the [localize system](?path=/docs/localize-intro--page).
|
||||||
All default validation messages are translated in the following languages (depicted by iso code):
|
All default validation messages are translated in the following languages (depicted by iso code):
|
||||||
bg, cs, de, en, es, fr, hu, it, nl, pl, ro ,ru, sk, uk and zh.
|
bg, cs, de, en, es, fr, hu, it, nl, pl, ro ,ru, sk, uk and zh.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ export const main = () => {
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Based on [lion-input](?path=/docs/forms-system-overview--page)
|
- Based on [lion-input](?path=/docs/forms-input--main#input)
|
||||||
- Makes use of [formatNumber](?path=/docs/localize-numbers) for formatting and parsing.
|
- Makes use of [formatNumber](?path=/docs/localize-numbers--formatting#formatting) for formatting and parsing.
|
||||||
- Option to show currency as a suffix
|
- Option to show currency as a suffix
|
||||||
- Option to override locale to change the formatting and parsing
|
- Option to override locale to change the formatting and parsing
|
||||||
- Option to provide additional format options overrides
|
- Option to provide additional format options overrides
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue