@spectrum-web-components/overlay
Advanced tools
Comparing version 0.11.17-lit-next.0 to 0.12.0
@@ -37,8 +37,2 @@ { | ||
"kind": "javascript-module", | ||
"path": "sync/overlay-trigger.ts", | ||
"declarations": [], | ||
"exports": [] | ||
}, | ||
{ | ||
"kind": "javascript-module", | ||
"path": "src/ActiveOverlay.ts", | ||
@@ -495,3 +489,3 @@ "declarations": [ | ||
"kind": "method", | ||
"name": "getUpdateComplete", | ||
"name": "_getUpdateComplete", | ||
"privacy": "protected", | ||
@@ -963,3 +957,3 @@ "return": { | ||
"kind": "method", | ||
"name": "getUpdateComplete", | ||
"name": "_getUpdateComplete", | ||
"privacy": "protected", | ||
@@ -1566,2 +1560,30 @@ "return": { | ||
"kind": "method", | ||
"name": "manageFocusAfterCloseWhenOverlaysRemain", | ||
"privacy": "private", | ||
"return": { | ||
"type": { | ||
"text": "void" | ||
} | ||
} | ||
}, | ||
{ | ||
"kind": "method", | ||
"name": "manageFocusAfterCloseWhenLastOverlay", | ||
"privacy": "private", | ||
"return": { | ||
"type": { | ||
"text": "void" | ||
} | ||
}, | ||
"parameters": [ | ||
{ | ||
"name": "overlay", | ||
"type": { | ||
"text": "ActiveOverlay" | ||
} | ||
} | ||
] | ||
}, | ||
{ | ||
"kind": "method", | ||
"name": "hideAndCloseOverlay", | ||
@@ -2039,4 +2061,10 @@ "privacy": "private", | ||
] | ||
}, | ||
{ | ||
"kind": "javascript-module", | ||
"path": "sync/overlay-trigger.ts", | ||
"declarations": [], | ||
"exports": [] | ||
} | ||
] | ||
} |
{ | ||
"name": "@spectrum-web-components/overlay", | ||
"version": "0.11.17-lit-next.0+aad74d6ac", | ||
"version": "0.12.0", | ||
"publishConfig": { | ||
@@ -52,6 +52,6 @@ "access": "public" | ||
"@popperjs/core": "^2.2.2", | ||
"@spectrum-web-components/action-button": "^0.5.10-lit-next.0+aad74d6ac", | ||
"@spectrum-web-components/base": "^0.4.6-lit-next.184+aad74d6ac", | ||
"@spectrum-web-components/shared": "^0.12.10-lit-next.0+aad74d6ac", | ||
"@spectrum-web-components/theme": "^0.8.15-lit-next.47+aad74d6ac", | ||
"@spectrum-web-components/action-button": "^0.6.0", | ||
"@spectrum-web-components/base": "^0.4.5", | ||
"@spectrum-web-components/shared": "^0.12.10", | ||
"@spectrum-web-components/theme": "^0.8.15", | ||
"popper-max-size-modifier": "^0.2.0", | ||
@@ -68,3 +68,3 @@ "tslib": "^2.0.0" | ||
], | ||
"gitHead": "aad74d6ac41d8450aee82d73aaf58ab949b72a00" | ||
"gitHead": "12d891f3dc85e8de641804d8efc9ca06b7fdee2d" | ||
} |
@@ -86,4 +86,4 @@ import { CSSResultArray, PropertyValues, SpectrumElement, TemplateResult } from '@spectrum-web-components/base'; | ||
private stealOverlayContentResolver; | ||
protected getUpdateComplete(): Promise<boolean>; | ||
protected _getUpdateComplete(): Promise<boolean>; | ||
} | ||
export {}; |
@@ -15,2 +15,3 @@ /* | ||
import { reparentChildren } from '@spectrum-web-components/shared'; | ||
import { firstFocusableIn } from '@spectrum-web-components/shared/src/first-focusable-in.js'; | ||
import styles from './active-overlay.css.js'; | ||
@@ -125,3 +126,3 @@ import { applyMaxSize, createPopper, maxSize } from './popper.js'; | ||
focus() { | ||
const firstFocusable = this.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"]), [focusable]'); | ||
const firstFocusable = firstFocusableIn(this); | ||
if (firstFocusable) { | ||
@@ -227,3 +228,4 @@ firstFocusable.focus(); | ||
/* c8 ignore next */ | ||
if (!this.overlayContent) | ||
const activeWithContent = this.state === 'active' && this.overlayContent; | ||
if (!activeWithContent) | ||
return; | ||
@@ -376,4 +378,4 @@ if (this.dataPopperPlacement) { | ||
} | ||
async getUpdateComplete() { | ||
const complete = (await super.getUpdateComplete()); | ||
async _getUpdateComplete() { | ||
const complete = (await super._getUpdateComplete()); | ||
await this.stealOverlayContentPromise; | ||
@@ -380,0 +382,0 @@ return complete; |
@@ -31,2 +31,4 @@ import { ActiveOverlay } from './ActiveOverlay.js'; | ||
private closeAllHoverOverlays; | ||
private manageFocusAfterCloseWhenOverlaysRemain; | ||
private manageFocusAfterCloseWhenLastOverlay; | ||
private hideAndCloseOverlay; | ||
@@ -33,0 +35,0 @@ private closeTopOverlay; |
@@ -86,5 +86,3 @@ /* | ||
if (event.code === 'Escape') { | ||
const overlay = this.topOverlay; | ||
this.closeTopOverlay(); | ||
overlay && overlay.trigger.focus(); | ||
} | ||
@@ -347,62 +345,79 @@ }; | ||
} | ||
manageFocusAfterCloseWhenOverlaysRemain() { | ||
const topOverlay = this.overlays[this.overlays.length - 1]; | ||
topOverlay.feature(); | ||
// Push focus in the the next remaining overlay as needed when a `type="modal"` overlay exists. | ||
if (topOverlay.interaction === 'modal' || topOverlay.hasModalRoot) { | ||
topOverlay.focus(); | ||
} | ||
else { | ||
this.stopTabTrapping(); | ||
} | ||
} | ||
manageFocusAfterCloseWhenLastOverlay(overlay) { | ||
this.stopTabTrapping(); | ||
const isModal = overlay.interaction === 'modal'; | ||
const isReplace = overlay.interaction === 'replace'; | ||
const isInline = overlay.interaction === 'inline'; | ||
const isTabbingAwayFromInlineOrReplace = (isReplace || isInline) && !overlay.tabbingAway; | ||
overlay.tabbingAway = false; | ||
if (!isModal && !isTabbingAwayFromInlineOrReplace) { | ||
return; | ||
} | ||
// Manage post closure focus when needed. | ||
const overlayRoot = overlay.overlayContent.getRootNode(); | ||
const overlayContentActiveElement = overlayRoot.activeElement; | ||
let triggerRoot; | ||
let triggerActiveElement; | ||
const contentContainsActiveElement = () => overlay.overlayContent.contains(overlayContentActiveElement); | ||
const triggerRootContainsActiveElement = () => { | ||
triggerRoot = overlay.trigger.getRootNode(); | ||
triggerActiveElement = triggerRoot.activeElement; | ||
return triggerRoot.contains(triggerActiveElement); | ||
}; | ||
const triggerHostIsActiveElement = () => triggerRoot.host && triggerRoot.host === triggerActiveElement; | ||
// Return focus to the trigger as long as the user hasn't actively focused | ||
// something outside of the current overlay interface; trigger, root, host. | ||
if (isModal || | ||
contentContainsActiveElement() || | ||
triggerRootContainsActiveElement() || | ||
triggerHostIsActiveElement()) { | ||
overlay.trigger.focus(); | ||
} | ||
} | ||
async hideAndCloseOverlay(overlay, animated) { | ||
if (overlay) { | ||
await overlay.hide(animated); | ||
const contentWithLifecycle = overlay.overlayContent; | ||
if (typeof contentWithLifecycle.open !== 'undefined') { | ||
contentWithLifecycle.open = false; | ||
} | ||
if (contentWithLifecycle.overlayCloseCallback) { | ||
const { trigger } = overlay; | ||
contentWithLifecycle.overlayCloseCallback({ trigger }); | ||
} | ||
if (overlay.state != 'dispose') | ||
return; | ||
const index = this.overlays.indexOf(overlay); | ||
if (index >= 0) { | ||
this.overlays.splice(index, 1); | ||
} | ||
if (this.overlays.length) { | ||
const topOverlay = this.overlays[this.overlays.length - 1]; | ||
topOverlay.feature(); | ||
if (topOverlay.interaction === 'modal' || | ||
topOverlay.hasModalRoot) { | ||
topOverlay.focus(); | ||
} | ||
else { | ||
this.stopTabTrapping(); | ||
} | ||
} | ||
else { | ||
this.stopTabTrapping(); | ||
if (overlay.interaction === 'modal' || | ||
((overlay.interaction === 'replace' || | ||
overlay.interaction === 'inline') && | ||
!overlay.tabbingAway)) { | ||
const overlayRoot = overlay.overlayContent.getRootNode(); | ||
const overlayContentActiveElement = overlayRoot.activeElement; | ||
const triggerRoot = overlay.trigger.getRootNode(); | ||
const triggerActiveElement = triggerRoot.activeElement; | ||
if (overlay.overlayContent.contains(overlayContentActiveElement) || | ||
overlay.trigger | ||
.getRootNode() | ||
.contains(triggerActiveElement) || | ||
(triggerRoot.host && | ||
triggerRoot.host === triggerActiveElement)) { | ||
overlay.trigger.focus(); | ||
} | ||
} | ||
overlay.tabbingAway = false; | ||
} | ||
overlay.remove(); | ||
overlay.dispose(); | ||
overlay.trigger.dispatchEvent(new CustomEvent('sp-closed', { | ||
bubbles: true, | ||
composed: true, | ||
cancelable: true, | ||
detail: { | ||
interaction: overlay.interaction, | ||
}, | ||
})); | ||
if (!overlay) { | ||
return; | ||
} | ||
await overlay.hide(animated); | ||
const contentWithLifecycle = overlay.overlayContent; | ||
if (typeof contentWithLifecycle.open !== 'undefined') { | ||
contentWithLifecycle.open = false; | ||
} | ||
if (contentWithLifecycle.overlayCloseCallback) { | ||
const { trigger } = overlay; | ||
contentWithLifecycle.overlayCloseCallback({ trigger }); | ||
} | ||
if (overlay.state != 'dispose') | ||
return; | ||
const index = this.overlays.indexOf(overlay); | ||
if (index >= 0) { | ||
this.overlays.splice(index, 1); | ||
} | ||
if (this.overlays.length) { | ||
this.manageFocusAfterCloseWhenOverlaysRemain(); | ||
} | ||
else { | ||
this.manageFocusAfterCloseWhenLastOverlay(overlay); | ||
} | ||
overlay.remove(); | ||
overlay.dispose(); | ||
overlay.trigger.dispatchEvent(new CustomEvent('sp-closed', { | ||
bubbles: true, | ||
composed: true, | ||
cancelable: true, | ||
detail: { | ||
interaction: overlay.interaction, | ||
}, | ||
})); | ||
} | ||
@@ -409,0 +424,0 @@ closeTopOverlay() { |
import { LitElement, CSSResultArray, TemplateResult, PropertyValues } from '@spectrum-web-components/base'; | ||
import { Placement, TriggerInteractions, OverlayOptions } from './overlay-types'; | ||
export declare type OverlayContentTypes = 'click' | 'hover' | 'longpress' | null | undefined; | ||
export declare type OverlayContentTypes = 'click' | 'hover' | 'longpress'; | ||
/** | ||
@@ -55,4 +55,4 @@ * @element overlay-trigger | ||
private openStateResolver; | ||
protected getUpdateComplete(): Promise<boolean>; | ||
protected _getUpdateComplete(): Promise<boolean>; | ||
disconnectedCallback(): void; | ||
} |
@@ -12,5 +12,5 @@ /* | ||
*/ | ||
var _a; | ||
import { __decorate } from "tslib"; | ||
import { html, LitElement, property, } from '@spectrum-web-components/base'; | ||
import { firstFocusableIn } from '@spectrum-web-components/shared/src/first-focusable-in.js'; | ||
import { openOverlay } from './loader.js'; | ||
@@ -117,13 +117,10 @@ import overlayTriggerStyles from './overlay-trigger.css.js'; | ||
manageOpen() { | ||
const handlers = { | ||
var _a; | ||
const openHandlers = { | ||
click: () => this.onTriggerClick(), | ||
hover: () => this.onTriggerMouseEnter(), | ||
longpress: () => this.onTriggerLongpress(), | ||
none: () => this.closeAllOverlays(), | ||
}; | ||
const handler = handlers[this.open || '']; | ||
if (!handler) { | ||
this.closeAllOverlays(); | ||
return; | ||
} | ||
handler(); | ||
openHandlers[(_a = this.open) !== null && _a !== void 0 ? _a : 'none'](); | ||
} | ||
@@ -180,3 +177,3 @@ async openOverlay(target, interaction, content, options) { | ||
} | ||
const firstFocusable = overlayContent.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"]), [focusable]'); | ||
const firstFocusable = firstFocusableIn(overlayContent); | ||
if (!firstFocusable) { | ||
@@ -198,3 +195,3 @@ overlayContent.tabIndex = 0; | ||
async onTriggerLongpress() { | ||
var _b, _c; | ||
var _a, _b; | ||
if (!this.targetContent || | ||
@@ -208,3 +205,3 @@ !this.longpressContent || | ||
this.prepareToFocusOverlayContent(longpressContent); | ||
const notImmediatelyClosable = ((_c = (_b = this._longpressEvent) === null || _b === void 0 ? void 0 : _b.detail) === null || _c === void 0 ? void 0 : _c.source) !== 'keyboard'; | ||
const notImmediatelyClosable = ((_b = (_a = this._longpressEvent) === null || _a === void 0 ? void 0 : _a.detail) === null || _b === void 0 ? void 0 : _b.source) !== 'keyboard'; | ||
this.closeLongpressOverlay = this.openOverlay(targetContent, this.type ? this.type : 'longpress', longpressContent, Object.assign(Object.assign({}, this.overlayOptions), { receivesFocus: 'auto', notImmediatelyClosable })); | ||
@@ -245,4 +242,4 @@ this._longpressEvent = undefined; | ||
} | ||
async getUpdateComplete() { | ||
const complete = (await super.getUpdateComplete()); | ||
async _getUpdateComplete() { | ||
const complete = (await super._getUpdateComplete()); | ||
await this.openStatePromise; | ||
@@ -256,3 +253,2 @@ return complete; | ||
} | ||
_a = OverlayTrigger; | ||
OverlayTrigger.openOverlay = async (target, interaction, content, options) => { | ||
@@ -259,0 +255,0 @@ return openOverlay(target, interaction, content, options); |
@@ -272,61 +272,11 @@ import { __decorate } from "tslib"; | ||
return html ` | ||
<sp-field-label for="picker1">Test</sp-field-label> | ||
<sp-picker id="picker1" focusable .label=${'test'}> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
</sp-picker> | ||
<sp-field-label for="picker2">Test2</sp-field-label> | ||
<sp-picker id="picker2" focusable .label=${'test'}> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
</sp-picker> | ||
<sp-field-label for="picker3">Test 3</sp-field-label> | ||
<sp-picker id="picker3" focusable .label=${'test'}> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
<sp-menu-item value=${'timeSinceLastSynced'}> | ||
${'test'} | ||
</sp-menu-item> | ||
</sp-picker> | ||
<overlay-trigger> | ||
<sp-button slot="trigger">Open me</sp-button> | ||
<sp-popover slot="click-content" direction="bottom" dialog> | ||
<p>This is all the content.</p> | ||
<p>This is all the content.</p> | ||
<p>This is all the content.</p> | ||
<p>This is all the content.</p> | ||
</sp-popover> | ||
</overlay-trigger> | ||
`; | ||
@@ -336,5 +286,8 @@ } | ||
__decorate([ | ||
query('sp-picker') | ||
], PopoverContent.prototype, "picker", void 0); | ||
query('[slot="trigger"]') | ||
], PopoverContent.prototype, "button", void 0); | ||
__decorate([ | ||
query('overlay-trigger') | ||
], PopoverContent.prototype, "trigger", void 0); | ||
customElements.define('popover-content', PopoverContent); | ||
//# sourceMappingURL=overlay-story-components.js.map |
@@ -174,4 +174,4 @@ /* | ||
active-overlay::part(theme) { | ||
--styled-div-background-color: var(--spectrum-semantic-cta-color-background-default); | ||
--spectrum-button-cta-m-background-color: rebeccapurple; | ||
--styled-div-background-color: var(--spectrum-semantic-cta-background-color-default); | ||
--spectrum-button-m-cta-texticon-background-color: rebeccapurple; | ||
} | ||
@@ -506,14 +506,42 @@ </style> | ||
}; | ||
export const complexModal = () => { | ||
requestAnimationFrame(() => { | ||
function nextFrame() { | ||
return new Promise((res) => requestAnimationFrame(() => res())); | ||
} | ||
class ComplexModalReady extends HTMLElement { | ||
constructor() { | ||
super(); | ||
this.handleTriggerOpened = async () => { | ||
await nextFrame(); | ||
const picker = document.querySelector('#test-picker'); | ||
picker.addEventListener('sp-opened', this.handlePickerOpen); | ||
picker.open = true; | ||
}; | ||
this.handlePickerOpen = async () => { | ||
await nextFrame(); | ||
this.ready(true); | ||
}; | ||
this.readyPromise = Promise.resolve(false); | ||
this.readyPromise = new Promise((res) => { | ||
this.ready = res; | ||
this.setup(); | ||
}); | ||
} | ||
async setup() { | ||
await nextFrame(); | ||
const overlay = document.querySelector(`overlay-trigger`); | ||
const trigger = overlay.shadowRoot.querySelector('#trigger'); | ||
trigger.addEventListener('sp-opened', () => { | ||
requestAnimationFrame(() => { | ||
const picker = document.querySelector('#test-picker'); | ||
picker.open = true; | ||
}); | ||
}); | ||
}); | ||
overlay.addEventListener('sp-opened', this.handleTriggerOpened); | ||
} | ||
get updateComplete() { | ||
return this.readyPromise; | ||
} | ||
} | ||
customElements.define('complex-modal-ready', ComplexModalReady); | ||
const complexModalDecorator = (story) => { | ||
return html ` | ||
${story()} | ||
<complex-modal-ready></complex-modal-ready> | ||
`; | ||
}; | ||
export const complexModal = () => { | ||
return html ` | ||
<style> | ||
@@ -573,2 +601,3 @@ body { | ||
}; | ||
complexModal.decorators = [complexModalDecorator]; | ||
export const superComplexModal = () => { | ||
@@ -724,2 +753,42 @@ return html ` | ||
}; | ||
class DefinedOverlayReady extends HTMLElement { | ||
constructor() { | ||
super(); | ||
this.handleTriggerOpened = async () => { | ||
await nextFrame(); | ||
const popover = document.querySelector('popover-content'); | ||
if (!popover) { | ||
return; | ||
} | ||
popover.addEventListener('sp-opened', this.handlePopoverOpen); | ||
popover.button.click(); | ||
}; | ||
this.handlePopoverOpen = async () => { | ||
await nextFrame(); | ||
this.ready(true); | ||
}; | ||
this.readyPromise = Promise.resolve(false); | ||
this.readyPromise = new Promise((res) => { | ||
this.ready = res; | ||
this.setup(); | ||
}); | ||
} | ||
async setup() { | ||
await nextFrame(); | ||
const overlay = document.querySelector(`overlay-trigger`); | ||
const button = document.querySelector(`[slot="trigger"]`); | ||
overlay.addEventListener('sp-opened', this.handleTriggerOpened); | ||
button.click(); | ||
} | ||
get updateComplete() { | ||
return this.readyPromise; | ||
} | ||
} | ||
customElements.define('defined-overlay-ready', DefinedOverlayReady); | ||
const definedOverlayDecorator = (story) => { | ||
return html ` | ||
${story()} | ||
<defined-overlay-ready></defined-overlay-ready> | ||
`; | ||
}; | ||
export const definedOverlayElement = () => { | ||
@@ -735,2 +804,3 @@ return html ` | ||
}; | ||
definedOverlayElement.decorators = [definedOverlayDecorator]; | ||
//# sourceMappingURL=overlay.stories.js.map |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
364128
5053
0
+ Added@spectrum-web-components/action-button@0.6.1(transitive)
+ Added@spectrum-web-components/button@0.15.1(transitive)
+ Added@spectrum-web-components/icon@0.10.1(transitive)
+ Added@spectrum-web-components/icons-ui@0.7.1(transitive)
- Removed@spectrum-web-components/action-button@0.5.10-lit-next.0(transitive)
- Removed@spectrum-web-components/button@0.14.10-lit-next.0(transitive)
- Removed@spectrum-web-components/icon@0.9.12-lit-next.47(transitive)
- Removed@spectrum-web-components/icons-ui@0.6.12-lit-next.47(transitive)