From 9d64cb36f569e57cde360b0ec65378345d7ec987 Mon Sep 17 00:00:00 2001 From: Thijs Louisse Date: Wed, 3 Jul 2019 00:08:01 +0200 Subject: [PATCH] chore(form-system): add form fundament demos --- packages/form-system/package.json | 3 + .../form-system/stories/formatting.stories.js | 131 ++++++++++++++++++ .../form-system/stories/helper-wc/h-output.js | 105 ++++++++++++++ .../stories/interactionStates.stories.js | 105 ++++++++++++++ stories/index.stories.js | 3 + 5 files changed, 347 insertions(+) create mode 100644 packages/form-system/stories/formatting.stories.js create mode 100644 packages/form-system/stories/helper-wc/h-output.js create mode 100644 packages/form-system/stories/interactionStates.stories.js diff --git a/packages/form-system/package.json b/packages/form-system/package.json index 3b30205c9..2b3ffc269 100644 --- a/packages/form-system/package.json +++ b/packages/form-system/package.json @@ -35,6 +35,7 @@ "@lion/checkbox": "^0.1.51", "@lion/checkbox-group": "^0.1.57", "@lion/core": "^0.1.13", + "@lion/field": "^0.2.3", "@lion/fieldset": "^0.1.50", "@lion/form": "^0.1.56", "@lion/input": "^0.1.50", @@ -42,9 +43,11 @@ "@lion/input-date": "^0.1.51", "@lion/input-email": "^0.1.50", "@lion/input-iban": "^0.1.52", + "@lion/localize": "^0.4.14", "@lion/radio": "^0.1.51", "@lion/radio-group": "^0.1.57", "@lion/textarea": "^0.1.53", + "@lion/validate": "^0.2.29", "@open-wc/demoing-storybook": "^0.2.0", "@open-wc/testing": "^2.0.6" } diff --git a/packages/form-system/stories/formatting.stories.js b/packages/form-system/stories/formatting.stories.js new file mode 100644 index 000000000..9be528afa --- /dev/null +++ b/packages/form-system/stories/formatting.stories.js @@ -0,0 +1,131 @@ +import { storiesOf, html } from '@open-wc/demoing-storybook'; +import { Unparseable } from '@lion/validate'; +import '@lion/input/lion-input.js'; +import './helper-wc/h-output.js'; + +function newDateValid(d) { + const result = d ? new Date(d) : new Date(); + return !isNaN(result.getTime()) ? result : null; // eslint-disable-line no-restricted-globals +} + +storiesOf('Form Fundaments|Formatting and Parsing', module) + .add( + 'model value', + () => html` +

+ Note: we always use lion-input to demonstrate, but all things that extend lion-input have + this functionality! +

+ + + + `, + ) + .add( + 'parser', + () => html` + + + + `, + ) + .add( + 'formatter', + () => html` + + + + `, + ) + /* .add( + 'preprocessor', + () => html` + + + + `, + ) */ + .add( + '(de)serializer', + () => html` + + + + `, + ) + .add( + 'Unparseable', + () => html` +
+ + + +
+ `, + ) + .add( + 'Unparseable restore', + () => html` + + + + `, + ); diff --git a/packages/form-system/stories/helper-wc/h-output.js b/packages/form-system/stories/helper-wc/h-output.js new file mode 100644 index 000000000..34a6a8902 --- /dev/null +++ b/packages/form-system/stories/helper-wc/h-output.js @@ -0,0 +1,105 @@ +import { LitElement, html, css } from '@lion/core'; +import { LionField } from '@lion/field'; + +export class HelperOutput extends LitElement { + static get properties() { + return { + field: Object, + show: Array, + }; + } + + static get styles() { + return [ + css` + :host { + display: block; + margin-top: 16px; + } + + table, + th, + td { + border: 1px solid #ccc; + padding: 4px; + font-size: 12px; + } + + table { + border-collapse: collapse; + } + + caption { + text-align: left; + } + `, + ]; + } + + firstUpdated(c) { + super.firstUpdated(c); + if (!this.field) { + // Fuzzy logic, but... practical + const prev = this.previousElementSibling; + if (prev instanceof LionField) { + this.field = prev; + } + } + this.__rerender = this.__rerender.bind(this); + this.field.addEventListener('model-value-changed', this.__rerender); + this.field.addEventListener('mousemove', this.__rerender); + this.field.addEventListener('blur', this.__rerender); + this.field.addEventListener('focusin', this.__rerender); + this.field.addEventListener('focusout', this.__rerender); + + if (this.field.inputElement.form) { + this.field.inputElement.form.addEventListener('submit', this.__rerender); + } + } + + __rerender() { + setTimeout(() => { + const f = this.field; + this.field = null; + this.field = f; + }); + } + + __renderProp(p) { + if (typeof p === 'boolean') { + return p === true ? '✓' : ''; + } + if (typeof p === 'undefined') { + return '?'; + } + return p; + } + + render() { + const field = this.field || {}; + return html` + + + + ${this.show.map( + prop => html` + + `, + )} + + + + ${this.show.map( + prop => html` + + `, + )} + +
+ Interaction States +
${prop}
${this.__renderProp(field[prop])}
+ `; + } +} + +customElements.define('h-output', HelperOutput); diff --git a/packages/form-system/stories/interactionStates.stories.js b/packages/form-system/stories/interactionStates.stories.js new file mode 100644 index 000000000..fdebf0a5b --- /dev/null +++ b/packages/form-system/stories/interactionStates.stories.js @@ -0,0 +1,105 @@ +import { storiesOf, html } from '@open-wc/demoing-storybook'; +import { render } from '@lion/core'; +import { localize } from '@lion/localize'; +import '@lion/checkbox/lion-checkbox.js'; +import '@lion/checkbox-group/lion-checkbox-group.js'; +import '@lion/form/lion-form.js'; +import '@lion/input/lion-input.js'; +import './helper-wc/h-output.js'; + +function renderOffline(litHtmlTemplate) { + const offlineRenderContainer = document.createElement('div'); + render(litHtmlTemplate, offlineRenderContainer); + return offlineRenderContainer.firstElementChild; +} + +function addTranslations(ns, data) { + if (!localize._isNamespaceInCache('en-GB', ns)) { + localize.addData('en-GB', ns, data); + } +} + +storiesOf('Form Fundaments|Interaction States', module) + .add( + 'States', + () => html` + + + + + + + `, + ) + .add('Feedback condition', () => { + // 1. Initialize variables... + // properties on InteractionStateMixin we want to check conditions for + const props = ['touched', 'dirty', 'prefilled', 'focused', 'filled', 'submitted']; + + // Here we will store the conditions (trigger for validation feedback) + // provided via the UI of the demo + let conditions = []; + + // 2. Create a validator... + // Define a demo validator that should only be visible on an odd amount of characters + const oddValidator = [modelValue => ({ odd: modelValue.length % 2 !== 0 })]; + + addTranslations('lion-validate+odd', { + error: { + odd: '[ Error feedback ] : Add or remove one character', + }, + }); + + // 3. Create field overriding .showErrorCondition... + // Here we will store a reference to the Field element that overrides the default condition + // (function `showErrorCondition`) for triggering validation feedback of `.errorValidators` + const fieldElement = renderOffline(html` + + + + `); + + function fetchConditionsAndReevaluate({ currentTarget: { modelValue } }) { + if (!modelValue['props[]']) { + return; + } + // Create props list like: ['touched', 'submitted'] + conditions = modelValue['props[]'].filter(p => p.checked).map(p => p.value); + // Reevaluate + fieldElement.validate(); + } + + return html` + +
+ ${fieldElement} + +
+
+ + + +

+ Set conditions for validation feedback visibility +

+ + + ${props.map( + p => html` + + `, + )} + + `; + }); diff --git a/stories/index.stories.js b/stories/index.stories.js index dbf8e0500..bd8ebdfa8 100755 --- a/stories/index.stories.js +++ b/stories/index.stories.js @@ -14,7 +14,10 @@ import '../packages/fieldset/stories/index.stories.js'; import '../packages/checkbox-group/stories/index.stories.js'; import '../packages/radio-group/stories/index.stories.js'; import '../packages/form/stories/index.stories.js'; + import '../packages/form-system/stories/index.stories.js'; +import '../packages/form-system/stories/formatting.stories.js'; +import '../packages/form-system/stories/interactionStates.stories.js'; import '../packages/icon/stories/index.stories.js'; import '../packages/ajax/stories/index.stories.js';