Socket
Socket
Sign inDemoInstall

@anypoint-web-components/anypoint-radio-button

Package Overview
Dependencies
9
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.1 to 0.1.2

10

anypoint-radio-button.js
import { LitElement, html, css } from 'lit-element';
import { CheckedElementMixin } from '@anypoint-web-components/anypoint-form-mixins/anypoint-form-mixins.js';
import '@anypoint-web-components/anypoint-styles/colors.js';
/**

@@ -67,2 +68,3 @@ * `anypoint-radio-button`

cursor: pointer;
vertical-align: middle;
}

@@ -190,4 +192,5 @@

:host([disabled]) #radioLabel {
opacity: 0.65;
:host([disabled]) .radioLabel {
pointer-events: none;
color: var(--anypoint-radio-button-disabled-color, #a8a8a8);
}

@@ -291,2 +294,5 @@ `;

_asyncClick() {
if (this.disabled) {
return;
}
setTimeout(() => this.click(), 1);

@@ -293,0 +299,0 @@ }

234

anypoint-radio-group.js

@@ -0,1 +1,3 @@

import { LitElement } from 'lit-element';
import { AnypointMenuMixin } from '@anypoint-web-components/anypoint-menu-mixin/anypoint-menu-mixin.js';
/**

@@ -36,8 +38,5 @@ * A web component that groups custom radio buttons and handles selection inside

*/
class AnypointRadioGroup extends HTMLElement {
/**
* @return {Node|undefined} Currently selected radio button.
*/
get selected() {
return this._selected;
class AnypointRadioGroup extends AnypointMenuMixin(LitElement) {
createRenderRoot() {
return this;
}

@@ -53,57 +52,19 @@ /**

super();
this._nodesChanged = this._nodesChanged.bind(this);
this._radioAction = this._radioAction.bind(this);
this.multi = false;
}
connectedCallback() {
if (super.connectedCallback) {
super.connectedCallback();
}
this.style.display = 'inline-block';
this.style.verticalAlign = 'middle';
this.setAttribute('role', 'radiogroup');
const config = {
attributes: true,
childList: true,
subtree: true
};
this._observer = new MutationObserver(this._nodesChanged);
this._observer.observe(this, config);
this._discoverNodes();
}
disconnectedCallback() {
this._observer.disconnect();
this._observer = null;
this._removeListeners();
}
/**
* Processes mutations to the light DOM of this element.
* Processes added and removed nodes and changes to attributes.
* @param {Array<MutationRecord>} mutationsList List of changes discovered by
* `MutationObserver`
*/
_nodesChanged(mutationsList) {
for (const mutation of mutationsList) {
switch (mutation.type) {
case 'attributes':
this._processNodeAttributeChange(mutation);
break;
case 'childList':
this._processAddedNodes(mutation.addedNodes);
this._processRemovedNodes(mutation.removedNodes);
this._manageNodesSelection(mutation.addedNodes);
break;
}
this.selectable = '[role=radio],input[type=radio]';
this._ensureSingleSelection();
if (this.disabled) {
this._disabledChanged(this.disabled);
}
}
/**
* This to be run when element is inserted into the DOM.
* It discovers radio buttons in light DOM and manages the sate.
*/
_discoverNodes() {
const nodes = this.elements;
if (nodes.length) {
this._processAddedNodes(nodes);
this._manageNodesSelection(nodes);
}
}
/**
* Function that manages attribute change.

@@ -120,2 +81,5 @@ * If the changed attribute is `role` with value `radio` then the node is processed

const target = record.target;
if (target === this) {
return;
}
if (target.getAttribute('role') === 'radio') {

@@ -128,32 +92,2 @@ this._processAddedNodes([target]);

/**
* Processes new and existing nodes and makes single selection from multiple selected
* radio buttons. If arriving `nodes` has selected nodes the last selected node in
* the selection keeps the selection.
*
* @param {NodeList?} nodes Optional list of newly added nodes to the light DOM.
*/
_manageNodesSelection(nodes) {
let selected = this._lastSelected(nodes);
const domNodes = this.elements;
if (!selected) {
selected = this._lastSelected(domNodes);
}
if (!selected) {
return;
}
this._selected = selected;
for (let i = domNodes.length - 1; i >= 0; i--) {
const node = domNodes[i];
if (!this._isRadioButton(node)) {
continue;
}
if (node.disabled || !node.checked) {
continue;
}
if (node !== selected && node.checked) {
node.checked = false;
}
}
}
/**
* Tests if given node is a radio button.

@@ -174,21 +108,2 @@ * @param {Node} node A node to test

/**
* @param {NodeList?} nodes Optional list of nodes to check for selection.
* @return {Node} Last selected node or undefined when no selection is detected.
*/
_lastSelected(nodes) {
if (!nodes || !nodes.length) {
return;
}
for (let i = nodes.length - 1; i >= 0; i--) {
const node = nodes[i];
if (!this._isRadioButton(node)) {
continue;
}
if (node.disabled || !node.checked) {
continue;
}
return node;
}
}
/**
* Adds `change` event listener to detected radio buttons.

@@ -202,9 +117,6 @@ * A button is considered as a radio button when its `role` is `radio`.

const node = nodes[i];
if (!this._isRadioButton(node)) {
if (node === this || !this._isRadioButton(node)) {
continue;
}
// The event may have been already added when the attribute has been set
// with the same name again.
node.removeEventListener('change', this._radioAction);
node.addEventListener('change', this._radioAction);
node.setAttribute('tabindex', '-1');
}

@@ -220,3 +132,3 @@ }

const node = nodes[i];
if (!this._isRadioButton(node)) {
if (node === this || !this._isRadioButton(node)) {
continue;

@@ -234,42 +146,96 @@ }

_nodeRemoved(node) {
node.removeEventListener('change', this._radioAction);
if (node === this._selected) {
this._selected = undefined;
const { selected } = this;
if ((selected || selected === 0) && this._valueForItem(node) === selected) {
this.selected = undefined;
}
}
/**
* Remove listeners from all current `elements`.
* Overrides `AnypointMenuMixin._onKeydown`. Adds right / left arrows support.
* @param {KeyboardEvent} e
*/
_removeListeners() {
const nodes = this.elements;
for (let i = 0, len = nodes.length; i < len; i++) {
nodes[i].removeEventListener('change', this._radioAction);
_onKeydown(e) {
if (e.key === 'ArrowRight') {
this._onDownKey(e);
e.stopPropagation();
} else if (e.key === 'ArrowLeft') {
this._onUpKey(e);
e.stopPropagation();
} else {
super._onKeydown(e);
}
}
/**
* Handler for radio's `change` event.
* @param {Event} e
* Overrides `AnypointSelectableMixin._applySelection` to manage item's checked
* state.
* @param {Node} item Selected / deselected item.
* @param {Boolean} isSelected True if the item is selected
*/
_radioAction(e) {
const target = e.target;
if (!target.checked) {
return;
_applySelection(item, isSelected) {
super._applySelection(item, isSelected);
item.checked = isSelected;
}
/**
* Ensures that the last child element is checked in the group.
*/
_ensureSingleSelection() {
const nodes = this._items;
let checked = false;
for (let i = nodes.length - 1; i >= 0; i--) {
const currentChecked = nodes[i].checked;
if (currentChecked && !checked) {
checked = true;
if (this.attrForSelected) {
const value = this._valueForItem(nodes[i]);
this.select(value);
} else {
this.select(i);
}
} else if (currentChecked && checked) {
this._applySelection(nodes[i], false);
}
}
this._selected = target;
const name = target.name;
if (!name) {
return;
}
// Normally you would use querySelectorAll with [name="${name}"]
// but the name can be anything, including invalid selectors causing
// error. This queries for all checkboxes and compares names manually.
const nodes = this.elements;
for (let i = 0, len = nodes.length; i < len; i++) {
const node = nodes[i];
if (node.name !== name && node !== target && node.checked) {
node.checked = false;
}
/**
* Overrides `AnypointSelectableMixin._mutationHandler`.
* Processes dynamically added nodes and updates selection if needed.
* @param {Array<MutationRecord>} mutationsList A list of changes record
*/
_mutationHandler(mutationsList) {
for (const mutation of mutationsList) {
if (mutation.type === 'attributes') {
this._processNodeAttributeChange(mutation);
} else if (mutation.type === 'childList') {
if (mutation.addedNodes && mutation.addedNodes.length) {
this._ensureSingleSelection();
}
if (mutation.removedNodes && mutation.removedNodes.length) {
this._processRemovedNodes(mutation.removedNodes);
}
}
}
super._mutationHandler(mutationsList);
}
/**
* Overrides `AnypointSelectableMixin._observeItems` to include subtree.
* @return {MutationObserver}
*/
_observeItems() {
const config = {
attributes: true,
childList: true,
subtree: true
};
const observer = new MutationObserver(this._mutationHandler);
observer.observe(this, config);
return observer;
}
/**
* Disables children when disabled state changes
* @param {Boolean} disabled
*/
_disabledChanged(disabled) {
super._disabledChanged(disabled);
this.items.forEach((node) => node.disabled = disabled);
}
}
window.customElements.define('anypoint-radio-group', AnypointRadioGroup);
{
"name": "@anypoint-web-components/anypoint-radio-button",
"description": "Anypoint styled radio button",
"version": "0.1.1",
"version": "0.1.2",
"license": "Apache-2.0",

@@ -33,18 +33,20 @@ "main": "anypoint-radio-button.js",

"@anypoint-web-components/anypoint-form-mixins": "^1.0.1",
"@anypoint-web-components/anypoint-menu-mixin": "^1.0.0",
"@anypoint-web-components/anypoint-styles": "^1.0.0-preview.1",
"lit-element": "^2.0.1"
},
"devDependencies": {
"@advanced-rest-client/arc-demo-helper": "^1.0.9",
"@advanced-rest-client/arc-demo-helper": "^1.0.12",
"@advanced-rest-client/eslint-config": "^1.0.6",
"@advanced-rest-client/prettier-config": "^0.1.0",
"@advanced-rest-client/testing-karma-sl": "^1.0.3",
"@anypoint-web-components/anypoint-styles": "^1.0.0-preview.1",
"@anypoint-web-components/anypoint-checkbox": "^1.0.0",
"@commitlint/cli": "^8.1.0",
"@commitlint/config-conventional": "^7.0.0",
"@open-wc/testing": "^2.2.1",
"@open-wc/testing-karma": "^3.1.5",
"@open-wc/testing-karma": "^3.1.17",
"@polymer/gen-typescript-declarations": "^1.6.2",
"@polymer/iron-test-helpers": "^3.0.1",
"deepmerge": "^4.0.0",
"es-dev-server": "^1.8.3",
"es-dev-server": "^1.11.1",
"husky": "^1.0.0",

@@ -51,0 +53,0 @@ "karma": "^4.2.0",

@@ -7,6 +7,13 @@ [![Published on NPM](https://img.shields.io/npm/v/@anypoint-web-components/anypoint-radio-button.svg)](https://www.npmjs.com/package/@anypoint-web-components/anypoint-radio-button)

Accessible radio button and radio buttons group for Anypoint platform
Accessible radio button and radio button group for Anypoint platform.
Radio buttons are used to select one of predefined options.
Radio buttons should be used when the user must see all available options. Consider using a dropdown list if the options can be collapsed.
See [Radio buttons](https://material.io/design/components/selection-controls.html#radio-buttons) documentation in Material Design documentation for principles and anatomy of radio buttons.
## Usage
### Installation
```

@@ -13,0 +20,0 @@ npm i --save @anypoint-web-components/anypoint-radio-button

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc