diff --git a/packages/checkbox-group/README.md b/packages/checkbox-group/README.md index 5584c8c29..0cd5d842b 100644 --- a/packages/checkbox-group/README.md +++ b/packages/checkbox-group/README.md @@ -11,6 +11,7 @@ Its purpose is to provide a way for users to check **multiple** options amongst import { html } from '@lion/core'; import { Required, Validator } from '@lion/form-core'; import './lion-checkbox-group.js'; +import './lion-checkbox-indeterminate.js'; import './lion-checkbox.js'; export default { @@ -166,3 +167,17 @@ export const event = () => html` Selected scientists: N/A `; ``` + +### Indeterminate + +```js preview-story +export const indeterminate = () => html` + + + + + + + +`; +``` diff --git a/packages/checkbox-group/index.js b/packages/checkbox-group/index.js index 6f20e3181..c07ad86a5 100644 --- a/packages/checkbox-group/index.js +++ b/packages/checkbox-group/index.js @@ -1,2 +1,3 @@ export { LionCheckboxGroup } from './src/LionCheckboxGroup.js'; +export { LionCheckboxIndeterminate } from './src/LionCheckboxIndeterminate.js'; export { LionCheckbox } from './src/LionCheckbox.js'; diff --git a/packages/checkbox-group/lion-checkbox-indeterminate.js b/packages/checkbox-group/lion-checkbox-indeterminate.js new file mode 100644 index 000000000..37b65d36b --- /dev/null +++ b/packages/checkbox-group/lion-checkbox-indeterminate.js @@ -0,0 +1,3 @@ +import { LionCheckboxIndeterminate } from './src/LionCheckboxIndeterminate.js'; + +customElements.define('lion-checkbox-indeterminate', LionCheckboxIndeterminate); diff --git a/packages/checkbox-group/package.json b/packages/checkbox-group/package.json index 044b29017..8e6bfa78d 100644 --- a/packages/checkbox-group/package.json +++ b/packages/checkbox-group/package.json @@ -31,7 +31,8 @@ }, "sideEffects": [ "lion-checkbox.js", - "lion-checkbox-group.js" + "lion-checkbox-group.js", + "lion-checkbox-indeterminate.js" ], "dependencies": { "@lion/core": "0.13.8", diff --git a/packages/checkbox-group/src/LionCheckboxIndeterminate.js b/packages/checkbox-group/src/LionCheckboxIndeterminate.js new file mode 100644 index 000000000..a164ec8c4 --- /dev/null +++ b/packages/checkbox-group/src/LionCheckboxIndeterminate.js @@ -0,0 +1,91 @@ +import { LionCheckbox } from './LionCheckbox.js'; + +export class LionCheckboxIndeterminate extends LionCheckbox { + static get properties() { + return { + /** + * Indeterminate state of the checkbox + */ + indeterminate: { + type: Boolean, + reflect: true, + }, + }; + } + + get _checkboxGroupNode() { + return /** @type {import('./LionCheckboxGroup').LionCheckboxGroup} */ (this.parentElement); + } + + get _subCheckboxes() { + return this._checkboxGroupNode.formElements.filter(checkbox => checkbox !== this); + } + + _parentModelValueChanged() { + const checkedElements = this._subCheckboxes.filter(checkbox => checkbox.checked); + switch (this._subCheckboxes.length - checkedElements.length) { + // all checked + case 0: + this.indeterminate = false; + this.checked = true; + break; + // none checked + case this._subCheckboxes.length: + this.indeterminate = false; + this.checked = false; + break; + default: + this.indeterminate = true; + } + } + + _ownModelValueChanged(ev) { + if (ev.target === this) { + this._subCheckboxes.forEach(checkbox => { + // eslint-disable-next-line no-param-reassign + checkbox.checked = this.checked; + }); + } + } + + constructor() { + super(); + this.indeterminate = false; + } + + connectedCallback() { + super.connectedCallback(); + this._checkboxGroupNode.addEventListener( + 'model-value-changed', + this._parentModelValueChanged.bind(this), + ); + this.addEventListener('model-value-changed', this._ownModelValueChanged); + } + + /** @param {import('lit-element').PropertyValues } changedProperties */ + updated(changedProperties) { + super.updated(changedProperties); + if (changedProperties.has('indeterminate')) { + this._inputNode.indeterminate = this.indeterminate; + } + } + + /** + * @override + * clicking on indeterminate status will set the status as checked + */ + __toggleChecked() { + if (this.disabled) { + return; + } + + // always turn off indeterminate + // and set checked to true + if (this.indeterminate) { + this.indeterminate = false; + this.checked = true; + } else { + this.checked = !this.checked; + } + } +}