diff --git a/packages/pwc/src/elements/__tests__/commitAttributes.test.ts b/packages/pwc/src/elements/__tests__/commitAttributes.test.ts index cec93ac..4d481d2 100644 --- a/packages/pwc/src/elements/__tests__/commitAttributes.test.ts +++ b/packages/pwc/src/elements/__tests__/commitAttributes.test.ts @@ -14,7 +14,7 @@ describe('Set element attribute/property/event handler', () => { }, ]; const div = document.createElement('div'); - commitAttributes(div, attrs, true); + commitAttributes(div, attrs, { isInitial: true }); expect(div.getAttribute('data-index')).toEqual('1'); expect(div.dataset.index).toEqual('1'); expect(div.getAttribute('class')).toEqual('container'); @@ -39,7 +39,7 @@ describe('Set element attribute/property/event handler', () => { }, ]; const parent1 = document.createElement('div'); - commitAttributes(parent1, parent1Attrs, true); + commitAttributes(parent1, parent1Attrs, { isInitial: true }); // Parent2 element const parent2ClickHandler = jest.fn().mockImplementation(() => { @@ -57,7 +57,7 @@ describe('Set element attribute/property/event handler', () => { }, ]; const parent2 = document.createElement('div'); - commitAttributes(parent2, parent2Attrs, true); + commitAttributes(parent2, parent2Attrs, { isInitial: true }); const childClickHandler = jest.fn().mockImplementation(() => { parent1ClickState = 'child clicked'; @@ -70,7 +70,7 @@ describe('Set element attribute/property/event handler', () => { }, ]; const child = document.createElement('div'); - commitAttributes(child, childAttrs, true); + commitAttributes(child, childAttrs, { isInitial: true }); document.body.appendChild(parent1); document.body.appendChild(parent2); @@ -113,7 +113,7 @@ describe('Set element attribute/property/event handler', () => { }, ]; - commitAttributes(customElement, attrs, true); + commitAttributes(customElement, attrs, { isInitial: true }); expect(customElement.getAttribute('data-index')).toEqual('1'); expect(customElement.dataset.index).toEqual('1'); @@ -133,11 +133,23 @@ describe('Set element attribute/property/event handler', () => { capture: true, } ]; - commitAttributes(div, attrs, true); + commitAttributes(div, attrs, { isInitial: true }); div.click(); expect(mockClickHandler).toBeCalledTimes(1); - commitAttributes(div, attrs, false); + commitAttributes(div, attrs); div.click(); expect(mockClickHandler).toBeCalledTimes(2); }); + + it('Svg elements should be set as attributes', () => { + const svg = document.createElement('svg'); + const attrs = [{ + name: 'width', + value: '200' + }]; + + commitAttributes(svg, attrs, { isInitial: true }); + + expect(svg.getAttribute('width')).toEqual('200'); + }); }); diff --git a/packages/pwc/src/elements/commitAttributes.ts b/packages/pwc/src/elements/commitAttributes.ts index 0924349..2bd60d0 100644 --- a/packages/pwc/src/elements/commitAttributes.ts +++ b/packages/pwc/src/elements/commitAttributes.ts @@ -3,7 +3,16 @@ import type { Attributes, PWCElement } from '../type'; import { isFunction, toRaw } from '../utils'; import { warning } from '../error'; -export function commitAttributes(element: Element, attrs: Attributes, isInitial, rootElement?: PWCElement) { +export function commitAttributes(element: Element, attrs: Attributes, opt?: { + isInitial?: boolean; + rootElement?: PWCElement; + isSVG?: boolean; +}) { + const { + isInitial = false, + isSVG = false, + rootElement, + } = opt || {}; for (const attr of attrs) { const { name, value } = attr; if (isEventName(name)) { @@ -21,6 +30,10 @@ export function commitAttributes(element: Element, attrs: Attributes, isInitial, // If capture is true, the event should be triggered when capture stage // Bind the rootElement to ensure the handler context is the element itself element.addEventListener(eventName, value.bind(rootElement), capture); + } else if (isSVG) { + // https://svgwg.org/svg2-draft/struct.html#InterfaceSVGSVGElement + // Svg elements must be set as attributes, all properties is read only + element.setAttribute(name, value); } else if (name in element) { // Verify that there is a target property on the element element[name] = toRaw(value); diff --git a/packages/pwc/src/elements/reactiveNode.ts b/packages/pwc/src/elements/reactiveNode.ts index c1d9f48..8fabb66 100644 --- a/packages/pwc/src/elements/reactiveNode.ts +++ b/packages/pwc/src/elements/reactiveNode.ts @@ -23,11 +23,13 @@ export class AttributedNode implements ReactiveNode { #el: Element; #root: PWCElement; #elIsCustom: boolean; + #elIsSvg: boolean; constructor(commentNode: Comment, initialAttrs: Attributes, rootNode: PWCElement) { this.#el = commentNode.nextSibling as Element; this.#root = rootNode; this.#elIsCustom = Boolean(window.customElements.get(this.#el.localName)); + this.#elIsSvg = this.#el instanceof SVGElement; this.#commitAttributes(initialAttrs, true); } @@ -41,6 +43,10 @@ export class AttributedNode implements ReactiveNode { } #commitAttributes(value: Attributes, isInitial = false) { - commitAttributes(this.#el, value, isInitial, this.#root); + commitAttributes(this.#el, value, { + isInitial, + isSVG: this.#elIsSvg, + rootElement: this.#root, + }); } }