kopia lustrzana https://github.com/shoelace-style/shoelace
Rework show/hide logic; #fixes 170
rodzic
fba34699c6
commit
573552b457
|
@ -14,7 +14,7 @@ export namespace Components {
|
|||
/**
|
||||
* Hides the alert
|
||||
*/
|
||||
"hide": () => Promise<boolean>;
|
||||
"hide": () => Promise<void>;
|
||||
/**
|
||||
* Indicates whether or not the alert is open. You can use this in lieu of the show/hide methods.
|
||||
*/
|
||||
|
@ -22,7 +22,7 @@ export namespace Components {
|
|||
/**
|
||||
* Shows the alert.
|
||||
*/
|
||||
"show": () => Promise<boolean>;
|
||||
"show": () => Promise<void>;
|
||||
/**
|
||||
* The type of alert.
|
||||
*/
|
||||
|
@ -276,7 +276,7 @@ export namespace Components {
|
|||
/**
|
||||
* Hides the alert
|
||||
*/
|
||||
"hide": () => Promise<boolean>;
|
||||
"hide": () => Promise<void>;
|
||||
/**
|
||||
* Indicates whether or not the details is open. You can use this in lieu of the show/hide methods.
|
||||
*/
|
||||
|
@ -284,7 +284,7 @@ export namespace Components {
|
|||
/**
|
||||
* Shows the alert.
|
||||
*/
|
||||
"show": () => Promise<boolean>;
|
||||
"show": () => Promise<void>;
|
||||
/**
|
||||
* The summary to show in the details header. If you need to display HTML, use the `summary` slot instead.
|
||||
*/
|
||||
|
@ -294,7 +294,7 @@ export namespace Components {
|
|||
/**
|
||||
* Hides the dialog
|
||||
*/
|
||||
"hide": () => Promise<boolean>;
|
||||
"hide": () => Promise<void>;
|
||||
/**
|
||||
* The dialog's label as displayed in the header. You should always include a relevant label even when using `no-header`, as it is required for proper accessibility.
|
||||
*/
|
||||
|
@ -310,7 +310,7 @@ export namespace Components {
|
|||
/**
|
||||
* Shows the dialog
|
||||
*/
|
||||
"show": () => Promise<boolean>;
|
||||
"show": () => Promise<void>;
|
||||
}
|
||||
interface SlDrawer {
|
||||
/**
|
||||
|
@ -320,7 +320,7 @@ export namespace Components {
|
|||
/**
|
||||
* Hides the drawer
|
||||
*/
|
||||
"hide": () => Promise<boolean>;
|
||||
"hide": () => Promise<void>;
|
||||
/**
|
||||
* The drawer's label as displayed in the header. You should always include a relevant label even when using `no-header`, as it is required for proper accessibility.
|
||||
*/
|
||||
|
@ -340,7 +340,7 @@ export namespace Components {
|
|||
/**
|
||||
* Shows the drawer
|
||||
*/
|
||||
"show": () => Promise<boolean>;
|
||||
"show": () => Promise<void>;
|
||||
}
|
||||
interface SlDropdown {
|
||||
/**
|
||||
|
@ -358,7 +358,7 @@ export namespace Components {
|
|||
/**
|
||||
* Hides the dropdown panel
|
||||
*/
|
||||
"hide": () => Promise<boolean>;
|
||||
"hide": () => Promise<void>;
|
||||
/**
|
||||
* Indicates whether or not the dropdown is open. You can use this in lieu of the show/hide methods.
|
||||
*/
|
||||
|
@ -381,7 +381,7 @@ export namespace Components {
|
|||
/**
|
||||
* Shows the dropdown panel
|
||||
*/
|
||||
"show": () => Promise<boolean>;
|
||||
"show": () => Promise<void>;
|
||||
/**
|
||||
* The distance in pixels from which to offset the panel along its trigger.
|
||||
*/
|
||||
|
@ -963,7 +963,7 @@ export namespace Components {
|
|||
/**
|
||||
* Shows the tooltip.
|
||||
*/
|
||||
"hide": () => Promise<boolean>;
|
||||
"hide": () => Promise<void>;
|
||||
/**
|
||||
* Indicates whether or not the tooltip is open. You can use this in lieu of the show/hide methods.
|
||||
*/
|
||||
|
@ -986,7 +986,7 @@ export namespace Components {
|
|||
/**
|
||||
* Shows the tooltip.
|
||||
*/
|
||||
"show": () => Promise<boolean>;
|
||||
"show": () => Promise<void>;
|
||||
/**
|
||||
* The distance in pixels from which to offset the tooltip along its target.
|
||||
*/
|
||||
|
|
|
@ -20,6 +20,7 @@ import { Component, Element, Event, EventEmitter, Host, Method, Prop, Watch, h }
|
|||
})
|
||||
export class Tab {
|
||||
alert: HTMLElement;
|
||||
isShowing = false;
|
||||
|
||||
@Element() host: HTMLSlAlertElement;
|
||||
|
||||
|
@ -64,28 +65,38 @@ export class Tab {
|
|||
/** Shows the alert. */
|
||||
@Method()
|
||||
async show() {
|
||||
if (this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slShow = this.slShow.emit();
|
||||
if (slShow.defaultPrevented) {
|
||||
return false;
|
||||
this.open = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.host.hidden = false;
|
||||
this.host.clientWidth; // force a reflow
|
||||
this.isShowing = true;
|
||||
this.open = true;
|
||||
}
|
||||
|
||||
/** Hides the alert */
|
||||
@Method()
|
||||
async hide() {
|
||||
if (!this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (!this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slHide = this.slHide.emit();
|
||||
if (slHide.defaultPrevented) {
|
||||
return false;
|
||||
this.open = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.isShowing = false;
|
||||
this.open = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,10 +23,11 @@ let id = 0;
|
|||
shadow: true
|
||||
})
|
||||
export class Details {
|
||||
body: HTMLElement;
|
||||
componentId = `details-${++id}`;
|
||||
details: HTMLElement;
|
||||
header: HTMLElement;
|
||||
componentId = `details-${++id}`;
|
||||
body: HTMLElement;
|
||||
isShowing = false;
|
||||
|
||||
/** Indicates whether or not the details is open. You can use this in lieu of the show/hide methods. */
|
||||
@Prop({ mutable: true, reflect: true }) open = false;
|
||||
|
@ -76,11 +77,15 @@ export class Details {
|
|||
/** Shows the alert. */
|
||||
@Method()
|
||||
async show() {
|
||||
if (this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slShow = this.slShow.emit();
|
||||
if (slShow.defaultPrevented) {
|
||||
return false;
|
||||
this.open = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.body.scrollHeight === 0) {
|
||||
|
@ -93,17 +98,22 @@ export class Details {
|
|||
this.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
this.isShowing = true;
|
||||
this.open = true;
|
||||
}
|
||||
|
||||
/** Hides the alert */
|
||||
@Method()
|
||||
async hide() {
|
||||
if (!this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (!this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slHide = this.slHide.emit();
|
||||
if (slHide.defaultPrevented) {
|
||||
return false;
|
||||
this.open = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// We can't transition out of `height: auto`, so let's set it to the current height first
|
||||
|
@ -115,6 +125,7 @@ export class Details {
|
|||
this.body.style.height = '0';
|
||||
});
|
||||
|
||||
this.isShowing = false;
|
||||
this.open = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,10 @@ let id = 0;
|
|||
shadow: true
|
||||
})
|
||||
export class Dialog {
|
||||
panel: HTMLElement;
|
||||
dialog: HTMLElement;
|
||||
componentId = `dialog-${++id}`;
|
||||
dialog: HTMLElement;
|
||||
isShowing = false;
|
||||
panel: HTMLElement;
|
||||
|
||||
@Element() host: HTMLSlDialogElement;
|
||||
|
||||
|
@ -99,16 +100,21 @@ export class Dialog {
|
|||
/** Shows the dialog */
|
||||
@Method()
|
||||
async show() {
|
||||
if (this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slShow = this.slShow.emit();
|
||||
if (slShow.defaultPrevented) {
|
||||
return false;
|
||||
this.open = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.dialog.hidden = false;
|
||||
this.host.clientWidth; // force a reflow
|
||||
requestAnimationFrame(() => (this.open = true));
|
||||
this.isShowing = true;
|
||||
this.open = true;
|
||||
|
||||
lockBodyScrolling(this.host);
|
||||
document.addEventListener('focusin', this.handleDocumentFocusIn);
|
||||
|
@ -117,13 +123,18 @@ export class Dialog {
|
|||
/** Hides the dialog */
|
||||
@Method()
|
||||
async hide() {
|
||||
if (!this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (!this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slHide = this.slHide.emit();
|
||||
if (slHide.defaultPrevented) {
|
||||
return false;
|
||||
this.open = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.isShowing = false;
|
||||
this.open = false;
|
||||
|
||||
unlockBodyScrolling(this.host);
|
||||
|
|
|
@ -26,9 +26,10 @@ let id = 0;
|
|||
shadow: true
|
||||
})
|
||||
export class Drawer {
|
||||
panel: HTMLElement;
|
||||
drawer: HTMLElement;
|
||||
componentId = `drawer-${++id}`;
|
||||
drawer: HTMLElement;
|
||||
isShowing = false;
|
||||
panel: HTMLElement;
|
||||
|
||||
@Element() host: HTMLSlDrawerElement;
|
||||
|
||||
|
@ -107,16 +108,21 @@ export class Drawer {
|
|||
/** Shows the drawer */
|
||||
@Method()
|
||||
async show() {
|
||||
if (this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slShow = this.slShow.emit();
|
||||
if (slShow.defaultPrevented) {
|
||||
return false;
|
||||
this.open = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.drawer.hidden = false;
|
||||
this.host.clientWidth; // force a reflow
|
||||
requestAnimationFrame(() => (this.open = true));
|
||||
this.isShowing = true;
|
||||
this.open = true;
|
||||
|
||||
// Lock body scrolling only if the drawer isn't contained
|
||||
if (!this.contained) {
|
||||
|
@ -129,17 +135,21 @@ export class Drawer {
|
|||
/** Hides the drawer */
|
||||
@Method()
|
||||
async hide() {
|
||||
if (!this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (!this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slHide = this.slHide.emit();
|
||||
if (slHide.defaultPrevented) {
|
||||
return false;
|
||||
this.open = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.isShowing = false;
|
||||
this.open = false;
|
||||
|
||||
unlockBodyScrolling(this.host);
|
||||
|
||||
document.removeEventListener('focusin', this.handleDocumentFocusIn);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ let id = 0;
|
|||
})
|
||||
export class Dropdown {
|
||||
componentId = `dropdown-${++id}`;
|
||||
isShowing = false;
|
||||
panel: HTMLElement;
|
||||
popover: Popover;
|
||||
trigger: HTMLElement;
|
||||
|
@ -123,11 +124,15 @@ export class Dropdown {
|
|||
/** Shows the dropdown panel */
|
||||
@Method()
|
||||
async show() {
|
||||
if (this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slShow = this.slShow.emit();
|
||||
if (slShow.defaultPrevented) {
|
||||
return false;
|
||||
this.open = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.panel.addEventListener('slActivate', this.handleMenuItemActivate);
|
||||
|
@ -135,18 +140,23 @@ export class Dropdown {
|
|||
document.addEventListener('mousedown', this.handleDocumentMouseDown);
|
||||
document.addEventListener('keydown', this.handleDocumentKeyDown);
|
||||
|
||||
this.popover.show();
|
||||
this.isShowing = true;
|
||||
this.open = true;
|
||||
this.popover.show();
|
||||
}
|
||||
|
||||
/** Hides the dropdown panel */
|
||||
@Method()
|
||||
async hide() {
|
||||
if (!this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (!this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slHide = this.slHide.emit();
|
||||
if (slHide.defaultPrevented) {
|
||||
return false;
|
||||
this.open = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.panel.removeEventListener('slActivate', this.handleMenuItemActivate);
|
||||
|
@ -154,8 +164,9 @@ export class Dropdown {
|
|||
document.removeEventListener('mousedown', this.handleDocumentMouseDown);
|
||||
document.removeEventListener('keydown', this.handleDocumentKeyDown);
|
||||
|
||||
this.popover.hide();
|
||||
this.isShowing = false;
|
||||
this.open = false;
|
||||
this.popover.hide();
|
||||
}
|
||||
|
||||
focusOnTrigger() {
|
||||
|
|
|
@ -19,6 +19,7 @@ let id = 0;
|
|||
})
|
||||
export class Tooltip {
|
||||
componentId = `tooltip-${++id}`;
|
||||
isShowing = false;
|
||||
popover: Popover;
|
||||
target: HTMLElement;
|
||||
tooltip: any;
|
||||
|
@ -126,29 +127,39 @@ export class Tooltip {
|
|||
/** Shows the tooltip. */
|
||||
@Method()
|
||||
async show() {
|
||||
if (this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slShow = this.slShow.emit();
|
||||
if (slShow.defaultPrevented) {
|
||||
return false;
|
||||
this.open = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.popover.show();
|
||||
this.isShowing = true;
|
||||
this.open = true;
|
||||
this.popover.show();
|
||||
}
|
||||
|
||||
/** Shows the tooltip. */
|
||||
@Method()
|
||||
async hide() {
|
||||
if (!this.open) return;
|
||||
// Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
|
||||
if (!this.isShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const slHide = this.slHide.emit();
|
||||
if (slHide.defaultPrevented) {
|
||||
return false;
|
||||
this.open = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.popover.hide();
|
||||
this.isShowing = false;
|
||||
this.open = false;
|
||||
this.popover.hide();
|
||||
}
|
||||
|
||||
getTarget() {
|
||||
|
|
Ładowanie…
Reference in New Issue