From bcea7774fc31ce9ca5bd17b97a2bae1737d5a745 Mon Sep 17 00:00:00 2001 From: Westbrook Johnson Date: Mon, 24 May 2021 10:19:46 -0400 Subject: [PATCH 1/2] fix(overlay): vend a VirtualTrigger for overlays with no element trigger --- packages/overlay/local.d.ts | 4 +- packages/overlay/src/ActiveOverlay.ts | 41 +++++++++------ packages/overlay/src/VirtualTrigger.ts | 45 ++++++++++++++++ packages/overlay/src/index.ts | 1 + packages/overlay/src/overlay-types.ts | 3 ++ packages/overlay/src/overlay.ts | 2 + packages/overlay/src/popper.ts | 7 ++- packages/overlay/stories/overlay.stories.ts | 57 ++++++++++++++++++++- 8 files changed, 138 insertions(+), 22 deletions(-) create mode 100644 packages/overlay/src/VirtualTrigger.ts diff --git a/packages/overlay/local.d.ts b/packages/overlay/local.d.ts index c6237fd6087..71412d67ffd 100644 --- a/packages/overlay/local.d.ts +++ b/packages/overlay/local.d.ts @@ -20,9 +20,9 @@ declare module '@popperjs/core/dist/esm/popper-lite.js' { } declare module '@popperjs/core/dist/esm/types.js' { - import { Instance } from '@popperjs/core/lib/types.js'; + import { Instance, VirtualElement } from '@popperjs/core/lib/types.js'; - export { Instance }; + export { Instance, VirtualElement }; } declare module '@popperjs/core/dist/esm/enums.js' { diff --git a/packages/overlay/src/ActiveOverlay.ts b/packages/overlay/src/ActiveOverlay.ts index 433d01fa2fe..9f316f3d57f 100644 --- a/packages/overlay/src/ActiveOverlay.ts +++ b/packages/overlay/src/ActiveOverlay.ts @@ -28,6 +28,7 @@ import { TriggerInteractions, } from './overlay-types.js'; import { applyMaxSize, createPopper, Instance, maxSize } from './popper.js'; +import { VirtualTrigger } from './VirtualTrigger.js'; export interface PositionResult { arrowOffsetLeft: number; @@ -115,6 +116,7 @@ export class ActiveOverlay extends SpectrumElement { public overlayContent!: HTMLElement; public overlayContentTip?: HTMLElement; public trigger!: HTMLElement; + public virtualTrigger?: VirtualTrigger; private popper?: Instance; @@ -250,25 +252,29 @@ export class ActiveOverlay extends SpectrumElement { if (!this.overlayContent || !this.trigger) return; if (this.placement && this.placement !== 'none') { - this.popper = createPopper(this.trigger, this, { - placement: this.placement, - modifiers: [ - maxSize, - applyMaxSize, - { - name: 'arrow', - options: { - element: this.overlayContentTip, + this.popper = createPopper( + this.virtualTrigger || this.trigger, + this, + { + placement: this.placement, + modifiers: [ + maxSize, + applyMaxSize, + { + name: 'arrow', + options: { + element: this.overlayContentTip, + }, }, - }, - { - name: 'offset', - options: { - offset: [0, this.offset], + { + name: 'offset', + options: { + offset: [0, this.offset], + }, }, - }, - ], - }); + ], + } + ); } this.state = 'active'; @@ -324,6 +330,7 @@ export class ActiveOverlay extends SpectrumElement { this.overlayContent = detail.content; this.overlayContentTip = detail.contentTip; this.trigger = detail.trigger; + this.virtualTrigger = detail.virtualTrigger; this.placement = detail.placement; this.offset = detail.offset; this.interaction = detail.interaction; diff --git a/packages/overlay/src/VirtualTrigger.ts b/packages/overlay/src/VirtualTrigger.ts new file mode 100644 index 00000000000..bf375834f91 --- /dev/null +++ b/packages/overlay/src/VirtualTrigger.ts @@ -0,0 +1,45 @@ +/* +Copyright 2020 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +import type { VirtualElement } from './popper.js'; +import { Overlay } from './overlay.js'; + +export class VirtualTrigger implements VirtualElement { + private x = 0; + private y = 0; + + public constructor(x: number, y: number) { + this.x = x; + this.y = y; + } + + public updateBoundingClientRect(x: number, y: number): void { + this.x = x; + this.y = y; + Overlay.update(); + } + + public getBoundingClientRect(): DOMRect { + return { + width: 0, + height: 0, + top: this.y, + right: this.x, + y: this.y, + x: this.x, + bottom: this.y, + left: this.x, + toJSON() { + return; + }, + }; + } +} diff --git a/packages/overlay/src/index.ts b/packages/overlay/src/index.ts index b0c1c23bc16..ce36445eb89 100644 --- a/packages/overlay/src/index.ts +++ b/packages/overlay/src/index.ts @@ -14,3 +14,4 @@ export * from './OverlayTrigger.js'; export * from './overlay-types.js'; export * from './ActiveOverlay.js'; export * from './loader.js'; +export * from './VirtualTrigger.js'; diff --git a/packages/overlay/src/overlay-types.ts b/packages/overlay/src/overlay-types.ts index 2b34286f18e..4ff5eb6cdf4 100644 --- a/packages/overlay/src/overlay-types.ts +++ b/packages/overlay/src/overlay-types.ts @@ -12,6 +12,7 @@ governing permissions and limitations under the License. import { ThemeData } from '@spectrum-web-components/theme'; import { Placement as PopperPlacement } from './popper'; +import { VirtualTrigger } from './VirtualTrigger.js'; export type TriggerInteractions = | 'click' @@ -29,6 +30,7 @@ export interface OverlayOpenDetail { offset: number; placement?: Placement; receivesFocus?: 'auto'; + virtualTrigger?: VirtualTrigger; trigger: HTMLElement; interaction: TriggerInteractions; theme: ThemeData; @@ -59,6 +61,7 @@ export type OverlayOptions = { receivesFocus?: 'auto'; notImmediatelyClosable?: boolean; abortPromise?: Promise; + virtualTrigger?: VirtualTrigger; }; declare global { diff --git a/packages/overlay/src/overlay.ts b/packages/overlay/src/overlay.ts index 5677c046fef..28cb5413e01 100644 --- a/packages/overlay/src/overlay.ts +++ b/packages/overlay/src/overlay.ts @@ -96,6 +96,7 @@ export class Overlay { placement = 'top', receivesFocus, notImmediatelyClosable, + virtualTrigger, }: OverlayOptions): Promise { /* c8 ignore next */ if (this.isOpen) return true; @@ -140,6 +141,7 @@ export class Overlay { theme: queryThemeDetail, receivesFocus, notImmediatelyClosable, + virtualTrigger, ...overlayDetailQuery, }); this.isOpen = true; diff --git a/packages/overlay/src/popper.ts b/packages/overlay/src/popper.ts index 595d69f3475..73b6d693a68 100644 --- a/packages/overlay/src/popper.ts +++ b/packages/overlay/src/popper.ts @@ -24,7 +24,10 @@ import { defaultModifiers, popperGenerator, } from '@popperjs/core/dist/esm/popper-lite.js'; -import type { Instance } from '@popperjs/core/dist/esm/types.js'; +import type { + Instance, + VirtualElement, +} from '@popperjs/core/dist/esm/types.js'; import maxSize from 'popper-max-size-modifier'; import { applyMaxSize } from './apply-max-size.js'; @@ -38,5 +41,5 @@ export const createPopper = popperGenerator({ ], }); -export type { Instance, Placement }; +export type { Instance, Placement, VirtualElement }; export { maxSize, applyMaxSize }; diff --git a/packages/overlay/stories/overlay.stories.ts b/packages/overlay/stories/overlay.stories.ts index 5e70de26ea4..9327afca50f 100644 --- a/packages/overlay/stories/overlay.stories.ts +++ b/packages/overlay/stories/overlay.stories.ts @@ -9,7 +9,13 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ import { html, TemplateResult, ifDefined } from '@spectrum-web-components/base'; -import { OverlayContentTypes, OverlayTrigger, Placement } from '../'; +import { + openOverlay, + OverlayContentTypes, + OverlayTrigger, + Placement, + VirtualTrigger, +} from '../'; import '@spectrum-web-components/action-button/sp-action-button.js'; import '@spectrum-web-components/action-group/sp-action-group.js'; import '@spectrum-web-components/button/sp-button.js'; @@ -20,6 +26,7 @@ import '@spectrum-web-components/icons-workflow/icons/sp-icon-magnify.js'; import '@spectrum-web-components/overlay/overlay-trigger.js'; import { Picker } from '@spectrum-web-components/picker'; import '@spectrum-web-components/picker/sp-picker.js'; +import '@spectrum-web-components/menu/sp-menu.js'; import '@spectrum-web-components/menu/sp-menu-item.js'; import '@spectrum-web-components/menu/sp-menu-divider.js'; import '@spectrum-web-components/popover/sp-popover.js'; @@ -637,3 +644,51 @@ export const superComplexModal = (): TemplateResult => { `; }; + +export const virtualElement = (args: Properties): TemplateResult => { + const pointerenter = async (event: PointerEvent): Promise => { + event.preventDefault(); + const trigger = event.target as HTMLElement; + const virtualTrigger = new VirtualTrigger(event.clientX, event.clientY); + openOverlay( + trigger, + 'modal', + trigger.nextElementSibling as HTMLElement, + { + placement: args.placement, + receivesFocus: 'auto', + virtualTrigger, + } + ); + }; + return html` + +
+ + event.target?.dispatchEvent( + new Event('close', { bubbles: true }) + )} + > + + Deselect + Select inverse + Feather... + Select and mask... + + Save selection + Make work path + + + `; +}; + +virtualElement.args = { + placement: 'right-end', +}; From 8e674bfd7bd30ca16aee4464641d04233b98fb30 Mon Sep 17 00:00:00 2001 From: Westbrook Johnson Date: Fri, 28 May 2021 17:41:43 -0400 Subject: [PATCH 2/2] ci: update golden image cache --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 61e0e6c3144..fb3182902ca 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ executors: parameters: current_golden_images_hash: type: string - default: 181d8463d1de8a10c6c47d4bf51eb4024c5ea1b4 + default: 11e0459cd14cde1294eb1564d92c15cea8335d9c commands: downstream: steps: