2022-02-26 15:48:56 +00:00
|
|
|
import { html, LitElement } from 'lit';
|
2021-10-07 13:31:20 +00:00
|
|
|
import { customElement, property } from 'lit/decorators.js';
|
2022-03-24 11:48:03 +00:00
|
|
|
import { emit } from '~/internal/event';
|
|
|
|
import { watch } from '~/internal/watch';
|
2021-07-10 00:45:44 +00:00
|
|
|
import styles from './resize-observer.styles';
|
2021-02-26 14:09:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @since 2.0
|
2021-03-23 12:43:38 +00:00
|
|
|
* @status stable
|
2021-06-24 22:24:54 +00:00
|
|
|
*
|
2021-09-30 21:16:27 +00:00
|
|
|
* @slot - One or more elements to watch for resizing.
|
|
|
|
*
|
2021-06-25 20:25:46 +00:00
|
|
|
* @event {{ entries: ResizeObserverEntry[] }} sl-resize - Emitted when the element is resized.
|
2021-02-26 14:09:13 +00:00
|
|
|
*/
|
2021-03-18 13:04:23 +00:00
|
|
|
@customElement('sl-resize-observer')
|
2021-03-09 00:14:32 +00:00
|
|
|
export default class SlResizeObserver extends LitElement {
|
2021-07-10 00:45:44 +00:00
|
|
|
static styles = styles;
|
2021-02-26 14:09:13 +00:00
|
|
|
|
|
|
|
private resizeObserver: ResizeObserver;
|
|
|
|
private observedElements: HTMLElement[] = [];
|
|
|
|
|
2021-10-07 13:31:20 +00:00
|
|
|
/** Disables the observer. */
|
|
|
|
@property({ type: Boolean, reflect: true }) disabled = false;
|
|
|
|
|
2021-03-06 17:01:39 +00:00
|
|
|
connectedCallback() {
|
|
|
|
super.connectedCallback();
|
2021-03-15 17:02:49 +00:00
|
|
|
this.resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {
|
2021-06-24 22:24:54 +00:00
|
|
|
emit(this, 'sl-resize', { detail: { entries } });
|
2021-03-15 17:02:49 +00:00
|
|
|
});
|
2021-10-07 13:31:20 +00:00
|
|
|
|
|
|
|
if (!this.disabled) {
|
|
|
|
this.startObserver();
|
|
|
|
}
|
2021-02-26 14:09:13 +00:00
|
|
|
}
|
|
|
|
|
2021-03-06 17:01:39 +00:00
|
|
|
disconnectedCallback() {
|
|
|
|
super.disconnectedCallback();
|
2021-10-07 13:31:20 +00:00
|
|
|
this.stopObserver();
|
2021-02-26 14:09:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handleSlotChange() {
|
2021-10-07 13:31:20 +00:00
|
|
|
if (!this.disabled) {
|
|
|
|
this.startObserver();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
startObserver() {
|
2022-01-16 05:47:14 +00:00
|
|
|
const slot = this.shadowRoot!.querySelector('slot');
|
2021-02-26 14:09:13 +00:00
|
|
|
|
2022-01-16 05:47:14 +00:00
|
|
|
if (slot !== null) {
|
2021-10-07 13:31:20 +00:00
|
|
|
const elements = slot.assignedElements({ flatten: true }) as HTMLElement[];
|
2021-02-26 14:09:13 +00:00
|
|
|
|
2021-10-07 13:31:20 +00:00
|
|
|
// Unwatch previous elements
|
2022-01-17 04:44:10 +00:00
|
|
|
this.observedElements.forEach(el => this.resizeObserver.unobserve(el));
|
2021-10-07 13:31:20 +00:00
|
|
|
this.observedElements = [];
|
|
|
|
|
|
|
|
// Watch new elements
|
2022-01-16 05:47:14 +00:00
|
|
|
elements.forEach(el => {
|
2021-10-07 13:31:20 +00:00
|
|
|
this.resizeObserver.observe(el);
|
|
|
|
this.observedElements.push(el);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stopObserver() {
|
|
|
|
this.resizeObserver.disconnect();
|
|
|
|
}
|
|
|
|
|
|
|
|
@watch('disabled', { waitUntilFirstUpdate: true })
|
|
|
|
handleDisabledChange() {
|
|
|
|
if (this.disabled) {
|
|
|
|
this.stopObserver();
|
|
|
|
} else {
|
|
|
|
this.startObserver();
|
|
|
|
}
|
2021-02-26 14:09:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
2021-03-06 17:01:39 +00:00
|
|
|
return html` <slot @slotchange=${this.handleSlotChange}></slot> `;
|
2021-02-26 14:09:13 +00:00
|
|
|
}
|
|
|
|
}
|
2021-03-12 14:07:38 +00:00
|
|
|
|
2021-03-12 14:09:08 +00:00
|
|
|
declare global {
|
|
|
|
interface HTMLElementTagNameMap {
|
|
|
|
'sl-resize-observer': SlResizeObserver;
|
|
|
|
}
|
|
|
|
}
|