dont use innerHTML

This commit is contained in:
“chrisshank” 2024-12-09 11:51:20 -08:00
parent c3e161d2c8
commit de724dd087
8 changed files with 69 additions and 63 deletions

View File

@ -129,7 +129,7 @@ async function openFile(showPicker = true) {
try { try {
const text = await fileSaver.open(showPicker); const text = await fileSaver.open(showPicker);
const json = JSON.parse(text || '{ "thoughts": [], "connections": [] }'); const json = JSON.parse(text || '{ "thoughts": [], "connections": [] }');
main.innerHTML = renderChainOfThought(json); main.setHTMLUnsafe(renderChainOfThought(json));
} catch (e) { } catch (e) {
// No file handler was persisted or the file is invalid JSON. // No file handler was persisted or the file is invalid JSON.
console.error(e); console.error(e);

View File

@ -1,5 +1,5 @@
// Ported from https://github.com/bitu467/record-player // Ported from https://github.com/bitu467/record-player
import { css } from '../../src/common/tags'; import { css, html } from '../../src/common/tags';
const styles = css` const styles = css`
::slotted(*) { ::slotted(*) {
@ -236,18 +236,17 @@ export class RecordPlayer extends HTMLElement {
const shadow = this.attachShadow({ mode: 'open' }); const shadow = this.attachShadow({ mode: 'open' });
shadow.adoptedStyleSheets.push(styles); shadow.adoptedStyleSheets.push(styles);
shadow.innerHTML = ` shadow.setHTMLUnsafe(html` <div class="player">
<div class="player"> <div class="record">
<div class="record"> <div class="label"></div>
<div class="label"></div> </div>
</div> <div class="tone-arm">
<div class="tone-arm"> <div class="control"></div>
<div class="control"></div> </div>
</div> <button class="btn"></button>
<button class="btn"></button> <input type="range" class="slider" min="0" max="1" step="0.05" value="0.5" />
<input type="range" class="slider" min="0" max="1" step="0.05" value="0.5"> </div>
</div> <slot></slot>`);
<slot></slot>`;
this.#volumeInput = shadow.querySelector('input[type="range"]')!; this.#volumeInput = shadow.querySelector('input[type="range"]')!;
this.#volumeInput.addEventListener('input', this); this.#volumeInput.addEventListener('input', this);

View File

@ -91,7 +91,7 @@ export class FolkLLM extends HTMLElement {
const stream = await this.#session.promptStreaming(this.prompt); const stream = await this.#session.promptStreaming(this.prompt);
for await (const chunk of stream) { for await (const chunk of stream) {
this.#shadow.innerHTML = chunk; this.#shadow.setHTMLUnsafe(chunk);
} }
this.dispatchEvent(new Event('finished')); this.dispatchEvent(new Event('finished'));

View File

@ -258,7 +258,7 @@ export class FolkShape extends HTMLElement {
// Ideally we would creating these lazily on first focus, but the resize handlers need to be around for delegate focus to work. // 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? // Maybe can add the first resize handler here, and lazily instantiate the rest when needed?
// I can see it becoming important at scale // I can see it becoming important at scale
this.#shadow.innerHTML = html` <button part="rotation-top-left" tabindex="-1"></button> this.#shadow.setHTMLUnsafe(html` <button part="rotation-top-left" tabindex="-1"></button>
<button part="rotation-top-right" tabindex="-1"></button> <button part="rotation-top-right" tabindex="-1"></button>
<button part="rotation-bottom-right" tabindex="-1"></button> <button part="rotation-bottom-right" tabindex="-1"></button>
<button part="rotation-bottom-left" tabindex="-1"></button> <button part="rotation-bottom-left" tabindex="-1"></button>
@ -266,7 +266,7 @@ export class FolkShape extends HTMLElement {
<button part="resize-top-right" aria-label="Resize shape from top right"></button> <button part="resize-top-right" aria-label="Resize shape from top right"></button>
<button part="resize-bottom-right" aria-label="Resize shape from bottom right"></button> <button part="resize-bottom-right" aria-label="Resize shape from bottom right"></button>
<button part="resize-bottom-left" aria-label="Resize shape from bottom left"></button> <button part="resize-bottom-left" aria-label="Resize shape from bottom left"></button>
<div><slot></slot></div>`; <div><slot></slot></div>`);
this.#handles = Object.fromEntries( this.#handles = Object.fromEntries(
Array.from(this.#shadow.querySelectorAll('[part]')).map((el) => [ Array.from(this.#shadow.querySelectorAll('[part]')).map((el) => [

View File

@ -46,7 +46,7 @@ export class FolkSpaceRadial extends HTMLElement {
this.#centerPoint = document.createElement('div'); this.#centerPoint = document.createElement('div');
this.#centerPoint.className = 'center-point'; this.#centerPoint.className = 'center-point';
this.#shadow.innerHTML = html` <slot></slot> `; this.#shadow.setHTMLUnsafe(html`<slot></slot> `);
this.#shadow.appendChild(this.#centerPoint); this.#shadow.appendChild(this.#centerPoint);
// Listen for changes in the slot to layout children when they change // Listen for changes in the slot to layout children when they change

View File

@ -1,4 +1,4 @@
import { html } from './common/tags'; import { html, css } from './common/tags';
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
@ -6,6 +6,44 @@ declare global {
} }
} }
const styles = css`
:host {
display: block;
perspective: 1000px;
position: relative;
width: 100%;
height: 100%;
}
.space {
position: absolute;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform-origin: center;
transition: transform 0.6s;
}
.space.rotate {
transform: rotateX(-90deg);
}
.face {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.front {
transform: rotateX(0deg);
}
.back {
transform: rotateX(90deg);
}
`;
export class FolkSpace extends HTMLElement { export class FolkSpace extends HTMLElement {
static tagName = 'folk-space'; static tagName = 'folk-space';
@ -14,47 +52,14 @@ export class FolkSpace extends HTMLElement {
customElements.define(this.tagName, this); customElements.define(this.tagName, this);
} }
#shadow = this.attachShadow({ mode: 'open' });
constructor() { constructor() {
super(); super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = html`
<style>
:host {
display: block;
perspective: 1000px;
position: relative;
width: 100%;
height: 100%;
}
.space { this.#shadow.adoptedStyleSheets.push(styles);
position: absolute;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform-origin: center;
transition: transform 0.6s;
}
.space.rotate { this.#shadow.setHTMLUnsafe(html`
transform: rotateX(-90deg);
}
.face {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.front {
transform: rotateX(0deg);
}
.back {
transform: rotateX(90deg);
}
</style>
<div class="space"> <div class="space">
<div class="face front"> <div class="face front">
<slot name="front"></slot> <slot name="front"></slot>
@ -63,7 +68,7 @@ export class FolkSpace extends HTMLElement {
<slot name="back"></slot> <slot name="back"></slot>
</div> </div>
</div> </div>
`; `);
} }
transition() { transition() {

View File

@ -1,4 +1,4 @@
import { css } from './common/tags'; import { css, html } from './common/tags';
// hardcoded column and row numbers // hardcoded column and row numbers
const styles = css` const styles = css`
@ -214,14 +214,14 @@ export class FolkSpreadsheet extends HTMLElement {
.join('\n')} .join('\n')}
</style>`; </style>`;
this.#shadow.innerHTML = ` this.#shadow.setHTMLUnsafe(html`
<s-header empty></s-header> <s-header empty></s-header>
<s-columns>${columnHeaders}</s-columns> <s-columns>${columnHeaders}</s-columns>
<s-rows>${rowHeaders}</s-rows> <s-rows>${rowHeaders}</s-rows>
<s-body><slot></slot></s-body> <s-body><slot></slot></s-body>
<textarea hidden></textarea> <textarea hidden></textarea>
${style} ${style}
`; `);
this.#textarea = this.#shadow.querySelector('textarea')!; this.#textarea = this.#shadow.querySelector('textarea')!;
} }

View File

@ -1,3 +1,5 @@
import { html } from './common/tags';
interface Weather { interface Weather {
temperature: string; temperature: string;
windSpeed: string; windSpeed: string;
@ -60,12 +62,12 @@ export class FolkWeather extends HTMLElement {
#renderResults() { #renderResults() {
if (this.#results === null) { if (this.#results === null) {
this.innerHTML = ''; this.setHTMLUnsafe('');
return; return;
} }
this.innerHTML = ` this.setHTMLUnsafe(html`
<p>Temperature: ${this.#results.temperature}</p> <p>Temperature: ${this.#results.temperature}</p>
<p>Wind Speed: ${this.#results.windSpeed}</p> <p>Wind Speed: ${this.#results.windSpeed}</p>
`; `);
} }
} }