From 7bdbac9f83cb8b77ccfcd4141f4146272cc70547 Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Tue, 21 Apr 2026 13:50:45 -0300 Subject: [PATCH] feat: add local custom elements for capacitor and inductor, enhancing SPICE simulation support --- frontend/src/components/DynamicComponent.tsx | 7 ++- .../src/wokwi-custom/capacitor-element.ts | 50 ++++++++++++++++++ frontend/src/wokwi-custom/index.ts | 18 +++++++ frontend/src/wokwi-custom/inductor-element.ts | 52 +++++++++++++++++++ 4 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 frontend/src/wokwi-custom/capacitor-element.ts create mode 100644 frontend/src/wokwi-custom/index.ts create mode 100644 frontend/src/wokwi-custom/inductor-element.ts diff --git a/frontend/src/components/DynamicComponent.tsx b/frontend/src/components/DynamicComponent.tsx index 0c22a88f..c912d8ee 100644 --- a/frontend/src/components/DynamicComponent.tsx +++ b/frontend/src/components/DynamicComponent.tsx @@ -17,9 +17,12 @@ import { useSimulatorStore } from '../store/useSimulatorStore'; import { PartSimulationRegistry } from '../simulation/parts'; import { isBoardComponent, boardPinToNumber } from '../utils/boardPinMapping'; -// Side-effect import: registers ALL wokwi custom elements (including new ones -// like wokwi-capacitor, wokwi-inductor) so document.createElement() works. +// Side-effect imports: register every web component we'll create at runtime. +// `@wokwi/elements` covers the upstream catalog; `../wokwi-custom` adds the +// velxio-local elements (e.g. , ) that we +// can't push back to the upstream wokwi-elements repo. import '@wokwi/elements'; +import '../wokwi-custom'; interface DynamicComponentProps { id: string; diff --git a/frontend/src/wokwi-custom/capacitor-element.ts b/frontend/src/wokwi-custom/capacitor-element.ts new file mode 100644 index 00000000..30023eca --- /dev/null +++ b/frontend/src/wokwi-custom/capacitor-element.ts @@ -0,0 +1,50 @@ +/** + * — local replacement for the upstream wokwi-elements + * version. Kept inside velxio because we cannot push the original Lit + * sources to wokwi/wokwi-elements. + * + * Plain HTMLElement (no Lit) — the SVG is static and `value` is read by + * the SPICE layer from the simulator store, not from this DOM node, so + * we don't need reactive rendering. + */ + +interface ElementPin { + name: string; + x: number; + y: number; + signals: unknown[]; +} + +const SVG = ` + + + + +`; + +export class CapacitorElement extends HTMLElement { + static observedAttributes = ['value']; + + readonly pinInfo: ElementPin[] = [ + { name: '1', x: 0, y: 5.65, signals: [] }, + { name: '2', x: 58.8, y: 5.65, signals: [] }, + ]; + + constructor() { + super(); + const root = this.attachShadow({ mode: 'open' }); + root.innerHTML = `${SVG}`; + } + + get value(): string { + return this.getAttribute('value') ?? '1u'; + } + set value(v: string) { + this.setAttribute('value', String(v)); + } +} + +if (!customElements.get('wokwi-capacitor')) { + customElements.define('wokwi-capacitor', CapacitorElement); +} diff --git a/frontend/src/wokwi-custom/index.ts b/frontend/src/wokwi-custom/index.ts new file mode 100644 index 00000000..59d8db36 --- /dev/null +++ b/frontend/src/wokwi-custom/index.ts @@ -0,0 +1,18 @@ +/** + * Velxio-local custom elements. + * + * These are wokwi-style web components that live IN this project rather + * than in the upstream `@wokwi/elements` package — useful when we don't + * have push access to wokwi/wokwi-elements but still need to ship new + * parts (e.g. ``, `` for SPICE). + * + * Side-effect import: each module calls `customElements.define(...)` at + * load time (guarded against double-registration), so a single + * `import './wokwi-custom';` is enough to make the tags resolvable. + */ + +import './capacitor-element'; +import './inductor-element'; + +export { CapacitorElement } from './capacitor-element'; +export { InductorElement } from './inductor-element'; diff --git a/frontend/src/wokwi-custom/inductor-element.ts b/frontend/src/wokwi-custom/inductor-element.ts new file mode 100644 index 00000000..3c60983e --- /dev/null +++ b/frontend/src/wokwi-custom/inductor-element.ts @@ -0,0 +1,52 @@ +/** + * — local replacement for the upstream wokwi-elements + * version. Kept inside velxio because we cannot push the original Lit + * sources to wokwi/wokwi-elements. + * + * Plain HTMLElement (no Lit) — the SVG is static and `value` is read by + * the SPICE layer from the simulator store, not from this DOM node. + */ + +interface ElementPin { + name: string; + x: number; + y: number; + signals: unknown[]; +} + +const SVG = ` + + + + + +`; + +export class InductorElement extends HTMLElement { + static observedAttributes = ['value']; + + readonly pinInfo: ElementPin[] = [ + { name: '1', x: 0, y: 5.65, signals: [] }, + { name: '2', x: 58.8, y: 5.65, signals: [] }, + ]; + + constructor() { + super(); + const root = this.attachShadow({ mode: 'open' }); + root.innerHTML = `${SVG}`; + } + + get value(): string { + return this.getAttribute('value') ?? '1m'; + } + set value(v: string) { + this.setAttribute('value', String(v)); + } +} + +if (!customElements.get('wokwi-inductor')) { + customElements.define('wokwi-inductor', InductorElement); +}