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: [
|
||||
'../packages/*/README.md',
|
||||
'../packages/*/docs/*.md',
|
||||
'../packages/*/docs/!(assets)**/*.md',
|
||||
'../docs/README.md',
|
||||
'../docs/**/*.md',
|
||||
'../README.md',
|
||||
|
|
|
|||
|
|
@ -57,6 +57,5 @@ Fieldsets are the basis for:
|
|||
|
||||
## Other Resources
|
||||
|
||||
- [Form fundamentals](?path=/docs/forms-field-fundaments--page)
|
||||
- [Formatting and parsing](?path=/docs/forms-field-formatting-and-parsing--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
|
||||
- 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.
|
||||
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ On top of default validators, application developers can write their own by exte
|
|||
|
||||
### 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):
|
||||
bg, cs, de, en, es, fr, hu, it, nl, pl, ro ,ru, sk, uk and zh.
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ export const main = () => {
|
|||
|
||||
## Features
|
||||
|
||||
- Based on [lion-input](?path=/docs/forms-system-overview--page)
|
||||
- Makes use of [formatNumber](?path=/docs/localize-numbers) for formatting and parsing.
|
||||
- Based on [lion-input](?path=/docs/forms-input--main#input)
|
||||
- Makes use of [formatNumber](?path=/docs/localize-numbers--formatting#formatting) for formatting and parsing.
|
||||
- Option to show currency as a suffix
|
||||
- Option to override locale to change the formatting and parsing
|
||||
- Option to provide additional format options overrides
|
||||
|
|
|
|||
Loading…
Reference in a new issue