diff --git a/src/folk-shape.ts b/src/folk-shape.ts index b28a270..28940e8 100644 --- a/src/folk-shape.ts +++ b/src/folk-shape.ts @@ -192,7 +192,6 @@ export class FolkShape extends HTMLElement { #shadow = this.attachShadow({ mode: 'open' }); #internals = this.attachInternals(); - #dynamicStyles = css``; #attrWidth: Dimension = 0; #attrHeight: Dimension = 0; @@ -200,6 +199,8 @@ export class FolkShape extends HTMLElement { #rect = new DOMRectTransform(); #previousRect = new DOMRectTransform(); + #handles: Record; + // Used for rotation handling, would love a better way to do this that avoids this clutter. #initialRotation = 0; #startAngle = 0; @@ -277,7 +278,7 @@ export class FolkShape extends HTMLElement { this.addEventListener('pointerdown', this); this.addEventListener('keydown', this); - this.#shadow.adoptedStyleSheets = [styles, this.#dynamicStyles]; + this.#shadow.adoptedStyleSheets.push(styles); // Ideally we would creating these lazily on first focus, but the resize handlers need to be around for delegate focus to work. // Maybe can add the first resize handler here, and lazily instantiate the rest when needed? // I can see it becoming important at scale @@ -291,6 +292,13 @@ export class FolkShape extends HTMLElement {
`; + this.#handles = Object.fromEntries( + Array.from(this.#shadow.querySelectorAll('[part]')).map((el) => [ + el.getAttribute('part') as ResizeHandle | RotateHandle, + el as HTMLElement, + ]) + ) as Record; + this.x = Number(this.getAttribute('x')) || 0; this.y = Number(this.getAttribute('y')) || 0; this.width = Number(this.getAttribute('width')) || 'auto'; @@ -499,11 +507,12 @@ export class FolkShape extends HTMLElement { target.removeEventListener('pointermove', this); target.removeEventListener('lostpointercapture', this); - this.#updateCursors(); if (target.getAttribute('part')?.startsWith('rotation')) { target.style.removeProperty('cursor'); } + this.#updateCursors(); + return; } } @@ -566,41 +575,16 @@ export class FolkShape extends HTMLElement { const resizeCursor0 = getResizeCursorUrl(degrees); const resizeCursor90 = getResizeCursorUrl((degrees + 90) % 360); - const rotateCursor0 = getRotateCursorUrl(degrees); - const rotateCursor90 = getRotateCursorUrl((degrees + 90) % 360); - const rotateCursor180 = getRotateCursorUrl((degrees + 180) % 360); - const rotateCursor270 = getRotateCursorUrl((degrees + 270) % 360); - // TODO use css variables - const dynamicStyles = ` - [part='resize-top-left'], - [part='resize-bottom-right'] { - cursor: ${resizeCursor0}; - } + this.#handles['resize-top-left'].style.setProperty('cursor', resizeCursor0); + this.#handles['resize-bottom-right'].style.setProperty('cursor', resizeCursor0); + this.#handles['resize-top-right'].style.setProperty('cursor', resizeCursor90); + this.#handles['resize-bottom-left'].style.setProperty('cursor', resizeCursor90); - [part='resize-top-right'], - [part='resize-bottom-left'] { - cursor: ${resizeCursor90}; - } - - [part='rotation-top-left'] { - cursor: ${rotateCursor0}; - } - - [part='rotation-top-right'] { - cursor: ${rotateCursor90}; - } - - [part='rotation-bottom-right'] { - cursor: ${rotateCursor180}; - } - - [part='rotation-bottom-left'] { - cursor: ${rotateCursor270}; - } - `; - - this.#dynamicStyles.replaceSync(dynamicStyles); + this.#handles['rotation-top-left'].style.setProperty('cursor', getRotateCursorUrl(degrees)); + this.#handles['rotation-top-right'].style.setProperty('cursor', getRotateCursorUrl((degrees + 90) % 360)); + this.#handles['rotation-bottom-right'].style.setProperty('cursor', getRotateCursorUrl((degrees + 180) % 360)); + this.#handles['rotation-bottom-left'].style.setProperty('cursor', getRotateCursorUrl((degrees + 270) % 360)); } #handleResize(handle: ResizeHandle, pointerPos: Point, target: HTMLElement, event?: PointerEvent) {