From 1e7aff50cf3882f711dd6eb56f08a95ee6f3c084 Mon Sep 17 00:00:00 2001 From: Elizabeth Mitchell Date: Thu, 24 Aug 2023 16:08:54 -0700 Subject: [PATCH] feat(focus,ripple): allow setting `element.control = elementRef` Why? Makes it easier in lit to attach elements in bindings ```html ``` This is needed to support radio, which needs to make the host element interactive. PiperOrigin-RevId: 559899531 --- focus/internal/focus-ring.ts | 3 +++ internal/controller/attachable-controller.ts | 15 +++++++++++---- ripple/internal/ripple.ts | 4 ++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/focus/internal/focus-ring.ts b/focus/internal/focus-ring.ts index e8c494296a..957c634b9f 100644 --- a/focus/internal/focus-ring.ts +++ b/focus/internal/focus-ring.ts @@ -41,6 +41,9 @@ export class FocusRing extends LitElement implements Attachable { get control() { return this.attachableController.control; } + set control(control: HTMLElement|null) { + this.attachableController.control = control; + } private readonly attachableController = new AttachableController(this, this.onControlChange.bind(this)); diff --git a/internal/controller/attachable-controller.ts b/internal/controller/attachable-controller.ts index 99e411eeaa..aeccacdd87 100644 --- a/internal/controller/attachable-controller.ts +++ b/internal/controller/attachable-controller.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {ReactiveController, ReactiveControllerHost, isServer} from 'lit'; +import {isServer, ReactiveController, ReactiveControllerHost} from 'lit'; /** * An element that can be attached to an associated controlling element. @@ -36,15 +36,15 @@ export interface Attachable { htmlFor: string|null; /** - * The element that controls the visibility of the attachable element. It is - * one of: + * Gets or sets the element that controls the visibility of the attachable + * element. It is one of: * * - The control referenced by the `for` attribute. * - The control provided to `element.attach(control)` * - The element's parent. * - `null` if the element is not controlled. */ - readonly control: HTMLElement|null; + control: HTMLElement|null; /** * Attaches the element to an interactive control. @@ -137,6 +137,13 @@ export class AttachableController implements ReactiveController, Attachable { return this.currentControl || this.host.parentElement; } + set control(control: HTMLElement|null) { + if (control) { + this.attach(control); + } else { + this.detach(); + } + } private currentControl: HTMLElement|null = null; diff --git a/ripple/internal/ripple.ts b/ripple/internal/ripple.ts index 14371aa7e6..c5c2261b18 100644 --- a/ripple/internal/ripple.ts +++ b/ripple/internal/ripple.ts @@ -99,6 +99,10 @@ export class Ripple extends LitElement implements Attachable { get control() { return this.attachableController.control; } + set control(control: HTMLElement|null) { + this.attachableController.control = control; + } + @state() private hovered = false; @state() private pressed = false;