Skip to content

Commit

Permalink
fix(input): support disabled and readonly with [multiple]
Browse files Browse the repository at this point in the history
  • Loading branch information
clshortfuse committed Jul 31, 2024
1 parent c15ac0e commit 16db8a8
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 45 deletions.
98 changes: 63 additions & 35 deletions components/Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -375,45 +375,55 @@ export default CustomElement
this.changeSuggestion({ value: this._listboxValue });
}
},
populateInputFromListbox() {
if (this.multiple) {
const { _values } = this;
/** @type {InstanceType<import('./InputChip.js').default>} */
let element = this.refs.chips.firstElementChild;

for (let i = 0; i < _values.length; i++) {
const currentValue = _values[i];
let foundOption;
if (this.listbox) {
for (const option of this.listbox.options) {
if (option.value === currentValue) {
foundOption = option;
break;
}
}
}
refreshMultiple() {
const { _values, multiple } = this;
if (!multiple) {
this.refs.chips.replaceChildren();
return;
}
/** @type {InstanceType<import('./InputChip.js').default>} */
let element = this.refs.chips.firstElementChild;

element ??= this.refs.chips.appendChild(document.createElement('mdw-input-chip'));
element.closeButton = true;
element.textContent = foundOption?.label || currentValue;
// eslint-disable-next-line unicorn/prefer-add-event-listener
element.onclose ??= this.onChipClose.bind(this);
element = element.nextElementSibling;
}
while (element) {
const prev = element;
element = element.nextElementSibling;
prev.remove();
}
this._chipSelected = false;
this._input.value = '';
this._draftInput = '';
this._listboxValue = '';
for (let i = 0; i < _values.length; i++) {
const currentValue = _values[i];
let foundOption;
if (this.listbox) {
for (const option of this.listbox.options) {
option.selected = _values.includes(option.value);
if (option.value === currentValue) {
foundOption = option;
break;
}
}
}

element ??= this.refs.chips.appendChild(document.createElement('mdw-input-chip'));
element.closeButton = true;
element.textContent = foundOption?.label || currentValue;
element.textContent = foundOption?.label || currentValue;
element.disabled = this.disabled;
element.readOnly = this.readOnly;
// eslint-disable-next-line unicorn/prefer-add-event-listener
element.onclose ??= this.onChipClose.bind(this);
element = element.nextElementSibling;
}
while (element) {
const prev = element;
element = element.nextElementSibling;
prev.remove();
}
this._chipSelected = false;
this._input.value = '';
this._draftInput = '';
this._listboxValue = '';
if (this.listbox) {
for (const option of this.listbox.options) {
option.selected = _values.includes(option.value);
}
}
},
populateInputFromListbox() {
if (this.multiple) {
this.refreshMultiple();
return;
}
if (!this._isSelect) return;
Expand Down Expand Up @@ -495,6 +505,8 @@ export default CustomElement
break;
case 'ArrowDown':
case 'Down':
if (this.disabled) return;
if (this.readOnly) return;
this._chipSelected = false;
if (this.readOnly) return;
if (event.altKey) {
Expand All @@ -506,6 +518,8 @@ export default CustomElement
break;
case 'ArrowUp':
case 'Up':
if (this.disabled) return;
if (this.readOnly) return;
if (event.altKey) {
this.toggleListbox();
break;
Expand All @@ -526,6 +540,8 @@ export default CustomElement
this.closeListbox();
break;
case 'Space':
if (this.disabled) return;
if (this.readOnly) return;
if (!this._isSelect) return;
if (!this._listbox) return;
if (this._expanded) {
Expand All @@ -538,6 +554,8 @@ export default CustomElement
}
break;
case 'Backspace':
if (this.disabled) return;
if (this.readOnly) return;
if (!this.multiple) return;
if (this._isSelect) return;
if (!this._input.value) {
Expand Down Expand Up @@ -738,7 +756,7 @@ export default CustomElement
_valuesChanged(previous, current) {
if (this.multiple && current) {
this._value = current.join(',');
this.populateInputFromListbox();
this.refreshMultiple();
}
},
_chipSelectedChanged(previous, current) {
Expand Down Expand Up @@ -771,6 +789,16 @@ export default CustomElement
this._onSetValue(this._input.value);
}
},
disabledStateChanged() {
this.refreshMultiple();
this._chipSelected = false;
this.closeListbox();
},
readOnlyChanged() {
this.refreshMultiple();
this._chipSelected = false;
this.closeListbox();
},
})
.html`
<div id=chips mdw-if={multiple}></div>
Expand Down
23 changes: 13 additions & 10 deletions components/InputChip.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { EVENT_HANDLER_TYPE } from '../core/customTypes.js';
import DelegatesFocusMixin from '../mixins/DelegatesFocusMixin.js';
import FormAssociatedMixin from '../mixins/FormAssociatedMixin.js';
import HyperlinkMixin from '../mixins/HyperlinkMixin.js';
import ShapeMixin from '../mixins/ShapeMixin.js';

Expand All @@ -12,14 +11,15 @@ import './IconButton.js';
export default Box
.extend()
.mixin(ShapeMixin)
.mixin(FormAssociatedMixin) // Tap into FormAssociated for disabledState
.mixin(DelegatesFocusMixin)
.mixin(HyperlinkMixin)
.observe({
avatar: 'boolean',
closeButton: 'boolean',
closeIcon: { empty: 'close' },
closeInk: { empty: 'inherit' },
readOnly: { attr: 'readonly', type: 'boolean' },
disabled: 'boolean',
icon: 'string',
iconInk: 'string',
src: 'string',
Expand All @@ -36,6 +36,9 @@ export default Box
hasIcon({ icon, svg, src, svgPath } = this) {
return icon ?? svg ?? src ?? svgPath;
},
showCloseIcon({ disabled, readOnly, closeButton }) {
return closeButton && !disabled && !readOnly;
},
})
.html`
<mdw-button
Expand All @@ -47,11 +50,11 @@ export default Box
ping={ping}
rel={rel}
hreflang={hreflang}
referrerpolicy={referrerPolicy} id=action disabled={disabledState}></mdw-button>
<mdw-icon mdw-if={hasIcon} id=icon ink={iconInk} disabled={disabledState}
referrerpolicy={referrerPolicy} id=action disabled={disabled}></mdw-button>
<mdw-icon mdw-if={hasIcon} id=icon ink={iconInk} disabled={disabled}
outlined={outlined} variation={iconVariation} aria-hidden=true svg={svg} src={src}
svg-path={svgPath} view-box={viewBox} icon={icon} avatar={avatar}></mdw-icon>
<mdw-icon-button role=none disabled={disabledState} tabindex=-1 mdw-if={closeButton} id=close class=button icon={closeIcon} ink={closeInk}>Close</mdw-icon-button>
<mdw-icon-button role=none disabled={disabled} tabindex=-1 mdw-if={showCloseIcon} id=close class=button icon={closeIcon} ink={closeInk}>Close</mdw-icon-button>
`
.css`
/* https://m3.material.io/components/chips/specs */
Expand Down Expand Up @@ -80,7 +83,7 @@ export default Box
padding-inline-start: calc(4px + (var(--mdw-density) * 2px));
}
:host(:where([close-button])) {
:host(:where([close-button]:not([disabled]):not([readonly]))) {
padding-inline-end: calc(8px + 18px + 8px + (var(--mdw-density) * 2px));
}
Expand Down Expand Up @@ -117,13 +120,12 @@ export default Box
--mdw-ink: rgb(var(--mdw-color__on-surface-variant));
}
#outline:is([ink],[color]) {
#outline:is([ink],[color],[disabled]) {
/* stylelint-disable-next-line rule-selector-property-disallowed-list */
--mdw-ink: inherit;
}
#slot[disabled],
#icon[disabled] {
:host([disabled]) {
color: rgba(var(--mdw-color__on-surface), 0.38);
}
Expand All @@ -148,11 +150,12 @@ export default Box
.recompose(({ refs: { anchor, slot, icon, outline } }) => {
icon.after(slot);
anchor.remove();
slot.setAttribute('disabled', '{disabledState}');
slot.setAttribute('disabled', '{disabled}');
slot.removeAttribute('ink');
slot.removeAttribute('color');
outline.removeAttribute('mdw-if');
outline.setAttribute('ink', '{ink}');
outline.setAttribute('color', '{color}');
outline.setAttribute('disabled', '{disabled}');
})
.autoRegister('mdw-input-chip');

0 comments on commit 16db8a8

Please sign in to comment.