Skip to content

Commit

Permalink
feat(m3,base,core)!: all migrated to lit
Browse files Browse the repository at this point in the history
  • Loading branch information
vollowx committed Apr 3, 2024
1 parent ba198f9 commit 66daf66
Show file tree
Hide file tree
Showing 38 changed files with 980 additions and 1,005 deletions.
13 changes: 7 additions & 6 deletions docs/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ function generateToC() {

generateToC();

// FIXME: import '../src/m3/button.js';
// import '../src/m3/fab.js';
// import '../src/m3/icon-button.js';
// import '../src/m3/icon-button-toggle.js';
// import '../src/m3/checkbox.js';
import '../src/m3/button.js';
import '../src/m3/focus-ring.js';
import '../src/m3/fab.js';
import '../src/m3/icon-button.js';
import '../src/m3/icon-button-toggle.js';
import '../src/m3/checkbox.js';
import '../src/m3/ripple.js';
// import '../src/m3/switch.js';
import '../src/m3/switch.js';
import '../src/m3/tooltip.js';
import './components/demo.js';
9 changes: 7 additions & 2 deletions src/base/attachable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ export const Attachable = <T extends Constructor<LitElement>>(
).querySelector<HTMLElement>(`#${this.htmlFor}`);
}

return this.currentControl || this.parentElement;
return this.currentControl || this.parentNode instanceof ShadowRoot
? ((this.parentNode as ShadowRoot).host as HTMLElement)
: this.parentElement;
}
set $control(control: HTMLElement | null) {
if (control) {
Expand Down Expand Up @@ -72,7 +74,10 @@ export const Attachable = <T extends Constructor<LitElement>>(
this.setAttribute('for', '');
}

handleControlChange(prev: Node | null = null, next: Node | null = null) {}
handleControlChange(
prev: HTMLElement | null = null,
next: HTMLElement | null = null
) {}
}
return AttachableElement as Constructor<AttachableInterface> & T;
};
24 changes: 13 additions & 11 deletions src/base/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import { LitElement } from 'lit';
import { property } from 'lit/decorators.js';

import { InternalsAttached, internals } from './internals-attached.js';
import { FormAssociatedMixin } from './form-mixin.js';
import { FormAssociated } from './form-associated.js';
import { hiddenStyles } from './hidden-styles.js';

import hiddenStyle from './hidden-style.js';

const Base = FormAssociatedMixin(InternalsAttached(LitElement));
const Base = FormAssociated(InternalsAttached(LitElement));

