@lion/form-core
Advanced tools
Comparing version 0.9.0 to 0.10.0
# Change Log | ||
## 0.10.0 | ||
### Minor Changes | ||
- 13f808af: Add preprocessor hook for completely preventing invalid input or doing other preprocessing steps before the parsing process of the FormatMixin. | ||
### Patch Changes | ||
- aa478174: fix: prevent a11y violations when applying aria-required | ||
- a809d7b5: Make sync updatable mixin work for elements that get re-connected to DOM e.g. through appendChild. Needed for integration with global overlays. | ||
## 0.9.0 | ||
@@ -4,0 +15,0 @@ |
@@ -7,4 +7,4 @@ # Systems >> Form >> Overview ||10 | ||
- Built in [validate](https://github.com/ing-bank/lion/blob/6f2b6f940a0875091f1d940f45f0cd32dffce9ac/docs/docs/systems/form/validate.md) for error/warning/info/success | ||
- Built in [validate](https://github.com/ing-bank/lion/blob/80e1f79e0b9f3e9a6607c5b6c797aee575401603/docs/docs/systems/form/validate.md) for error/warning/info/success | ||
- Formatting of values | ||
- Accessible |
{ | ||
"name": "@lion/form-core", | ||
"version": "0.9.0", | ||
"version": "0.10.0", | ||
"description": "Form-core contains all essential building blocks for creating form fields and fieldsets", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -7,4 +7,4 @@ # Systems >> Form >> Overview ||10 | ||
- Built in [validate](https://github.com/ing-bank/lion/blob/6f2b6f940a0875091f1d940f45f0cd32dffce9ac/docs/docs/systems/form/validate.md) for error/warning/info/success | ||
- Built in [validate](https://github.com/ing-bank/lion/blob/80e1f79e0b9f3e9a6607c5b6c797aee575401603/docs/docs/systems/form/validate.md) for error/warning/info/success | ||
- Formatting of values | ||
- Accessible |
@@ -145,2 +145,10 @@ /* eslint-disable class-methods-use-this */ | ||
/** | ||
* @param {string} v - the raw value from the <input> after keyUp/Down event | ||
* @returns {string} preprocessedValue: the result of preprocessing for invalid input | ||
*/ | ||
preprocessor(v) { | ||
return v; | ||
} | ||
/** | ||
* Converts formattedValue to modelValue | ||
@@ -230,2 +238,9 @@ * For instance, a localized date to a Date Object | ||
/** | ||
* @param {string} value | ||
*/ | ||
__callPreprocessor(value) { | ||
return this.preprocessor(value); | ||
} | ||
/** | ||
* @param {string|undefined} value | ||
@@ -333,7 +348,8 @@ * @return {?} | ||
* Synchronization from `._inputNode.value` to `LionField` (flow [2]) | ||
* Downwards syncing should only happen for `LionField`.value changes from 'above'. | ||
* This triggers _onModelValueChanged and connects user input | ||
* to the parsing/formatting/serializing loop. | ||
*/ | ||
_syncValueUpwards() { | ||
// Downwards syncing should only happen for `LionField`.value changes from 'above' | ||
// This triggers _onModelValueChanged and connects user input to the | ||
// parsing/formatting/serializing loop | ||
this.value = this.__callPreprocessor(this.value); | ||
this.modelValue = this.__callParser(this.value); | ||
@@ -340,0 +356,0 @@ } |
@@ -37,9 +37,17 @@ import { dedupeMixin } from '@lion/core'; | ||
/** @param {import('@lion/core').PropertyValues } changedProperties */ | ||
/** | ||
* Empty pending queue in order to guarantee order independence | ||
* | ||
* @param {import('lit-element').PropertyValues } changedProperties | ||
*/ | ||
firstUpdated(changedProperties) { | ||
super.firstUpdated(changedProperties); | ||
this.__SyncUpdatableNamespace.connected = true; | ||
this.__syncUpdatableInitialize(); | ||
} | ||
connectedCallback() { | ||
super.connectedCallback(); | ||
this.__SyncUpdatableNamespace.connected = true; | ||
} | ||
disconnectedCallback() { | ||
@@ -93,5 +101,4 @@ super.disconnectedCallback(); | ||
.constructor); | ||
// Before connectedCallback: queue | ||
if (!ns.connected) { | ||
if (!ns.initialized) { | ||
ns.queue = ns.queue || new Set(); | ||
@@ -98,0 +105,0 @@ // Makes sure that we only initialize one time, with most up to date value |
@@ -5,2 +5,12 @@ /** | ||
export class Required extends Validator { | ||
/** | ||
* In order to prevent accessibility violations, the aria-required attribute will | ||
* be combined with compatible aria roles: https://www.w3.org/TR/wai-aria/#aria-required | ||
*/ | ||
static get _compatibleRoles(): string[]; | ||
/** | ||
* In order to prevent accessibility violations, the aria-required attribute will | ||
* be combined with compatible platform input elements | ||
*/ | ||
static get _compatibleTags(): string[]; | ||
constructor(param?: any, config?: { | ||
@@ -7,0 +17,0 @@ [x: string]: any; |
@@ -13,2 +13,29 @@ import { Validator } from '../Validator.js'; | ||
/** | ||
* In order to prevent accessibility violations, the aria-required attribute will | ||
* be combined with compatible aria roles: https://www.w3.org/TR/wai-aria/#aria-required | ||
*/ | ||
static get _compatibleRoles() { | ||
return [ | ||
'combobox', | ||
'gridcell', | ||
'input', | ||
'listbox', | ||
'radiogroup', | ||
'select', | ||
'spinbutton', | ||
'textarea', | ||
'textbox', | ||
'tree', | ||
]; | ||
} | ||
/** | ||
* In order to prevent accessibility violations, the aria-required attribute will | ||
* be combined with compatible platform input elements | ||
*/ | ||
static get _compatibleTags() { | ||
return ['input', 'select', 'textarea']; | ||
} | ||
/** | ||
* We don't have an execute function, since the Required validator is 'special'. | ||
@@ -25,3 +52,8 @@ * The outcome depends on the modelValue of the FormControl and | ||
if (formControl._inputNode) { | ||
formControl._inputNode.setAttribute('aria-required', 'true'); | ||
const role = formControl._inputNode.getAttribute('role') || ''; | ||
const elementTagName = formControl._inputNode.tagName.toLowerCase(); | ||
const ctor = /** @type {typeof Required} */ (this.constructor); | ||
if (ctor._compatibleRoles.includes(role) || ctor._compatibleTags.includes(elementTagName)) { | ||
formControl._inputNode.setAttribute('aria-required', 'true'); | ||
} | ||
} | ||
@@ -28,0 +60,0 @@ } |
@@ -303,2 +303,38 @@ import { LitElement } from '@lion/core'; | ||
}); | ||
it('reinitializes when the element gets reconnected to DOM', async () => { | ||
const container = await fixture(html`<div></div>`); | ||
class UpdatableImplementation extends SyncUpdatableMixin(LitElement) { | ||
static get properties() { | ||
return { | ||
prop: { attribute: false }, | ||
}; | ||
} | ||
constructor() { | ||
super(); | ||
this.prop = ''; | ||
} | ||
} | ||
const tagString = defineCE(UpdatableImplementation); | ||
const tag = unsafeStatic(tagString); | ||
const el = /** @type {UpdatableImplementation} */ (fixtureSync(html`<${tag}></${tag}>`)); | ||
const ns = el.__SyncUpdatableNamespace; | ||
const updateSyncSpy = sinon.spy(el, 'updateSync'); | ||
expect(ns.connected).to.be.true; | ||
expect(ns.initialized).to.be.undefined; | ||
await el.updateComplete; | ||
expect(ns.initialized).to.be.true; | ||
el.parentElement?.removeChild(el); | ||
expect(ns.connected).to.be.false; | ||
container.appendChild(el); | ||
expect(ns.connected).to.be.true; | ||
// change a prop to cause rerender | ||
expect(updateSyncSpy.calledWith('prop', undefined)).to.be.true; | ||
el.prop = 'a'; | ||
await el.updateComplete; | ||
expect(updateSyncSpy.calledWith('prop', '')).to.be.true; | ||
}); | ||
}); |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
643606
127
19280