Add experimental resize observer

pull/261/head
Cory LaViska 2020-10-29 18:15:48 -04:00
rodzic b5c92a1713
commit 4adb6bbf04
6 zmienionych plików z 121 dodań i 1 usunięć

Wyświetl plik

@ -51,6 +51,7 @@
- [Animation](/components/animation.md)
- [Format Bytes](/components/format-bytes.md)
- [Include](/components/include.md)
- [Resize Observer](/components/resize-observer.md)
- [Theme](/components/theme.md)
- Design Tokens

Wyświetl plik

@ -0,0 +1,46 @@
# Resize Observer
[component-header:sl-resize-observer]
Resize observers offer a thin, declarative interface to the [`ResizeObserver API`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
The resize observer will report changes to the dimensions of the elements it wraps through the `sl-resize` event. When emitted, a collection of [`ResizeObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry) objects will be attached to `event.detail`, containing the target element and information about its dimensions.
```html preview
<div class="resize-observer-overview">
<sl-resize-observer>
<div>
Resize me and watch the console
</div>
</sl-resize-observer>
</div>
<script>
const container = document.querySelector('.resize-observer-overview');
const resizeObserver = container.querySelector('sl-resize-observer');
resizeObserver.addEventListener('sl-resize', event => {
console.log(event);
});
</script>
<style>
.resize-observer-overview div {
display: flex;
width: 12rem;
min-height: 12rem;
min-width: 12rem;
max-width: 100%;
max-height: 50vh;
border: solid 2px var(--sl-input-border-color);
resize: both;
overflow: auto;
align-items: center;
justify-content: center;
text-align: center;
padding: 1rem;
}
</style>
```
[component-metadata:sl-resize-observer]

Wyświetl plik

@ -8,7 +8,8 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
## Next
- Added `sl-theme` utility and updated theming documentation
- Added experimental `sl-resize-observer` utility
- Added experimental `sl-theme` utility and updated theming documentation
- Fixed a bug where `sl-menu-item` wouldn't render properly in the dark theme
- Improved placeholder contrast in dark theme
- Updated Boostrap Icons to 1.1.0

17
src/components.d.ts vendored
Wyświetl plik

@ -851,6 +851,8 @@ export namespace Components {
*/
"value": number;
}
interface SlResizeObserver {
}
interface SlResponsiveEmbed {
/**
* The aspect ratio of the embedded media in the format of `width:height`, e.g. `16:9`, `4:3`, or `1:1`. Ratios not in this format will be ignored.
@ -1376,6 +1378,12 @@ declare global {
prototype: HTMLSlRatingElement;
new (): HTMLSlRatingElement;
};
interface HTMLSlResizeObserverElement extends Components.SlResizeObserver, HTMLStencilElement {
}
var HTMLSlResizeObserverElement: {
prototype: HTMLSlResizeObserverElement;
new (): HTMLSlResizeObserverElement;
};
interface HTMLSlResponsiveEmbedElement extends Components.SlResponsiveEmbed, HTMLStencilElement {
}
var HTMLSlResponsiveEmbedElement: {
@ -1479,6 +1487,7 @@ declare global {
"sl-radio": HTMLSlRadioElement;
"sl-range": HTMLSlRangeElement;
"sl-rating": HTMLSlRatingElement;
"sl-resize-observer": HTMLSlResizeObserverElement;
"sl-responsive-embed": HTMLSlResponsiveEmbedElement;
"sl-select": HTMLSlSelectElement;
"sl-skeleton": HTMLSlSkeletonElement;
@ -2365,6 +2374,12 @@ declare namespace LocalJSX {
*/
"value"?: number;
}
interface SlResizeObserver {
/**
* Emitted when the element is resized.
*/
"onSl-resize"?: (event: CustomEvent<ResizeObserverEntry[]>) => void;
}
interface SlResponsiveEmbed {
/**
* The aspect ratio of the embedded media in the format of `width:height`, e.g. `16:9`, `4:3`, or `1:1`. Ratios not in this format will be ignored.
@ -2735,6 +2750,7 @@ declare namespace LocalJSX {
"sl-radio": SlRadio;
"sl-range": SlRange;
"sl-rating": SlRating;
"sl-resize-observer": SlResizeObserver;
"sl-responsive-embed": SlResponsiveEmbed;
"sl-select": SlSelect;
"sl-skeleton": SlSkeleton;
@ -2783,6 +2799,7 @@ declare module "@stencil/core" {
"sl-radio": LocalJSX.SlRadio & JSXBase.HTMLAttributes<HTMLSlRadioElement>;
"sl-range": LocalJSX.SlRange & JSXBase.HTMLAttributes<HTMLSlRangeElement>;
"sl-rating": LocalJSX.SlRating & JSXBase.HTMLAttributes<HTMLSlRatingElement>;
"sl-resize-observer": LocalJSX.SlResizeObserver & JSXBase.HTMLAttributes<HTMLSlResizeObserverElement>;
"sl-responsive-embed": LocalJSX.SlResponsiveEmbed & JSXBase.HTMLAttributes<HTMLSlResponsiveEmbedElement>;
"sl-select": LocalJSX.SlSelect & JSXBase.HTMLAttributes<HTMLSlSelectElement>;
"sl-skeleton": LocalJSX.SlSkeleton & JSXBase.HTMLAttributes<HTMLSlSkeletonElement>;

Wyświetl plik

@ -0,0 +1,5 @@
@import 'component';
:host {
display: contents;
}

Wyświetl plik

@ -0,0 +1,50 @@
import { Component, Element, Event, EventEmitter, h } from '@stencil/core';
import ResizeObserver from 'resize-observer-polyfill';
/**
* @since 2.0
* @status experimental
*/
@Component({
tag: 'sl-resize-observer',
styleUrl: 'resize-observer.scss',
shadow: true
})
export class ResizeObserverUtility {
resizeObserver: ResizeObserver;
observedElements: HTMLElement[] = [];
@Element() host: HTMLSlResizeObserverElement;
/** Emitted when the element is resized. */
@Event({ eventName: 'sl-resize' }) slResize: EventEmitter<ResizeObserverEntry[]>;
connectedCallback() {
this.resizeObserver = new ResizeObserver(event => this.slResize.emit(event));
this.handleSlotChange = this.handleSlotChange.bind(this);
}
disconnectedCallback() {
this.resizeObserver.disconnect();
}
handleSlotChange() {
const slot = this.host.shadowRoot.querySelector('slot');
const elements = slot.assignedElements({ flatten: true }) as HTMLElement[];
// Unwatch previous elements
this.observedElements.map(el => this.resizeObserver.unobserve(el));
this.observedElements = [];
// Watch new elements
elements.map(el => {
this.resizeObserver.observe(el);
this.observedElements.push(el);
});
}
render() {
return <slot onSlotchange={this.handleSlotChange} />;
}
}