fix: Resolve replaceChild and activeElement errors in FolkJS components
- Fix activeElement undefined error by guarding against missing shadowRoot - Fix replaceChild "parameter 2 is not of type Node" error in all 15 child components by using :scope > div selector to find container div directly instead of incorrectly searching inside slot.parentElement The bug was caused by looking for a nested div that doesn't exist - the slot's parent IS the container div that needs to be replaced. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
8eef5b58b7
commit
42b29ff9d7
|
|
@ -269,13 +269,10 @@ export class FolkCalendar extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
if (containerDiv) {
|
||||||
const existingDiv = parent.querySelector("div");
|
containerDiv.replaceWith(wrapper);
|
||||||
if (existingDiv) {
|
|
||||||
parent.replaceChild(wrapper, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get element references
|
// Get element references
|
||||||
|
|
|
||||||
|
|
@ -238,13 +238,10 @@ export class FolkChat extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
if (containerDiv) {
|
||||||
const existingDiv = parent.querySelector("div");
|
containerDiv.replaceWith(wrapper);
|
||||||
if (existingDiv) {
|
|
||||||
parent.replaceChild(wrapper, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get element references
|
// Get element references
|
||||||
|
|
|
||||||
|
|
@ -258,13 +258,10 @@ export class FolkEmbed extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
if (containerDiv) {
|
||||||
const existingDiv = parent.querySelector("div");
|
containerDiv.replaceWith(wrapper);
|
||||||
if (existingDiv) {
|
|
||||||
parent.replaceChild(wrapper, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = wrapper.querySelector(".content") as HTMLElement;
|
const content = wrapper.querySelector(".content") as HTMLElement;
|
||||||
|
|
|
||||||
|
|
@ -229,13 +229,11 @@ export class FolkGoogleItem extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our card
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
const cardEl = wrapper.querySelector(".card");
|
||||||
const existingDiv = parent.querySelector("div");
|
if (containerDiv && cardEl) {
|
||||||
if (existingDiv) {
|
containerDiv.replaceWith(cardEl);
|
||||||
parent.replaceChild(wrapper.querySelector(".card")!, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle visibility on badge click
|
// Toggle visibility on badge click
|
||||||
|
|
|
||||||
|
|
@ -264,13 +264,10 @@ export class FolkImageGen extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
if (containerDiv) {
|
||||||
const existingDiv = parent.querySelector("div");
|
containerDiv.replaceWith(wrapper);
|
||||||
if (existingDiv) {
|
|
||||||
parent.replaceChild(wrapper, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#promptInput = wrapper.querySelector(".prompt-input");
|
this.#promptInput = wrapper.querySelector(".prompt-input");
|
||||||
|
|
|
||||||
|
|
@ -308,13 +308,10 @@ export class FolkMap extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
if (containerDiv) {
|
||||||
const existingDiv = parent.querySelector("div");
|
containerDiv.replaceWith(wrapper);
|
||||||
if (existingDiv) {
|
|
||||||
parent.replaceChild(wrapper, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#mapEl = wrapper.querySelector(".map");
|
this.#mapEl = wrapper.querySelector(".map");
|
||||||
|
|
|
||||||
|
|
@ -173,10 +173,10 @@ export class FolkMarkdown extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Move existing slot content into our wrapper
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
const slot = root.querySelector("slot");
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
if (slot) {
|
if (containerDiv) {
|
||||||
slot.parentElement?.replaceChild(wrapper, slot.parentElement.querySelector("div")!);
|
containerDiv.replaceWith(wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get references to elements
|
// Get references to elements
|
||||||
|
|
|
||||||
|
|
@ -366,13 +366,10 @@ export class FolkObsNote extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
if (containerDiv) {
|
||||||
const existingDiv = parent.querySelector("div");
|
containerDiv.replaceWith(wrapper);
|
||||||
if (existingDiv) {
|
|
||||||
parent.replaceChild(wrapper, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#editor = wrapper.querySelector(".editor");
|
this.#editor = wrapper.querySelector(".editor");
|
||||||
|
|
|
||||||
|
|
@ -195,13 +195,11 @@ export class FolkPiano extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our piano container
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
const pianoContainer = wrapper.querySelector(".piano-container");
|
||||||
const existingDiv = parent.querySelector("div");
|
if (containerDiv && pianoContainer) {
|
||||||
if (existingDiv) {
|
containerDiv.replaceWith(pianoContainer);
|
||||||
parent.replaceChild(wrapper.querySelector(".piano-container")!, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get references
|
// Get references
|
||||||
|
|
|
||||||
|
|
@ -293,13 +293,10 @@ export class FolkPrompt extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
if (containerDiv) {
|
||||||
const existingDiv = parent.querySelector("div");
|
containerDiv.replaceWith(wrapper);
|
||||||
if (existingDiv) {
|
|
||||||
parent.replaceChild(wrapper, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#messagesEl = wrapper.querySelector(".messages");
|
this.#messagesEl = wrapper.querySelector(".messages");
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,9 @@ export class FolkShape extends FolkElement {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const focusedElement = (this.renderRoot as ShadowRoot).activeElement as HTMLElement | null;
|
const shadowRoot = this.renderRoot as ShadowRoot | undefined;
|
||||||
|
if (!shadowRoot) return;
|
||||||
|
const focusedElement = shadowRoot.activeElement as HTMLElement | null;
|
||||||
const target = event.composedPath()[0] as HTMLElement;
|
const target = event.composedPath()[0] as HTMLElement;
|
||||||
let handle: Handle | null = null;
|
let handle: Handle | null = null;
|
||||||
if (target) {
|
if (target) {
|
||||||
|
|
|
||||||
|
|
@ -88,12 +88,11 @@ export class FolkSlide extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our slide container
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
slot.parentElement.replaceChild(
|
const slideContainer = wrapper.querySelector(".slide-container");
|
||||||
wrapper.querySelector(".slide-container")!,
|
if (containerDiv && slideContainer) {
|
||||||
slot.parentElement.querySelector("div")!
|
containerDiv.replaceWith(slideContainer);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update label from attribute
|
// Update label from attribute
|
||||||
|
|
|
||||||
|
|
@ -349,13 +349,10 @@ export class FolkTranscription extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
if (containerDiv) {
|
||||||
const existingDiv = parent.querySelector("div");
|
containerDiv.replaceWith(wrapper);
|
||||||
if (existingDiv) {
|
|
||||||
parent.replaceChild(wrapper, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#recordBtn = wrapper.querySelector(".record-btn");
|
this.#recordBtn = wrapper.querySelector(".record-btn");
|
||||||
|
|
|
||||||
|
|
@ -325,13 +325,10 @@ export class FolkVideoChat extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
if (containerDiv) {
|
||||||
const existingDiv = parent.querySelector("div");
|
containerDiv.replaceWith(wrapper);
|
||||||
if (existingDiv) {
|
|
||||||
parent.replaceChild(wrapper, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = wrapper.querySelector(".content") as HTMLElement;
|
const content = wrapper.querySelector(".content") as HTMLElement;
|
||||||
|
|
|
||||||
|
|
@ -359,13 +359,10 @@ export class FolkVideoGen extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
if (containerDiv) {
|
||||||
const existingDiv = parent.querySelector("div");
|
containerDiv.replaceWith(wrapper);
|
||||||
if (existingDiv) {
|
|
||||||
parent.replaceChild(wrapper, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#promptInput = wrapper.querySelector(".prompt-input");
|
this.#promptInput = wrapper.querySelector(".prompt-input");
|
||||||
|
|
|
||||||
|
|
@ -340,13 +340,10 @@ export class FolkWorkflowBlock extends FolkShape {
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const slot = root.querySelector("slot");
|
// Replace the container div (slot's parent) with our wrapper
|
||||||
if (slot?.parentElement) {
|
const containerDiv = root.querySelector(":scope > div");
|
||||||
const parent = slot.parentElement;
|
if (containerDiv) {
|
||||||
const existingDiv = parent.querySelector("div");
|
containerDiv.replaceWith(wrapper);
|
||||||
if (existingDiv) {
|
|
||||||
parent.replaceChild(wrapper, existingDiv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#contentEl = wrapper.querySelector(".content");
|
this.#contentEl = wrapper.querySelector(".content");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue