diff --git a/packages/calcite-components/src/components/action/action.tsx b/packages/calcite-components/src/components/action/action.tsx index 2b7817d2133..e1befb94e76 100644 --- a/packages/calcite-components/src/components/action/action.tsx +++ b/packages/calcite-components/src/components/action/action.tsx @@ -13,7 +13,12 @@ import { } from "@stencil/core"; import { toAriaBoolean } from "../../utils/dom"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -163,6 +168,7 @@ export class Action // -------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); this.mutationObserver?.observe(this.el, { childList: true, subtree: true }); @@ -180,6 +186,7 @@ export class Action } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); this.mutationObserver?.disconnect(); diff --git a/packages/calcite-components/src/components/block/block.tsx b/packages/calcite-components/src/components/block/block.tsx index 1d73440c9ca..36f7b5de257 100644 --- a/packages/calcite-components/src/components/block/block.tsx +++ b/packages/calcite-components/src/components/block/block.tsx @@ -17,7 +17,12 @@ import { } from "../../utils/conditionalSlot"; import { getSlotted, toAriaBoolean } from "../../utils/dom"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { connectLocalized, disconnectLocalized, LocalizedComponent } from "../../utils/locale"; import { connectMessages, @@ -143,11 +148,13 @@ export class Block connectedCallback(): void { connectConditionalSlotComponent(this); + connectInteractive(this); connectLocalized(this); connectMessages(this); } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); disconnectConditionalSlotComponent(this); diff --git a/packages/calcite-components/src/components/button/button.tsx b/packages/calcite-components/src/components/button/button.tsx index 95acdf08a2a..15f2121e849 100644 --- a/packages/calcite-components/src/components/button/button.tsx +++ b/packages/calcite-components/src/components/button/button.tsx @@ -1,6 +1,11 @@ import { Build, Component, Element, h, Method, Prop, State, VNode, Watch } from "@stencil/core"; import { findAssociatedForm, FormOwner, resetForm, submitForm } from "../../utils/form"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { connectLabel, disconnectLabel, getLabelText, LabelableComponent } from "../../utils/label"; import { componentLoaded, @@ -175,6 +180,7 @@ export class Button //-------------------------------------------------------------------------- async connectedCallback(): Promise { + connectInteractive(this); connectLocalized(this); connectMessages(this); this.hasLoader = this.loading; @@ -185,6 +191,7 @@ export class Button disconnectedCallback(): void { this.mutationObserver?.disconnect(); + disconnectInteractive(this); disconnectLabel(this); disconnectLocalized(this); disconnectMessages(this); diff --git a/packages/calcite-components/src/components/checkbox/checkbox.tsx b/packages/calcite-components/src/components/checkbox/checkbox.tsx index 7aba245cba9..363b4588cda 100644 --- a/packages/calcite-components/src/components/checkbox/checkbox.tsx +++ b/packages/calcite-components/src/components/checkbox/checkbox.tsx @@ -17,7 +17,12 @@ import { HiddenFormInputSlot } from "../../utils/form"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { isActivationKey } from "../../utils/key"; import { connectLabel, disconnectLabel, getLabelText, LabelableComponent } from "../../utils/label"; import { @@ -226,11 +231,13 @@ export class Checkbox connectedCallback(): void { this.guid = this.el.id || `calcite-checkbox-${guid()}`; + connectInteractive(this); connectLabel(this); connectForm(this); } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); } diff --git a/packages/calcite-components/src/components/chip-group/chip-group.tsx b/packages/calcite-components/src/components/chip-group/chip-group.tsx index 527c6805412..1b3f8d3ed84 100644 --- a/packages/calcite-components/src/components/chip-group/chip-group.tsx +++ b/packages/calcite-components/src/components/chip-group/chip-group.tsx @@ -11,7 +11,12 @@ import { Watch } from "@stencil/core"; import { focusElementInGroup, toAriaBoolean } from "../../utils/dom"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { createObserver } from "../../utils/observers"; import { Scale, SelectionMode } from "../interfaces"; import { componentLoaded, setComponentLoaded, setUpLoadableComponent } from "../../utils/loadable"; @@ -93,10 +98,12 @@ export class ChipGroup implements InteractiveComponent { //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); this.mutationObserver?.observe(this.el, { childList: true, subtree: true }); } componentDidRender(): void { + disconnectInteractive(this); updateHostInteraction(this); } diff --git a/packages/calcite-components/src/components/chip/chip.tsx b/packages/calcite-components/src/components/chip/chip.tsx index 2179a6064a6..86345fb2c31 100644 --- a/packages/calcite-components/src/components/chip/chip.tsx +++ b/packages/calcite-components/src/components/chip/chip.tsx @@ -35,7 +35,12 @@ import { T9nComponent, updateMessages } from "../../utils/t9n"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { connectLocalized, disconnectLocalized, LocalizedComponent } from "../../utils/locale"; import { createObserver } from "../../utils/observers"; import { isActivationKey } from "../../utils/key"; @@ -196,6 +201,7 @@ export class Chip connectedCallback(): void { connectConditionalSlotComponent(this); + connectInteractive(this); connectLocalized(this); connectMessages(this); this.setupTextContentObserver(); @@ -211,6 +217,7 @@ export class Chip disconnectedCallback(): void { disconnectConditionalSlotComponent(this); + disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); } diff --git a/packages/calcite-components/src/components/color-picker/color-picker.tsx b/packages/calcite-components/src/components/color-picker/color-picker.tsx index 63a5be34f89..fdbe88c8364 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.tsx +++ b/packages/calcite-components/src/components/color-picker/color-picker.tsx @@ -43,7 +43,12 @@ import { toNonAlphaMode } from "./utils"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { isActivationKey } from "../../utils/key"; import { componentLoaded, @@ -687,6 +692,7 @@ export class ColorPicker } connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); } @@ -698,6 +704,7 @@ export class ColorPicker disconnectedCallback(): void { document.removeEventListener("pointermove", this.globalPointerMoveHandler); document.removeEventListener("pointerup", this.globalPointerUpHandler); + disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); } diff --git a/packages/calcite-components/src/components/combobox-item/combobox-item.tsx b/packages/calcite-components/src/components/combobox-item/combobox-item.tsx index 684ce368714..698bad70a0b 100644 --- a/packages/calcite-components/src/components/combobox-item/combobox-item.tsx +++ b/packages/calcite-components/src/components/combobox-item/combobox-item.tsx @@ -16,7 +16,12 @@ import { } from "../../utils/conditionalSlot"; import { getElementProp, getSlotted } from "../../utils/dom"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { ComboboxChildElement } from "../combobox/interfaces"; import { getAncestors, getDepth } from "../combobox/utils"; import { Scale } from "../interfaces"; @@ -99,10 +104,12 @@ export class ComboboxItem implements ConditionalSlotComponent, InteractiveCompon this.ancestors = getAncestors(this.el); this.scale = getElementProp(this.el, "scale", this.scale); connectConditionalSlotComponent(this); + connectInteractive(this); } disconnectedCallback(): void { disconnectConditionalSlotComponent(this); + disconnectInteractive(this); } componentDidRender(): void { diff --git a/packages/calcite-components/src/components/combobox/combobox.tsx b/packages/calcite-components/src/components/combobox/combobox.tsx index e16bd81874b..827a8bb3074 100644 --- a/packages/calcite-components/src/components/combobox/combobox.tsx +++ b/packages/calcite-components/src/components/combobox/combobox.tsx @@ -37,7 +37,12 @@ import { submitForm } from "../../utils/form"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { connectLabel, disconnectLabel, getLabelText, LabelableComponent } from "../../utils/label"; import { componentLoaded, @@ -387,6 +392,7 @@ export class Combobox // -------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); this.internalValueChangeFlag = true; @@ -427,6 +433,7 @@ export class Combobox disconnectedCallback(): void { this.mutationObserver?.disconnect(); this.resizeObserver?.disconnect(); + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); disconnectFloatingUI(this, this.referenceEl, this.floatingEl); diff --git a/packages/calcite-components/src/components/date-picker-day/date-picker-day.tsx b/packages/calcite-components/src/components/date-picker-day/date-picker-day.tsx index 0046d241000..792fd25bc93 100644 --- a/packages/calcite-components/src/components/date-picker-day/date-picker-day.tsx +++ b/packages/calcite-components/src/components/date-picker-day/date-picker-day.tsx @@ -12,7 +12,12 @@ import { import { dateToISO } from "../../utils/date"; import { closestElementCrossShadowBoundary, getElementDir, toAriaBoolean } from "../../utils/dom"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { isActivationKey } from "../../utils/key"; import { numberStringFormatter } from "../../utils/locale"; import { CSS_UTILITY } from "../../utils/resources"; @@ -185,10 +190,18 @@ export class DatePickerDay implements InteractiveComponent { ); } + connectedCallback(): void { + connectInteractive(this); + } + componentDidRender(): void { updateHostInteraction(this, this.isTabbable); } + disconnectedCallback(): void { + disconnectInteractive(this); + } + isTabbable(): boolean { return this.active; } diff --git a/packages/calcite-components/src/components/dropdown/dropdown.tsx b/packages/calcite-components/src/components/dropdown/dropdown.tsx index 2be288fe1ec..d4d14e23184 100644 --- a/packages/calcite-components/src/components/dropdown/dropdown.tsx +++ b/packages/calcite-components/src/components/dropdown/dropdown.tsx @@ -32,7 +32,12 @@ import { reposition } from "../../utils/floating-ui"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { isActivationKey } from "../../utils/key"; import { componentLoaded, @@ -212,6 +217,7 @@ export class Dropdown if (this.open) { this.openHandler(this.open); } + connectInteractive(this); connectOpenCloseComponent(this); } @@ -230,8 +236,9 @@ export class Dropdown disconnectedCallback(): void { this.mutationObserver?.disconnect(); - disconnectFloatingUI(this, this.referenceEl, this.floatingEl); this.resizeObserver?.disconnect(); + disconnectInteractive(this); + disconnectFloatingUI(this, this.referenceEl, this.floatingEl); disconnectOpenCloseComponent(this); } diff --git a/packages/calcite-components/src/components/fab/fab.tsx b/packages/calcite-components/src/components/fab/fab.tsx index c29adfcc020..586992f81dd 100755 --- a/packages/calcite-components/src/components/fab/fab.tsx +++ b/packages/calcite-components/src/components/fab/fab.tsx @@ -1,6 +1,11 @@ import { Component, Element, h, Method, Prop, VNode } from "@stencil/core"; import { focusElement } from "../../utils/dom"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -89,6 +94,10 @@ export class Fab implements InteractiveComponent, LoadableComponent { // //-------------------------------------------------------------------------- + connectedCallback(): void { + connectInteractive(this); + } + componentWillLoad(): void { setUpLoadableComponent(this); } @@ -101,6 +110,10 @@ export class Fab implements InteractiveComponent, LoadableComponent { updateHostInteraction(this); } + disconnectedCallback(): void { + disconnectInteractive(this); + } + // -------------------------------------------------------------------------- // // Methods diff --git a/packages/calcite-components/src/components/filter/filter.tsx b/packages/calcite-components/src/components/filter/filter.tsx index 882c55b1742..c57fe268d59 100644 --- a/packages/calcite-components/src/components/filter/filter.tsx +++ b/packages/calcite-components/src/components/filter/filter.tsx @@ -13,7 +13,12 @@ import { } from "@stencil/core"; import { debounce } from "lodash-es"; import { filter } from "../../utils/filter"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -158,6 +163,7 @@ export class Filter } connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); } @@ -167,6 +173,7 @@ export class Filter } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); } diff --git a/packages/calcite-components/src/components/flow-item/flow-item.tsx b/packages/calcite-components/src/components/flow-item/flow-item.tsx index a9be13ef72d..255ee9e076c 100644 --- a/packages/calcite-components/src/components/flow-item/flow-item.tsx +++ b/packages/calcite-components/src/components/flow-item/flow-item.tsx @@ -12,7 +12,12 @@ import { Watch } from "@stencil/core"; import { getElementDir } from "../../utils/dom"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -130,6 +135,7 @@ export class FlowItem //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); } @@ -144,6 +150,7 @@ export class FlowItem } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); } diff --git a/packages/calcite-components/src/components/inline-editable/inline-editable.tsx b/packages/calcite-components/src/components/inline-editable/inline-editable.tsx index c71762554ed..ffb84e5e12e 100644 --- a/packages/calcite-components/src/components/inline-editable/inline-editable.tsx +++ b/packages/calcite-components/src/components/inline-editable/inline-editable.tsx @@ -12,7 +12,12 @@ import { Watch } from "@stencil/core"; import { getSlotted } from "../../utils/dom"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { connectLabel, disconnectLabel, getLabelText, LabelableComponent } from "../../utils/label"; import { componentLoaded, @@ -131,6 +136,7 @@ export class InlineEditable //-------------------------------------------------------------------------- connectedCallback() { + connectInteractive(this); connectLabel(this); connectLocalized(this); connectMessages(this); @@ -148,6 +154,7 @@ export class InlineEditable } disconnectedCallback() { + disconnectInteractive(this); disconnectLabel(this); disconnectLocalized(this); disconnectMessages(this); diff --git a/packages/calcite-components/src/components/input-date-picker/input-date-picker.tsx b/packages/calcite-components/src/components/input-date-picker/input-date-picker.tsx index 63bc29aa81d..9ee4ae2b328 100644 --- a/packages/calcite-components/src/components/input-date-picker/input-date-picker.tsx +++ b/packages/calcite-components/src/components/input-date-picker/input-date-picker.tsx @@ -41,7 +41,12 @@ import { HiddenFormInputSlot, submitForm } from "../../utils/form"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { numberKeys } from "../../utils/key"; import { connectLabel, disconnectLabel, LabelableComponent } from "../../utils/label"; import { @@ -433,6 +438,7 @@ export class InputDatePicker // -------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); const { open } = this; @@ -488,6 +494,7 @@ export class InputDatePicker disconnectedCallback(): void { deactivateFocusTrap(this); + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); disconnectFloatingUI(this, this.referenceEl, this.floatingEl); diff --git a/packages/calcite-components/src/components/input-number/input-number.tsx b/packages/calcite-components/src/components/input-number/input-number.tsx index 231564451fa..8bef5603a7e 100644 --- a/packages/calcite-components/src/components/input-number/input-number.tsx +++ b/packages/calcite-components/src/components/input-number/input-number.tsx @@ -26,7 +26,12 @@ import { HiddenFormInputSlot, submitForm } from "../../utils/form"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { numberKeys } from "../../utils/key"; import { connectLabel, disconnectLabel, getLabelText, LabelableComponent } from "../../utils/label"; import { @@ -402,6 +407,7 @@ export class InputNumber //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); this.inlineEditableEl = this.el.closest("calcite-inline-editable"); @@ -429,6 +435,7 @@ export class InputNumber } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); disconnectLocalized(this); diff --git a/packages/calcite-components/src/components/input-text/input-text.tsx b/packages/calcite-components/src/components/input-text/input-text.tsx index d5dbcbab50c..fb87486e378 100644 --- a/packages/calcite-components/src/components/input-text/input-text.tsx +++ b/packages/calcite-components/src/components/input-text/input-text.tsx @@ -19,7 +19,12 @@ import { HiddenFormInputSlot, submitForm } from "../../utils/form"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { connectLabel, disconnectLabel, getLabelText, LabelableComponent } from "../../utils/label"; import { componentLoaded, @@ -312,6 +317,7 @@ export class InputText //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); @@ -330,6 +336,7 @@ export class InputText } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); disconnectLocalized(this); diff --git a/packages/calcite-components/src/components/input-time-picker/input-time-picker.tsx b/packages/calcite-components/src/components/input-time-picker/input-time-picker.tsx index a70d7fa9964..20a1eea3017 100644 --- a/packages/calcite-components/src/components/input-time-picker/input-time-picker.tsx +++ b/packages/calcite-components/src/components/input-time-picker/input-time-picker.tsx @@ -20,7 +20,12 @@ import { submitForm } from "../../utils/form"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { numberKeys } from "../../utils/key"; import { connectLabel, disconnectLabel, getLabelText, LabelableComponent } from "../../utils/label"; import { @@ -576,7 +581,7 @@ export class InputTimePicker private getExtendedLocaleConfig( locale: string - ): Parameters<(typeof dayjs)["updateLocale"]>[1] | undefined { + ): Parameters[1] | undefined { if (locale === "ar") { return { meridiem: (hour) => (hour > 12 ? "م" : "ص"), @@ -752,6 +757,7 @@ export class InputTimePicker //-------------------------------------------------------------------------- connectedCallback() { + connectInteractive(this); connectLocalized(this); if (isValidTime(this.value)) { @@ -785,6 +791,7 @@ export class InputTimePicker } disconnectedCallback() { + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); disconnectLocalized(this); diff --git a/packages/calcite-components/src/components/input/input.tsx b/packages/calcite-components/src/components/input/input.tsx index 033b9ca833a..97b4580f616 100644 --- a/packages/calcite-components/src/components/input/input.tsx +++ b/packages/calcite-components/src/components/input/input.tsx @@ -26,7 +26,12 @@ import { HiddenFormInputSlot, submitForm } from "../../utils/form"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { numberKeys } from "../../utils/key"; import { connectLabel, disconnectLabel, getLabelText, LabelableComponent } from "../../utils/label"; import { @@ -466,6 +471,7 @@ export class Input //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); @@ -494,6 +500,7 @@ export class Input } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); disconnectLocalized(this); diff --git a/packages/calcite-components/src/components/link/link.tsx b/packages/calcite-components/src/components/link/link.tsx index 8a84d467a2f..2d1201e8f93 100644 --- a/packages/calcite-components/src/components/link/link.tsx +++ b/packages/calcite-components/src/components/link/link.tsx @@ -1,6 +1,11 @@ import { Component, Element, h, Host, Listen, Method, Prop, VNode } from "@stencil/core"; import { focusElement, getElementDir } from "../../utils/dom"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -69,6 +74,10 @@ export class Link implements InteractiveComponent, LoadableComponent { // //-------------------------------------------------------------------------- + connectedCallback(): void { + connectInteractive(this); + } + componentWillLoad(): void { setUpLoadableComponent(this); } @@ -81,6 +90,10 @@ export class Link implements InteractiveComponent, LoadableComponent { updateHostInteraction(this); } + disconnectedCallback(): void { + disconnectInteractive(this); + } + render(): VNode { const { download, el } = this; const dir = getElementDir(el); diff --git a/packages/calcite-components/src/components/list-item-group/list-item-group.tsx b/packages/calcite-components/src/components/list-item-group/list-item-group.tsx index fb68acff73e..851b8819d93 100644 --- a/packages/calcite-components/src/components/list-item-group/list-item-group.tsx +++ b/packages/calcite-components/src/components/list-item-group/list-item-group.tsx @@ -1,5 +1,10 @@ import { Component, Element, h, Host, Prop, State, VNode } from "@stencil/core"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { MAX_COLUMNS } from "../list-item/resources"; import { getDepth } from "../list-item/utils"; import { CSS } from "./resources"; @@ -38,12 +43,17 @@ export class ListItemGroup implements InteractiveComponent { connectedCallback(): void { const { el } = this; this.visualLevel = getDepth(el, true); + connectInteractive(this); } componentDidRender(): void { updateHostInteraction(this); } + disconnectedCallback(): void { + disconnectInteractive(this); + } + // -------------------------------------------------------------------------- // // Private Properties diff --git a/packages/calcite-components/src/components/list-item/list-item.tsx b/packages/calcite-components/src/components/list-item/list-item.tsx index c5df924156f..8a88d94b3e3 100644 --- a/packages/calcite-components/src/components/list-item/list-item.tsx +++ b/packages/calcite-components/src/components/list-item/list-item.tsx @@ -12,7 +12,12 @@ import { Watch } from "@stencil/core"; import { getElementDir, slotChangeHasAssignedElement, toAriaBoolean } from "../../utils/dom"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { SelectionMode } from "../interfaces"; import { SelectionAppearance } from "../list/resources"; import { CSS, ICONS, SLOTS } from "./resources"; @@ -251,6 +256,7 @@ export class ListItem actionsEndEl: HTMLTableCellElement; connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); const { el } = this; @@ -274,6 +280,7 @@ export class ListItem } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); } diff --git a/packages/calcite-components/src/components/list/list.tsx b/packages/calcite-components/src/components/list/list.tsx index 490b777d9a0..fca1e5dae50 100755 --- a/packages/calcite-components/src/components/list/list.tsx +++ b/packages/calcite-components/src/components/list/list.tsx @@ -13,7 +13,12 @@ import { } from "@stencil/core"; import { debounce } from "lodash-es"; import { toAriaBoolean } from "../../utils/dom"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { createObserver } from "../../utils/observers"; import { SelectionMode } from "../interfaces"; import { ItemData } from "../list-item/interfaces"; @@ -203,10 +208,12 @@ export class List implements InteractiveComponent, LoadableComponent { connectedCallback(): void { this.mutationObserver?.observe(this.el, { childList: true, subtree: true }); this.updateListItems(); + connectInteractive(this); } disconnectedCallback(): void { this.mutationObserver?.disconnect(); + disconnectInteractive(this); } componentWillLoad(): void { diff --git a/packages/calcite-components/src/components/panel/panel.tsx b/packages/calcite-components/src/components/panel/panel.tsx index 89e2270e5fd..cbc61fcfe9c 100644 --- a/packages/calcite-components/src/components/panel/panel.tsx +++ b/packages/calcite-components/src/components/panel/panel.tsx @@ -12,7 +12,12 @@ import { Watch } from "@stencil/core"; import { focusFirstTabbable, slotChangeGetAssignedElements, toAriaBoolean } from "../../utils/dom"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -120,6 +125,7 @@ export class Panel //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); } @@ -138,6 +144,7 @@ export class Panel } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); this.resizeObserver?.disconnect(); diff --git a/packages/calcite-components/src/components/pick-list-item/pick-list-item.tsx b/packages/calcite-components/src/components/pick-list-item/pick-list-item.tsx index fc582f7ae8a..1a4aa8b9971 100644 --- a/packages/calcite-components/src/components/pick-list-item/pick-list-item.tsx +++ b/packages/calcite-components/src/components/pick-list-item/pick-list-item.tsx @@ -17,7 +17,12 @@ import { disconnectConditionalSlotComponent } from "../../utils/conditionalSlot"; import { getSlotted, toAriaBoolean } from "../../utils/dom"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -191,6 +196,7 @@ export class PickListItem // -------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); connectConditionalSlotComponent(this); @@ -206,6 +212,7 @@ export class PickListItem } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); disconnectConditionalSlotComponent(this); diff --git a/packages/calcite-components/src/components/pick-list/pick-list.tsx b/packages/calcite-components/src/components/pick-list/pick-list.tsx index 823d625a3d3..3d54fc60a99 100644 --- a/packages/calcite-components/src/components/pick-list/pick-list.tsx +++ b/packages/calcite-components/src/components/pick-list/pick-list.tsx @@ -10,7 +10,12 @@ import { State, VNode } from "@stencil/core"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -156,10 +161,12 @@ export class PickList< connectedCallback(): void { initialize.call(this); initializeObserver.call(this); + connectInteractive(this); } disconnectedCallback(): void { cleanUpObserver.call(this); + disconnectInteractive(this); } componentWillLoad(): void { diff --git a/packages/calcite-components/src/components/radio-button/radio-button.tsx b/packages/calcite-components/src/components/radio-button/radio-button.tsx index beef04e3f75..def598595a6 100644 --- a/packages/calcite-components/src/components/radio-button/radio-button.tsx +++ b/packages/calcite-components/src/components/radio-button/radio-button.tsx @@ -20,7 +20,12 @@ import { HiddenFormInputSlot } from "../../utils/form"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { connectLabel, disconnectLabel, getLabelText, LabelableComponent } from "../../utils/label"; import { componentLoaded, @@ -438,6 +443,7 @@ export class RadioButton if (this.name) { this.checkLastRadioButton(); } + connectInteractive(this); connectLabel(this); connectForm(this); } @@ -455,6 +461,7 @@ export class RadioButton } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); } diff --git a/packages/calcite-components/src/components/rating/rating.tsx b/packages/calcite-components/src/components/rating/rating.tsx index a6de56b96bb..f100fa59be3 100644 --- a/packages/calcite-components/src/components/rating/rating.tsx +++ b/packages/calcite-components/src/components/rating/rating.tsx @@ -12,7 +12,12 @@ import { } from "@stencil/core"; import { connectForm, disconnectForm, FormComponent, HiddenFormInputSlot } from "../../utils/form"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { connectLabel, disconnectLabel, LabelableComponent } from "../../utils/label"; import { componentLoaded, @@ -174,6 +179,7 @@ export class Rating //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); connectLabel(this); @@ -229,6 +235,7 @@ export class Rating } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); disconnectLabel(this); diff --git a/packages/calcite-components/src/components/segmented-control/segmented-control.tsx b/packages/calcite-components/src/components/segmented-control/segmented-control.tsx index b3e6f118343..0c287517db0 100644 --- a/packages/calcite-components/src/components/segmented-control/segmented-control.tsx +++ b/packages/calcite-components/src/components/segmented-control/segmented-control.tsx @@ -21,7 +21,12 @@ import { FormComponent, HiddenFormInputSlot } from "../../utils/form"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { connectLabel, disconnectLabel, LabelableComponent } from "../../utils/label"; import { componentLoaded, @@ -154,11 +159,13 @@ export class SegmentedControl } connectedCallback(): void { + connectInteractive(this); connectLabel(this); connectForm(this); } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); } diff --git a/packages/calcite-components/src/components/select/select.tsx b/packages/calcite-components/src/components/select/select.tsx index 30b544e3503..f9df6bfebef 100644 --- a/packages/calcite-components/src/components/select/select.tsx +++ b/packages/calcite-components/src/components/select/select.tsx @@ -19,7 +19,12 @@ import { FormComponent, HiddenFormInputSlot } from "../../utils/form"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { connectLabel, disconnectLabel, LabelableComponent, getLabelText } from "../../utils/label"; import { componentLoaded, @@ -159,12 +164,14 @@ export class Select childList: true }); + connectInteractive(this); connectLabel(this); connectForm(this); } disconnectedCallback(): void { this.mutationObserver?.disconnect(); + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); } diff --git a/packages/calcite-components/src/components/slider/slider.tsx b/packages/calcite-components/src/components/slider/slider.tsx index ec2afbeadf7..7a42b1ad94c 100644 --- a/packages/calcite-components/src/components/slider/slider.tsx +++ b/packages/calcite-components/src/components/slider/slider.tsx @@ -22,7 +22,12 @@ import { FormComponent, HiddenFormInputSlot } from "../../utils/form"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { isActivationKey } from "../../utils/key"; import { connectLabel, disconnectLabel, LabelableComponent, getLabelText } from "../../utils/label"; import { @@ -203,6 +208,7 @@ export class Slider //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); this.setMinMaxFromValue(); this.setValueFromMinMax(); @@ -211,6 +217,7 @@ export class Slider } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); disconnectLocalized(this); diff --git a/packages/calcite-components/src/components/sortable-list/sortable-list.tsx b/packages/calcite-components/src/components/sortable-list/sortable-list.tsx index 6eb6ace2e11..5418296434f 100644 --- a/packages/calcite-components/src/components/sortable-list/sortable-list.tsx +++ b/packages/calcite-components/src/components/sortable-list/sortable-list.tsx @@ -1,6 +1,11 @@ import { Component, Element, Event, EventEmitter, h, Listen, Prop, VNode } from "@stencil/core"; import Sortable from "sortablejs"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { createObserver } from "../../utils/observers"; import { HandleNudge } from "../handle/interfaces"; import { Layout } from "../interfaces"; @@ -86,9 +91,11 @@ export class SortableList implements InteractiveComponent, SortableComponent { connectedCallback(): void { this.setUpSorting(); this.beginObserving(); + connectInteractive(this); } disconnectedCallback(): void { + disconnectInteractive(this); disconnectSortableComponent(this); this.endObserving(); } diff --git a/packages/calcite-components/src/components/split-button/split-button.tsx b/packages/calcite-components/src/components/split-button/split-button.tsx index ba7355bca25..7f45aee0183 100644 --- a/packages/calcite-components/src/components/split-button/split-button.tsx +++ b/packages/calcite-components/src/components/split-button/split-button.tsx @@ -10,7 +10,12 @@ import { Watch } from "@stencil/core"; import { OverlayPositioning } from "../../utils/floating-ui"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -141,6 +146,10 @@ export class SplitButton implements InteractiveComponent, LoadableComponent { // //-------------------------------------------------------------------------- + connectedCallback(): void { + connectInteractive(this); + } + componentWillLoad(): void { setUpLoadableComponent(this); } @@ -153,6 +162,10 @@ export class SplitButton implements InteractiveComponent, LoadableComponent { updateHostInteraction(this); } + disconnectedCallback(): void { + disconnectInteractive(this); + } + render(): VNode { const widthClasses = { [CSS.container]: true, diff --git a/packages/calcite-components/src/components/stepper-item/stepper-item.tsx b/packages/calcite-components/src/components/stepper-item/stepper-item.tsx index 75547153641..52fa081b89c 100644 --- a/packages/calcite-components/src/components/stepper-item/stepper-item.tsx +++ b/packages/calcite-components/src/components/stepper-item/stepper-item.tsx @@ -14,7 +14,12 @@ import { } from "@stencil/core"; import { getElementProp, toAriaBoolean } from "../../utils/dom"; import { Layout, Scale } from "../interfaces"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { StepperItemChangeEventDetail, StepperItemEventDetail, @@ -172,6 +177,7 @@ export class StepperItem implements InteractiveComponent, LocalizedComponent, Lo //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); } @@ -199,6 +205,7 @@ export class StepperItem implements InteractiveComponent, LocalizedComponent, Lo } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLocalized(this); } diff --git a/packages/calcite-components/src/components/switch/switch.tsx b/packages/calcite-components/src/components/switch/switch.tsx index 36c7837a684..44e934037dd 100644 --- a/packages/calcite-components/src/components/switch/switch.tsx +++ b/packages/calcite-components/src/components/switch/switch.tsx @@ -16,7 +16,12 @@ import { disconnectForm, HiddenFormInputSlot } from "../../utils/form"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { isActivationKey } from "../../utils/key"; import { connectLabel, disconnectLabel, getLabelText, LabelableComponent } from "../../utils/label"; import { @@ -168,6 +173,7 @@ export class Switch //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLabel(this); connectForm(this); } @@ -181,6 +187,7 @@ export class Switch } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); } diff --git a/packages/calcite-components/src/components/tab-title/tab-title.tsx b/packages/calcite-components/src/components/tab-title/tab-title.tsx index 6244ee52cdb..c78f8b732f4 100644 --- a/packages/calcite-components/src/components/tab-title/tab-title.tsx +++ b/packages/calcite-components/src/components/tab-title/tab-title.tsx @@ -15,7 +15,12 @@ import { } from "@stencil/core"; import { getElementDir, getElementProp, toAriaBoolean, nodeListToArray } from "../../utils/dom"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { createObserver } from "../../utils/observers"; import { FlipContext, Scale } from "../interfaces"; import { TabChangeEventDetail, TabCloseEventDetail } from "../tab/interfaces"; @@ -144,6 +149,7 @@ export class TabTitle implements InteractiveComponent, LocalizedComponent, T9nCo //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); this.setupTextContentObserver(); @@ -160,6 +166,7 @@ export class TabTitle implements InteractiveComponent, LocalizedComponent, T9nCo }) ); this.resizeObserver?.disconnect(); + disconnectInteractive(this); disconnectLocalized(this); disconnectMessages(this); } diff --git a/packages/calcite-components/src/components/text-area/text-area.tsx b/packages/calcite-components/src/components/text-area/text-area.tsx index 3236911e4b3..aaabaa04026 100644 --- a/packages/calcite-components/src/components/text-area/text-area.tsx +++ b/packages/calcite-components/src/components/text-area/text-area.tsx @@ -38,7 +38,12 @@ import { } from "../../utils/t9n"; import { TextAreaMessages } from "./assets/text-area/t9n"; import { throttle } from "lodash-es"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; /** * @slot - A slot for adding text. @@ -218,6 +223,7 @@ export class TextArea //-------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLabel(this); connectForm(this); connectLocalized(this); @@ -239,6 +245,7 @@ export class TextArea } disconnectedCallback(): void { + disconnectInteractive(this); disconnectLabel(this); disconnectForm(this); disconnectLocalized(this); diff --git a/packages/calcite-components/src/components/tile-select-group/tile-select-group.tsx b/packages/calcite-components/src/components/tile-select-group/tile-select-group.tsx index 23d21620f40..f2e8664004b 100644 --- a/packages/calcite-components/src/components/tile-select-group/tile-select-group.tsx +++ b/packages/calcite-components/src/components/tile-select-group/tile-select-group.tsx @@ -1,5 +1,10 @@ import { Component, Element, h, Prop, VNode } from "@stencil/core"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { TileSelectGroupLayout } from "./interfaces"; /** @@ -41,10 +46,18 @@ export class TileSelectGroup implements InteractiveComponent { // //-------------------------------------------------------------------------- + connectedCallback(): void { + connectInteractive(this); + } + componentDidRender(): void { updateHostInteraction(this); } + disconnectedCallback(): void { + disconnectInteractive(this); + } + render(): VNode { return ; } diff --git a/packages/calcite-components/src/components/tile-select/tile-select.tsx b/packages/calcite-components/src/components/tile-select/tile-select.tsx index 46e089b7083..98336c56b59 100644 --- a/packages/calcite-components/src/components/tile-select/tile-select.tsx +++ b/packages/calcite-components/src/components/tile-select/tile-select.tsx @@ -12,7 +12,12 @@ import { Watch } from "@stencil/core"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -249,6 +254,7 @@ export class TileSelect implements InteractiveComponent, LoadableComponent { connectedCallback(): void { this.renderInput(); + connectInteractive(this); } componentWillLoad(): void { @@ -261,6 +267,7 @@ export class TileSelect implements InteractiveComponent, LoadableComponent { disconnectedCallback(): void { this.input.parentNode.removeChild(this.input); + disconnectInteractive(this); } componentDidRender(): void { diff --git a/packages/calcite-components/src/components/tile/tile.tsx b/packages/calcite-components/src/components/tile/tile.tsx index a116b65240f..f04646e9ffe 100644 --- a/packages/calcite-components/src/components/tile/tile.tsx +++ b/packages/calcite-components/src/components/tile/tile.tsx @@ -5,7 +5,12 @@ import { disconnectConditionalSlotComponent } from "../../utils/conditionalSlot"; import { getSlotted } from "../../utils/dom"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { SLOTS } from "./resources"; /** @@ -84,10 +89,12 @@ export class Tile implements ConditionalSlotComponent, InteractiveComponent { connectedCallback(): void { connectConditionalSlotComponent(this); + connectInteractive(this); } disconnectedCallback(): void { disconnectConditionalSlotComponent(this); + disconnectInteractive(this); } componentDidRender(): void { diff --git a/packages/calcite-components/src/components/tree-item/tree-item.tsx b/packages/calcite-components/src/components/tree-item/tree-item.tsx index 92b170db5eb..3f6ed880c4f 100644 --- a/packages/calcite-components/src/components/tree-item/tree-item.tsx +++ b/packages/calcite-components/src/components/tree-item/tree-item.tsx @@ -24,7 +24,12 @@ import { connectConditionalSlotComponent, disconnectConditionalSlotComponent } from "../../utils/conditionalSlot"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { onToggleOpenCloseComponent, OpenCloseComponent } from "../../utils/openCloseComponent"; import { CSS_UTILITY } from "../../utils/resources"; import { FlipContext, Scale, SelectionMode } from "../interfaces"; @@ -174,10 +179,12 @@ export class TreeItem this.updateParentIsExpanded(this.parentTreeItem, expanded); } connectConditionalSlotComponent(this); + connectInteractive(this); } disconnectedCallback(): void { disconnectConditionalSlotComponent(this); + disconnectInteractive(this); } componentWillRender(): void { diff --git a/packages/calcite-components/src/components/value-list-item/value-list-item.tsx b/packages/calcite-components/src/components/value-list-item/value-list-item.tsx index f455c0a174e..e97bb06f2cd 100644 --- a/packages/calcite-components/src/components/value-list-item/value-list-item.tsx +++ b/packages/calcite-components/src/components/value-list-item/value-list-item.tsx @@ -17,7 +17,12 @@ import { } from "../../utils/conditionalSlot"; import { getSlotted } from "../../utils/dom"; import { guid } from "../../utils/guid"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -130,10 +135,12 @@ export class ValueListItem connectedCallback(): void { connectConditionalSlotComponent(this); + connectInteractive(this); } disconnectedCallback(): void { disconnectConditionalSlotComponent(this); + disconnectInteractive(this); } componentWillLoad(): void { diff --git a/packages/calcite-components/src/components/value-list/value-list.tsx b/packages/calcite-components/src/components/value-list/value-list.tsx index 18ee29427a8..19f4cbdbd06 100644 --- a/packages/calcite-components/src/components/value-list/value-list.tsx +++ b/packages/calcite-components/src/components/value-list/value-list.tsx @@ -12,7 +12,12 @@ import { Watch } from "@stencil/core"; import Sortable from "sortablejs"; -import { InteractiveComponent, updateHostInteraction } from "../../utils/interactive"; +import { + connectInteractive, + disconnectInteractive, + InteractiveComponent, + updateHostInteraction +} from "../../utils/interactive"; import { componentLoaded, LoadableComponent, @@ -220,6 +225,7 @@ export class ValueList< // -------------------------------------------------------------------------- connectedCallback(): void { + connectInteractive(this); connectLocalized(this); connectMessages(this); initialize.call(this); @@ -242,6 +248,7 @@ export class ValueList< } disconnectedCallback(): void { + disconnectInteractive(this); disconnectSortableComponent(this); disconnectLocalized(this); disconnectMessages(this); diff --git a/packages/calcite-components/src/utils/browser.ts b/packages/calcite-components/src/utils/browser.ts new file mode 100644 index 00000000000..6bb779dbc05 --- /dev/null +++ b/packages/calcite-components/src/utils/browser.ts @@ -0,0 +1,17 @@ +interface NavigatorUAData { + brands: Array<{ brand: string; version: string }>; + mobile: boolean; + platform: string; +} + +export function getUserAgentData(): NavigatorUAData | undefined { + return (navigator as any).userAgentData; +} + +export function getUserAgentString(): string { + const uaData = getUserAgentData(); + + return uaData?.brands + ? uaData.brands.map(({ brand, version }) => `${brand}/${version}`).join(" ") + : navigator.userAgent; +} diff --git a/packages/calcite-components/src/utils/floating-ui.ts b/packages/calcite-components/src/utils/floating-ui.ts index 9e3267be703..9a66171a50e 100644 --- a/packages/calcite-components/src/utils/floating-ui.ts +++ b/packages/calcite-components/src/utils/floating-ui.ts @@ -19,49 +19,32 @@ import { debounce } from "lodash-es"; import { config } from "./config"; import { getElementDir } from "./dom"; import { Layout } from "../components/interfaces"; +import { getUserAgentData, getUserAgentString } from "./browser"; const floatingUIBrowserCheck = patchFloatingUiForNonChromiumBrowsers(); -async function patchFloatingUiForNonChromiumBrowsers(): Promise { - interface NavigatorUAData { - brands: Array<{ brand: string; version: string }>; - mobile: boolean; - platform: string; - } - - function getUAData(): NavigatorUAData | undefined { - return (navigator as any).userAgentData; - } +export function isChrome109OrAbove(): boolean { + const uaData = getUserAgentData(); - function getUAString(): string { - const uaData = getUAData(); - - return uaData?.brands - ? uaData.brands.map(({ brand, version }) => `${brand}/${version}`).join(" ") - : navigator.userAgent; + if (uaData?.brands) { + return !!uaData.brands.find( + ({ brand, version }) => (brand === "Google Chrome" || brand === "Chromium") && Number(version) >= 109 + ); } - function isChrome109OrAbove(): boolean { - const uaData = getUAData(); + return !!navigator.userAgent.split(" ").find((ua) => { + const [browser, version] = ua.split("/"); - if (uaData?.brands) { - return !!uaData.brands.find( - ({ brand, version }) => (brand === "Google Chrome" || brand === "Chromium") && Number(version) >= 109 - ); - } - - return !!navigator.userAgent.split(" ").find((ua) => { - const [browser, version] = ua.split("/"); - - return browser === "Chrome" && parseInt(version) >= 109; - }); - } + return browser === "Chrome" && parseInt(version) >= 109; + }); +} +async function patchFloatingUiForNonChromiumBrowsers(): Promise { if ( Build.isBrowser && config.floatingUINonChromiumPositioningFix && // ⚠️ browser-sniffing is not a best practice and should be avoided ⚠️ - (/firefox|safari/i.test(getUAString()) || isChrome109OrAbove()) + (/firefox|safari/i.test(getUserAgentString()) || isChrome109OrAbove()) ) { const { offsetParent } = await import("composed-offset-position"); diff --git a/packages/calcite-components/src/utils/interactive.ts b/packages/calcite-components/src/utils/interactive.ts index 8734cefb340..bc2d4c29695 100644 --- a/packages/calcite-components/src/utils/interactive.ts +++ b/packages/calcite-components/src/utils/interactive.ts @@ -1,3 +1,5 @@ +import { getUserAgentString } from "./browser"; + export interface InteractiveComponent { /** * The host element. @@ -24,6 +26,15 @@ type HostIsTabbablePredicate = () => boolean; */ export type InteractiveHTMLElement = HTMLElement & Pick; +// ⚠️ browser-sniffing is not a best practice and should be avoided ⚠️ +const isFirefox = /firefox/i.test(getUserAgentString()); + +type ParentElement = T | null; + +const interactiveElementToParent: WeakMap | null = isFirefox + ? new WeakMap() + : null; + function interceptedClick(): void { const { disabled } = this as InteractiveHTMLElement; @@ -33,13 +44,27 @@ function interceptedClick(): void { } function onPointerDown(event: PointerEvent): void { - // prevent click from moving focus on host - event.preventDefault(); + const interactiveElement = event.target as InteractiveHTMLElement; + + if (isFirefox && !interactiveElementToParent.get(interactiveElement)) { + return; + } + + const { disabled } = interactiveElement; + + if (disabled) { + // prevent click from moving focus on host + event.preventDefault(); + } } const nonBubblingWhenDisabledMouseEvents = ["mousedown", "mouseup", "click"]; function onNonBubblingWhenDisabledMouseEvent(event: MouseEvent): void { + if (isFirefox && !interactiveElementToParent.get(event.target as InteractiveHTMLElement)) { + return; + } + const { disabled } = event.target as InteractiveHTMLElement; // prevent disallowed mouse events from being emitted on the disabled host (per https://github.com/whatwg/html/issues/5886) @@ -77,20 +102,12 @@ export function updateHostInteraction( (document.activeElement as HTMLElement).blur(); } - component.el.click = interceptedClick; - component.el.addEventListener("pointerdown", onPointerDown, captureOnlyOptions); - nonBubblingWhenDisabledMouseEvents.forEach((event) => - component.el.addEventListener(event, onNonBubblingWhenDisabledMouseEvent, captureOnlyOptions) - ); + blockInteraction(component); return; } - component.el.click = HTMLElement.prototype.click; - component.el.removeEventListener("pointerdown", onPointerDown, captureOnlyOptions); - nonBubblingWhenDisabledMouseEvents.forEach((event) => - component.el.removeEventListener(event, onNonBubblingWhenDisabledMouseEvent, captureOnlyOptions) - ); + restoreInteraction(component); if (typeof hostIsTabbable === "function") { component.el.setAttribute("tabindex", hostIsTabbable.call(component) ? "0" : "-1"); @@ -104,3 +121,76 @@ export function updateHostInteraction( component.el.removeAttribute("aria-disabled"); } + +function blockInteraction(component: InteractiveComponent): void { + component.el.click = interceptedClick; + addInteractionListeners(isFirefox ? getParentElement(component) : component.el); +} + +function addInteractionListeners(element: HTMLElement): void { + if (!element) { + // this path is only applicable to Firefox + return; + } + + element.addEventListener("pointerdown", onPointerDown, captureOnlyOptions); + nonBubblingWhenDisabledMouseEvents.forEach((event) => + element.addEventListener(event, onNonBubblingWhenDisabledMouseEvent, captureOnlyOptions) + ); +} + +function getParentElement(component: InteractiveComponent): ParentElement { + return interactiveElementToParent.get(component.el as InteractiveHTMLElement); +} + +function restoreInteraction(component: InteractiveComponent): void { + delete component.el.click; // fallback on HTMLElement.prototype.click + removeInteractionListeners(isFirefox ? getParentElement(component) : component.el); +} + +function removeInteractionListeners(element: HTMLElement): void { + if (!element) { + // this path is only applicable to Firefox + return; + } + + element.removeEventListener("pointerdown", onPointerDown, captureOnlyOptions); + nonBubblingWhenDisabledMouseEvents.forEach((event) => + element.removeEventListener(event, onNonBubblingWhenDisabledMouseEvent, captureOnlyOptions) + ); +} + +/** + * This utility helps disable components consistently in Firefox. + * + * It needs to be called in `connectedCallback` and is only needed for Firefox as it does not call capture event listeners before non-capture ones (see https://bugzilla.mozilla.org/show_bug.cgi?id=1731504). + * + * @param component + */ +export function connectInteractive(component: InteractiveComponent): void { + if (!component.disabled || !isFirefox) { + return; + } + + const parent = + component.el.parentElement || component.el; /* assume element is host if it has no parent when connected */ + interactiveElementToParent.set(component.el as InteractiveHTMLElement, parent); + blockInteraction(component); +} + +/** + * This utility restores interactivity to disabled components consistently in Firefox. + * + * It needs to be called in `disconnectedCallback` and is only needed for Firefox as it does not call capture event listeners before non-capture ones (see https://bugzilla.mozilla.org/show_bug.cgi?id=1731504). + * + * @param component + */ +export function disconnectInteractive(component: InteractiveComponent): void { + if (!isFirefox) { + return; + } + + // always remove on disconnect as render or connect will restore it + interactiveElementToParent.delete(component.el as InteractiveHTMLElement); + restoreInteraction(component); +}