fix: sliders in demo require reload to rerender

CSS custom property changes (--pxicon-ap-size, --pxicon-mode) aren't
observed by MutationObserver/ResizeObserver, so a live-mounted <px-icon>
never rechecked its config. Add a pxicon:refresh document event + exported
refreshAll() helper; demo calls it from its control handlers.
This commit is contained in:
mark
2026-08-08 15:56:58 +02:00
parent c6035b66bf
commit 60cde14401
2 changed files with 22 additions and 2 deletions
+2 -1
View File
@@ -170,7 +170,7 @@
</div> </div>
<script type="module"> <script type="module">
import '../px-icon.js'; import { refreshAll } from '../px-icon.js';
const apSizeInput = document.getElementById('apSize'); const apSizeInput = document.getElementById('apSize');
const apSizeVal = document.getElementById('apSizeVal'); const apSizeVal = document.getElementById('apSizeVal');
@@ -181,6 +181,7 @@ function applyConfig() {
apSizeVal.textContent = ap; apSizeVal.textContent = ap;
document.documentElement.style.setProperty('--pxicon-ap-size', ap + 'px'); document.documentElement.style.setProperty('--pxicon-ap-size', ap + 'px');
document.documentElement.style.setProperty('--pxicon-mode', modeSelect.value); document.documentElement.style.setProperty('--pxicon-mode', modeSelect.value);
refreshAll();
} }
apSizeInput.addEventListener('input', applyConfig); apSizeInput.addEventListener('input', applyConfig);
modeSelect.addEventListener('change', applyConfig); modeSelect.addEventListener('change', applyConfig);
+20 -1
View File
@@ -15,6 +15,14 @@ const DEFAULT_AP_SIZE = 8;
const DEFAULT_MODE = 'average'; const DEFAULT_MODE = 'average';
const SUPERSAMPLE = 8; // per grid cell, for point-sample mode const SUPERSAMPLE = 8; // per grid cell, for point-sample mode
// CSS custom properties (--pxicon-ap-size, --pxicon-mode, ...) aren't
// observable the way DOM mutations/resizes are: MutationObserver and
// ResizeObserver don't fire when a cascaded custom property changes.
// Instances listen for this document-level event so config changes (e.g.
// a page-level theme/control update) can trigger a re-check without every
// caller needing to touch each <px-icon>'s internals.
const REFRESH_EVENT = 'pxicon:refresh';
// key -> Promise<HTMLCanvasElement> (the small pre-upscale grid raster) // key -> Promise<HTMLCanvasElement> (the small pre-upscale grid raster)
const rasterCache = new Map(); const rasterCache = new Map();
@@ -131,12 +139,15 @@ class PxIcon extends HTMLElement {
// e.g. a morph swapping in a different icon. // e.g. a morph swapping in a different icon.
this._observer ??= new MutationObserver(() => this._scheduleRender()); this._observer ??= new MutationObserver(() => this._scheduleRender());
this._observer.observe(this, { childList: true, subtree: true, attributes: true, characterData: true }); this._observer.observe(this, { childList: true, subtree: true, attributes: true, characterData: true });
this._refreshHandler ??= () => this._scheduleRender();
document.addEventListener(REFRESH_EVENT, this._refreshHandler);
this._scheduleRender(); this._scheduleRender();
} }
disconnectedCallback() { disconnectedCallback() {
this._observer?.disconnect(); this._observer?.disconnect();
this._resizeObserver?.disconnect(); this._resizeObserver?.disconnect();
document.removeEventListener(REFRESH_EVENT, this._refreshHandler);
} }
_upgrade() { _upgrade() {
@@ -219,4 +230,12 @@ class PxIcon extends HTMLElement {
customElements.define('px-icon', PxIcon); customElements.define('px-icon', PxIcon);
export { PxIcon, rasterCache }; // Call after changing a --pxicon-* custom property (e.g. on :root, or any
// ancestor of a group of icons) to make every connected <px-icon> re-check
// its computed config and re-render if it actually changed. Cheap to call
// broadly: each instance's own key check skips the work if nothing did.
function refreshAll() {
document.dispatchEvent(new CustomEvent(REFRESH_EVENT));
}
export { PxIcon, rasterCache, refreshAll };