diff --git a/docs/components/mutation-observer.md b/docs/components/mutation-observer.md index 1eddefcb..258803bc 100644 --- a/docs/components/mutation-observer.md +++ b/docs/components/mutation-observer.md @@ -8,7 +8,7 @@ The mutation observer will report changes to the content it wraps through the `s ```html preview
- + Click to mutate @@ -42,6 +42,47 @@ The mutation observer will report changes to the content it wraps through the `s
``` +```jsx react +import { useState } from 'react'; +import { SlButton, SlMutationObserver } from '@shoelace-style/shoelace/dist/react'; + +const css = ` + .resize-observer-overview div { + display: flex; + border: solid 2px rgb(var(--sl-input-border-color)); + align-items: center; + justify-content: center; + text-align: center; + padding: 4rem 2rem; + } +`; + +const types = ['primary', 'success', 'neutral', 'warning', 'danger']; +let clicks = 0; + +const App = () => { + const [type, setType] = useState('primary'); + + function handleClick() { + clicks++; + setType(types[clicks % types.length]); + } + + return ( + <> + console.log(event.detail)} + > + Click to mutate + + + + + ); +}; +``` + ?> When you create a mutation observer, you must indicate what changes it should respond to by including at least one of `attr`, `child-list`, or `char-data`. If you don't specify at least one of these attributes, no mutation events will be emitted. ## Examples @@ -101,4 +142,55 @@ Use the `child-list` attribute to watch for new child elements that are added or ``` +```jsx react +import { useState } from 'react'; +import { SlButton, SlMutationObserver } from '@shoelace-style/shoelace/dist/react'; + +const css = ` + .mutation-child-list .buttons { + display: flex; + gap: .25rem; + flex-wrap: wrap; + margin-bottom: 1rem; + } +`; + +let buttonCount = 0; + +const App = () => { + const [buttonIds, setButtonIds] = useState([]); + + function addButton() { + setButtonIds([...buttonIds, ++buttonCount]); + } + + function removeButton(id) { + setButtonIds(buttonIds.filter(i => i !== id)); + } + + return ( + <> +
+ console.log(event.detail)} + > +
+ Add button + {buttonIds.map(id => ( + removeButton(id)}> + {id} + + ))} +
+
+
+ + 👆 Add and remove buttons and watch the console + + + ); +}; +``` + [component-metadata:sl-mutation-observer] diff --git a/docs/resources/changelog.md b/docs/resources/changelog.md index b81a8246..88134ad7 100644 --- a/docs/resources/changelog.md +++ b/docs/resources/changelog.md @@ -9,6 +9,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis ## Next - Added React examples and CodePen links to all components +- Changed the `attr` in experimental `` to require `"*"` instead of `""` to target all attributes - Fixed a bug in `` where the `label` attribute didn't set the label - Fixed a bug in `` that caused disabled and readonly controls to transition on hover - The `panel` property of `` is now reflected diff --git a/src/components/mutation-observer/mutation-observer.ts b/src/components/mutation-observer/mutation-observer.ts index 685b282a..7f36c465 100644 --- a/src/components/mutation-observer/mutation-observer.ts +++ b/src/components/mutation-observer/mutation-observer.ts @@ -19,8 +19,8 @@ export default class SlMutationObserver extends LitElement { private mutationObserver: MutationObserver; /** - * Watches for changes to attributes. If empty, all changes will be reported. To watch only specific attributes, - * separate them by a space. + * Watches for changes to attributes. If set to *, all changes will be reported. To watch only specific attributes, + * separate them by a space, e.g. "class id title". */ @property({ reflect: true }) attr: string; @@ -80,12 +80,15 @@ export default class SlMutationObserver extends LitElement { } startObserver() { + const observeAttributes = typeof this.attr === 'string' && this.attr.length > 0; + const attributeFilter = observeAttributes && this.attr !== '*' ? this.attr.split(' ') : undefined; + try { this.mutationObserver.observe(this, { subtree: true, childList: this.childList, - attributes: typeof this.attr === 'string', - attributeFilter: typeof this.attr === 'string' && this.attr.length > 0 ? this.attr.split(' ') : undefined, + attributes: observeAttributes, + attributeFilter, attributeOldValue: this.attrOldValue, characterData: this.charData, characterDataOldValue: this.charDataOldValue