export default class Button extends Base {
constructor() {
super();
this[internals].role = 'button';
this.updateInternals();
}
static styles = [hiddenStyle];
static styles = [hiddenStyles];
connectedCallback() {
super.connectedCallback();
this.addEventListener('keydown', this.#boundKeyDown);
Expand All @@ -26,13 +26,15 @@ export default class Button extends Base {
this.removeEventListener('keyup', this.#boundKeyUp);
this.removeEventListener('click', this.#boundClick);
}
protected updated(changed: Map<string, any>) {
if (changed.has('disabled')) {
this.updateInternals();
}
}
@property({ reflect: true }) type: 'button' | 'submit' | 'reset' = 'button';
@property({ type: Boolean, reflect: true }) disabled = false;

static observedAttributes = ['disabled'];
@property() type: 'button' | 'submit' | 'reset' = 'button';
@property({ type: Boolean }) disabled = false;

update({ first = false, dispatch = false } = {}) {
super.update?.({ first, dispatch });
private updateInternals() {
this.setAttribute('tabindex', this.disabled ? '-1' : '0');
this[internals].ariaDisabled = this.disabled ? 'true' : 'false';
}
Expand Down
72 changes: 30 additions & 42 deletions src/base/checkbox.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,54 @@
import ReactiveElement from '../core/reactive-element.js';
import { sheetsFromCss } from '../core/template.js';
import { property } from '../core/decorators.js';
import { internals } from '../core/symbols.js';
import { LitElement } from 'lit';
import { property } from 'lit/decorators.js';

import FormMixin from './form-mixin.js';

import HiddenStyles from './hidden.css?inline';
import { FormAssociated } from './form-associated.js';
import { InternalsAttached, internals } from './internals-attached.js';
import { hiddenStyles } from './hidden-styles.js';

const PROPERTY_FROM_ARIA_CHECKED = {
true: 'checked',
false: 'unchecked',
mixed: 'indeterminate',
};

const Base = FormMixin(ReactiveElement);
const Base = FormAssociated(InternalsAttached(LitElement));

export default class Checkbox extends Base {
constructor() {
super();
this[internals].role = 'checkbox';

this.checked = this.hasAttribute('checked');
this.indeterminate = this.hasAttribute('indeterminate');
this.updateInternals();
}
get styles() {
return [...sheetsFromCss(HiddenStyles)];
}
static styles = [hiddenStyles];
connectedCallback() {
super.connectedCallback();
this.addEventListener('click', this.#boundClick);
this.addEventListener('keydown', this.#boundKeyDown);
this.addEventListener('keyup', this.#boundKeyUp);
}
disconnectedCallback() {
super.disconnectedCallback?.();
super.disconnectedCallback();
this.removeEventListener('click', this.#boundClick);
this.removeEventListener('keydown', this.#boundKeyDown);
this.removeEventListener('keyup', this.#boundKeyUp);
}
/**
* @param {string} name
* @param {string|null} oldValue
* @param {string|null} newValue
*/
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case 'checked':
case 'indeterminate':
this.update({ dispatch: true });
break;

default:
super.attributeChangedCallback?.(name, oldValue, newValue);
break;
protected updated(changed: Map<string, any>) {
if (
changed.has('checked') ||
changed.has('disabled') ||
changed.has('indeterminate')
) {
this.updateInternals(true);
}
}
static observedAttributes = ['checked', 'indeterminate', 'disabled'];
@property({ type: Boolean }) checked = false;
@property({ type: Boolean }) indeterminate = false;
@property({ type: Boolean }) disabled = false;
@property({ type: Boolean, reflect: true }) disabled = false;

update({ first = false, dispatch = false } = {}) {
super.update?.({ first, dispatch });
private updateInternals(dispatch = false) {
this[internals].states.delete('was-unchecked');
this[internals].states.delete('was-checked');
this[internals].states.delete('was-indeterminate');
Expand All @@ -68,8 +58,8 @@ export default class Checkbox extends Base {
this[internals].ariaChecked = this.indeterminate
? 'mixed'
: this.checked
? 'true'
: 'false';
? 'true'
: 'false';
this[internals].states.delete('unchecked');
this[internals].states.delete('checked');
this[internals].states.delete('indeterminate');
Expand All @@ -95,32 +85,30 @@ export default class Checkbox extends Base {
#boundClick = this.#handleClick.bind(this);
#boundKeyDown = this.#handleKeyDown.bind(this);
#boundKeyUp = this.#handleKeyUp.bind(this);
/** @param {Event} e */
#handleClick(e) {
#handleClick(e: Event) {
e.stopPropagation();
e.preventDefault();
this._toggleStatus();
this.#toggleChecked();
}
/** @param {KeyboardEvent} e */
#handleKeyDown(e) {
#handleKeyDown(e: KeyboardEvent) {
if (e.key === ' ') {
e.preventDefault();
e.stopPropagation();
}
}
/** @param {KeyboardEvent} e */
#handleKeyUp(e) {
#handleKeyUp(e: KeyboardEvent) {
if (e.key === ' ') {
e.preventDefault();
e.stopPropagation();
this._toggleStatus();
this.#toggleChecked();
}
}

_toggleStatus() {
#toggleChecked() {
if (this.disabled) return;

this.checked = !this.checked;
this.indeterminate = false;
this.updateInternals();
}
}
15 changes: 8 additions & 7 deletions src/base/form-mixin.ts → src/base/form-associated.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { LitElement } from 'lit';
import { internals } from './internals-attached';

type Constructor<T> = new (...args: any[]) => T;

export const FormAssociatedMixin = <T extends Constructor<LitElement>>(
export const FormAssociated = <T extends Constructor<LitElement>>(
superClass: T
) => {
class FormAssociatedElement extends superClass {
static formAssociated = true;

get form() {
return this._internals.form;
return this[internals].form;
}
get name() {
return this.getAttribute('name');
Expand All @@ -18,20 +19,20 @@ export const FormAssociatedMixin = <T extends Constructor<LitElement>>(
// return this.localName;
// }
get validity() {
return this._internals.validity;
return this[internals].validity;
}
get validationMessage() {
return this._internals.validationMessage;
return this[internals].validationMessage;
}
get willValidate() {
return this._internals.willValidate;
return this[internals].willValidate;
}

checkValidity() {
return this._internals.checkValidity();
return this[internals].checkValidity();
}
reportValidity() {
return this._internals.reportValidity();
return this[internals].reportValidity();
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/base/hidden-styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { css } from 'lit';

export const hiddenStyles = css`
:host([hidden]) {
display: none;
visibility: hidden;
}
`;
4 changes: 0 additions & 4 deletions src/base/hidden.css

This file was deleted.

Loading

0 comments on commit 66daf66

Please sign in to comment.