kopia lustrzana https://github.com/shoelace-style/shoelace
Add experimental resize observer
rodzic
b5c92a1713
commit
4adb6bbf04
|
@ -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
|
||||
|
|
|
@ -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]
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
@import 'component';
|
||||
|
||||
:host {
|
||||
display: contents;
|
||||
}
|
|
@ -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} />;
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue