You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
49 lines
1.4 KiB
49 lines
1.4 KiB
/**
|
|
* `apply` / `remove` — the only mutation surface of `ActiveDom`.
|
|
*
|
|
* `ActiveDom` doesn't know product frameworks. It receives instructions
|
|
* already resolved by upper layers and applies them to the DOM. Nothing else.
|
|
*
|
|
* Contract:
|
|
* - `string | number` → `setAttribute(name, String(value))`
|
|
* - `true` → `setAttribute(name, '')` (presence flag, e.g. `data-disabled`)
|
|
* - `false | null | undefined` → `removeAttribute(name)`
|
|
*
|
|
* No event dispatch, no batching, no observation. Pure mutations.
|
|
*/
|
|
|
|
import { isBrowser } from '$libs/dom';
|
|
|
|
export type DomAttrValue = string | number | boolean | null | undefined;
|
|
|
|
export type StructuralChange = {
|
|
target: HTMLElement;
|
|
attrs: Record<string, DomAttrValue>;
|
|
};
|
|
|
|
function writeAttr(target: HTMLElement, name: string, value: DomAttrValue): void {
|
|
if (value === false || value === null || value === undefined) {
|
|
target.removeAttribute(name);
|
|
return;
|
|
}
|
|
if (value === true) {
|
|
target.setAttribute(name, '');
|
|
return;
|
|
}
|
|
target.setAttribute(name, String(value));
|
|
}
|
|
|
|
export function applyChange(change: StructuralChange): void {
|
|
if (!isBrowser) return;
|
|
for (const name in change.attrs) {
|
|
writeAttr(change.target, name, change.attrs[name]);
|
|
}
|
|
}
|
|
|
|
export function removeAttrs(target: HTMLElement, names: readonly string[]): void {
|
|
if (!isBrowser) return;
|
|
for (const name of names) {
|
|
target.removeAttribute(name);
|
|
}
|
|
}
|