diff --git a/packages/renderers/src/components/closeCellButton.ts b/packages/renderers/src/components/closeCellButton.ts index c0513cb..e07f18e 100644 --- a/packages/renderers/src/components/closeCellButton.ts +++ b/packages/renderers/src/components/closeCellButton.ts @@ -1,7 +1,8 @@ import { LitElement, css, html } from 'lit' -import { customElement } from 'lit/decorators.js' -@customElement('close-cell-button') +import { safeCustomElement } from '../decorators' + +@safeCustomElement('close-cell-button') export class CloseCellButton extends LitElement { /* eslint-disable */ static styles = css` diff --git a/packages/renderers/src/components/console/actionButton.ts b/packages/renderers/src/components/console/actionButton.ts index 5f1d9eb..a50eced 100644 --- a/packages/renderers/src/components/console/actionButton.ts +++ b/packages/renderers/src/components/console/actionButton.ts @@ -1,11 +1,12 @@ import { LitElement, css, html } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' import { when } from 'lit/directives/when.js' +import { safeCustomElement } from '../../decorators' import { SaveIcon } from '../icons/save' import { ShareIcon } from '../icons/share' -@customElement('action-button') +@safeCustomElement('action-button') export class ActionButton extends LitElement { @property({ type: String }) text: string = 'Copy' diff --git a/packages/renderers/src/components/console/gistCell.ts b/packages/renderers/src/components/console/gistCell.ts index 33c9aab..ccce403 100644 --- a/packages/renderers/src/components/console/gistCell.ts +++ b/packages/renderers/src/components/console/gistCell.ts @@ -1,10 +1,11 @@ import { LitElement, css, html } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' import { when } from 'lit/directives/when.js' +import { safeCustomElement } from '../../decorators' import { GistIcon } from '../icons/gistIcon' -@customElement('gist-cell') +@safeCustomElement('gist-cell') export class GistCell extends LitElement { @property({ type: String }) text: string = 'Preview & Gist' diff --git a/packages/renderers/src/components/console/open.ts b/packages/renderers/src/components/console/open.ts index c156140..284487d 100644 --- a/packages/renderers/src/components/console/open.ts +++ b/packages/renderers/src/components/console/open.ts @@ -1,10 +1,11 @@ import { LitElement, css, html } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' import { when } from 'lit/directives/when.js' +import { safeCustomElement } from '../../decorators' import { EyeIcon } from '../icons/eye' -@customElement('open-cell') +@safeCustomElement('open-cell') export class OpenCell extends LitElement { @property({ type: String }) openText: string = 'Open' diff --git a/packages/renderers/src/components/console/runme.ts b/packages/renderers/src/components/console/runme.ts index afc5c3f..88923b5 100644 --- a/packages/renderers/src/components/console/runme.ts +++ b/packages/renderers/src/components/console/runme.ts @@ -10,11 +10,12 @@ import { import { create } from '@bufbuild/protobuf' import { Interceptor } from '@connectrpc/connect' import { LitElement, PropertyValues, html } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' import { Disposable } from 'vscode' import { type RendererContext } from 'vscode-notebook-renderer' import { type VSCodeEvent } from 'vscode-notebook-renderer/events' +import { safeCustomElement } from '../../decorators' import { setContext } from '../../messaging' import Streams from '../../streams' import { ClientMessages } from '../../types' @@ -31,7 +32,7 @@ export interface RunmeConsoleStream { export const RUNME_CONSOLE = 'runme-console' -@customElement(RUNME_CONSOLE) +@safeCustomElement(RUNME_CONSOLE) export class RunmeConsole extends LitElement { protected disposables: Disposable[] = [] diff --git a/packages/renderers/src/components/console/saveButton.ts b/packages/renderers/src/components/console/saveButton.ts index f166e5d..905cdce 100644 --- a/packages/renderers/src/components/console/saveButton.ts +++ b/packages/renderers/src/components/console/saveButton.ts @@ -1,9 +1,10 @@ import { LitElement, html } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' +import { safeCustomElement } from '../../decorators' import './actionButton' -@customElement('save-button') +@safeCustomElement('save-button') export class SaveButton extends LitElement { @property({ type: Boolean, reflect: true }) loading: boolean = false diff --git a/packages/renderers/src/components/console/shareButton.ts b/packages/renderers/src/components/console/shareButton.ts index 54dac10..17f8b36 100644 --- a/packages/renderers/src/components/console/shareButton.ts +++ b/packages/renderers/src/components/console/shareButton.ts @@ -1,9 +1,10 @@ import { LitElement, html } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' +import { safeCustomElement } from '../../decorators' import './actionButton' -@customElement('share-button') +@safeCustomElement('share-button') export class ShareButton extends LitElement { @property({ type: Boolean, reflect: true }) loading: boolean = false diff --git a/packages/renderers/src/components/console/view.ts b/packages/renderers/src/components/console/view.ts index e3a999a..51bbd43 100644 --- a/packages/renderers/src/components/console/view.ts +++ b/packages/renderers/src/components/console/view.ts @@ -3,7 +3,7 @@ import { Unicode11Addon } from '@xterm/addon-unicode11' import { WebLinksAddon } from '@xterm/addon-web-links' import { ITheme, Terminal as XTermJS } from '@xterm/xterm' import { LitElement, PropertyValues, css, html, unsafeCSS } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' import { when } from 'lit/directives/when.js' import { Observable } from 'rxjs' import { @@ -15,6 +15,7 @@ import { } from 'rxjs/operators' import { Disposable, TerminalDimensions } from 'vscode' +import { safeCustomElement } from '../../decorators' import { FitAddon, type ITerminalDimensions } from '../../fitAddon' import { getContext, onClientMessage, postClientMessage } from '../../messaging' import { ClientMessages, OutputType, WebViews } from '../../types' @@ -90,7 +91,7 @@ const ANSI_COLORS = [ export const CONSOLE_VIEW = 'console-view' -@customElement(CONSOLE_VIEW) +@safeCustomElement(CONSOLE_VIEW) export class ConsoleView extends LitElement { protected copyText = 'Copy' diff --git a/packages/renderers/src/components/copyButton.ts b/packages/renderers/src/components/copyButton.ts index 498e6a8..38e0c3b 100644 --- a/packages/renderers/src/components/copyButton.ts +++ b/packages/renderers/src/components/copyButton.ts @@ -1,9 +1,10 @@ import { LitElement, css, html } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' +import { safeCustomElement } from '../decorators' import { CopyIcon } from './icons/copy' -@customElement('copy-button') +@safeCustomElement('copy-button') export class CopyButton extends LitElement { @property({ type: String }) copyText: string = 'Copy' diff --git a/packages/renderers/src/components/dropdownlist.ts b/packages/renderers/src/components/dropdownlist.ts index 76a7928..3f193ae 100644 --- a/packages/renderers/src/components/dropdownlist.ts +++ b/packages/renderers/src/components/dropdownlist.ts @@ -1,5 +1,7 @@ import { LitElement, css, html } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' + +import { safeCustomElement } from '../decorators' export interface DropdownListOption { text: string @@ -12,7 +14,7 @@ export type DropdownListEvent = { key: string } -@customElement('dropdown-list') +@safeCustomElement('dropdown-list') export class DropdownList extends LitElement { @property({ type: String }) label: string | undefined diff --git a/packages/renderers/src/components/env/store.ts b/packages/renderers/src/components/env/store.ts index 001dec9..b2d0353 100644 --- a/packages/renderers/src/components/env/store.ts +++ b/packages/renderers/src/components/env/store.ts @@ -1,9 +1,10 @@ import { MonitorEnvStoreResponseSnapshot_SnapshotEnv } from '@buf/runmedev_runme.bufbuild_es/runme/runner/v2/runner_pb' import { MonitorEnvStoreResponseSnapshot_Status } from '@buf/runmedev_runme.bufbuild_es/runme/runner/v2/runner_pb' import { LitElement, TemplateResult, html } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' import { Disposable } from 'vscode' +import { safeCustomElement } from '../../decorators' import { formatDate, formatDateWithTimeAgo } from '../../utils' import '../envViewer' import { CustomErrorIcon } from '../icons/error' @@ -45,7 +46,7 @@ const COLUMNS = [ const HIDDEN_COLUMNS = ['resolvedValue', 'errors', 'status', 'specClass'] -@customElement('env-store') +@safeCustomElement('env-store') export default class Table extends LitElement { protected disposables: Disposable[] = [] diff --git a/packages/renderers/src/components/envViewer.ts b/packages/renderers/src/components/envViewer.ts index 13b91ba..d781d52 100644 --- a/packages/renderers/src/components/envViewer.ts +++ b/packages/renderers/src/components/envViewer.ts @@ -1,16 +1,17 @@ import { MonitorEnvStoreResponseSnapshot_Status } from '@buf/runmedev_runme.bufbuild_es/runme/runner/v2/runner_pb' import { LitElement, TemplateResult, css, html } from 'lit' -import { customElement, property, state } from 'lit/decorators.js' +import { property, state } from 'lit/decorators.js' import { when } from 'lit/directives/when.js' import { Disposable } from 'vscode' +import { safeCustomElement } from '../decorators' import { CheckIcon } from './icons/check' import { CopyIcon } from './icons/copy' import { EyeIcon } from './icons/eye' import { EyeClosedIcon } from './icons/eyeClosed' import './tooltip' -@customElement('env-viewer') +@safeCustomElement('env-viewer') export class EnvViewer extends LitElement implements Disposable { protected disposables: Disposable[] = [] diff --git a/packages/renderers/src/components/table/index.ts b/packages/renderers/src/components/table/index.ts index 8c2e210..0d051da 100644 --- a/packages/renderers/src/components/table/index.ts +++ b/packages/renderers/src/components/table/index.ts @@ -1,13 +1,15 @@ import { LitElement, TemplateResult, css, html, nothing } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' import { when } from 'lit/directives/when.js' +import { safeCustomElement } from '../../decorators' + export interface Column { text: string colspan?: number | undefined } -@customElement('table-view') +@safeCustomElement('table-view') export class Table extends LitElement { @property({ type: Array }) columns?: Column[] = [] diff --git a/packages/renderers/src/components/tooltip.ts b/packages/renderers/src/components/tooltip.ts index 59321ba..424b40d 100644 --- a/packages/renderers/src/components/tooltip.ts +++ b/packages/renderers/src/components/tooltip.ts @@ -1,8 +1,10 @@ import { LitElement, TemplateResult, css, html } from 'lit' -import { customElement, property } from 'lit/decorators.js' +import { property } from 'lit/decorators.js' import { when } from 'lit/directives/when.js' -@customElement('tooltip-text') +import { safeCustomElement } from '../decorators' + +@safeCustomElement('tooltip-text') export class Tooltip extends LitElement { @property({ type: String }) tooltipText: string | TemplateResult<1> | undefined diff --git a/packages/renderers/src/decorators.ts b/packages/renderers/src/decorators.ts new file mode 100644 index 0000000..c427956 --- /dev/null +++ b/packages/renderers/src/decorators.ts @@ -0,0 +1,12 @@ +/** + * A safe version of @customElement that checks if the element is already defined + * before registering it. This prevents errors when the same module is imported multiple times. + */ +export function safeCustomElement(tagName: string) { + return function (constructor: T): T { + if (!customElements.get(tagName)) { + customElements.define(tagName, constructor) + } + return constructor + } +}