Skip to content
29 changes: 29 additions & 0 deletions packages/openscd/src/translations/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ export const de: Translations = {
toggleChildElements: 'Kindelemente umschalten',
settings: 'Services für IED or AccessPoint',
createIed: 'Virtuelles IED erstellen',
addAccessPoint: 'AccessPoint hinzufügen',
wizard: {
daTitle: 'DA Informationen anzeigen',
doTitle: 'DO Informationen anzeigen',
Expand All @@ -254,6 +255,34 @@ export const de: Translations = {
nameFormatError: 'IED Name darf keine Leerzeichen enthalten',
nameUniqueError: 'IED Name ist bereits vergeben',
},
addAccessPointDialog: {
title: 'AccessPoint hinzufügen',
nameHelper: 'AccessPoint Name',
descHelper: 'AccessPoint Beschreibung',
apName: 'AccessPoint Name',
createServerAt: 'ServerAt hinzufügen',
selectAccessPoint: 'AccessPoint auswählen',
serverAtDesc: 'ServerAt Beschreibung',
nameFormatError: 'AccessPoint Name darf keine Leerzeichen enthalten',
nameUniqueError: 'AccessPoint Name ist bereits vergeben',
nameTooLongError: 'AccessPoint Name ist zu lang',
},
addLDeviceDialog: {
title: 'LDevice hinzufügen',
inst: 'LDevice inst',
desc: 'LDevice Beschreibung',
instRequiredError: 'LDevice inst ist erforderlich',
instFormatError: 'LDevice inst darf keine Leerzeichen enthalten',
instUniqueError: 'LDevice inst ist bereits vergeben',
instTooLongError: 'LDevice inst ist zu lang',
},
addLnDialog: {
title: 'LN hinzufügen',
amount: 'Menge',
prefix: 'Prefix',
filter: 'Logical Node Types filtern',
noResults: 'Keine Logical Node Types gefunden',
},
},
ied: {
wizard: {
Expand Down
31 changes: 30 additions & 1 deletion packages/openscd/src/translations/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ export const en = {
toggleChildElements: 'Toggle child elements',
settings: 'Show Services the IED/AccessPoint provides',
createIed: 'Create Virtual IED',
addAccessPoint: 'Add AccessPoint',
wizard: {
daTitle: 'Show DA Info',
doTitle: 'Show DO Info',
Expand All @@ -247,10 +248,38 @@ export const en = {
daValue: 'Data attribute value',
},
createDialog: {
iedName: 'IED Name',
iedName: 'IED name',
nameFormatError: 'IED name cannot contain spaces',
nameUniqueError: 'IED name already exists',
},
addAccessPointDialog: {
title: 'Add AccessPoint',
nameHelper: 'AccessPoint name',
descHelper: 'AccessPoint description',
apName: 'AccessPoint name',
createServerAt: 'Add ServerAt',
selectAccessPoint: 'Select AccessPoint',
serverAtDesc: 'ServerAt description',
nameFormatError: 'AccessPoint name cannot contain spaces',
nameUniqueError: 'AccessPoint name already exists',
nameTooLongError: 'AccessPoint name is too long',
},
addLDeviceDialog: {
title: 'Add LDevice',
inst: 'LDevice inst',
desc: 'LDevice description',
instRequiredError: 'LDevice inst is required',
instFormatError: 'Invalid inst',
instUniqueError: 'LDevice inst already exists',
instTooLongError: 'LDevice inst is too long',
},
addLnDialog: {
title: 'Add LN',
amount: 'Amount',
prefix: 'Prefix',
filter: 'Filter Logical Node Types',
noResults: 'No Logical Node Types found',
},
},
ied: {
wizard: {
Expand Down
112 changes: 112 additions & 0 deletions packages/plugins/src/components/tooltip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import {
css,
customElement,
html,
LitElement,
property,
TemplateResult,
} from 'lit-element';

/** A tooltip element that follows the mouse cursor and displays a text box. */
@customElement('oscd-tooltip-4c6027dd')
export class OscdTooltip extends LitElement {
@property({ type: String })
text = '';

@property({ type: Boolean, reflect: true })
visible = false;

@property({ type: Number })
x = 0;

@property({ type: Number })
y = 0;

@property({ type: Number })
offset = 12;

private pendingFrame = 0;

show(text: string, clientX: number, clientY: number): void {
this.text = text;
this.visible = true;
this.updatePosition(clientX, clientY);
}

hide(): void {
this.visible = false;
this.text = '';
if (this.pendingFrame) {
cancelAnimationFrame(this.pendingFrame);
this.pendingFrame = 0;
}
}

updatePosition(clientX: number, clientY: number): void {
this.x = clientX + this.offset;
this.y = clientY + this.offset;

if (this.pendingFrame) return;

this.pendingFrame = requestAnimationFrame(() => {
this.pendingFrame = 0;
if (!this.visible) return;

const tipRect = this.getBoundingClientRect();
let x = this.x;
let y = this.y;

const innerW = window.innerWidth;
const innerH = window.innerHeight;

if (x + tipRect.width + this.offset > innerW) {
x = this.x - this.offset - tipRect.width - this.offset;
}
if (x < this.offset) x = this.offset;

if (y + tipRect.height + this.offset > innerH) {
y = this.y - this.offset - tipRect.height - this.offset;
}
if (y < this.offset) y = this.offset;

this.style.transform = `translate3d(${Math.round(x)}px, ${Math.round(
y
)}px, 0)`;
});
}

render(): TemplateResult {
return html`<slot>${this.text}</slot>`;
}

static styles = css`
:host {
position: fixed;
pointer-events: none;
background: rgba(20, 20, 20, 0.95);
color: rgba(240, 240, 240, 0.98);
padding: 6px 8px;
border-radius: 4px;
font-size: 0.85em;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
z-index: 6000;
max-width: 60vw;
border: 1px solid rgba(255, 255, 255, 0.04);
left: 0;
top: 0;
transform: translate3d(0, 0, 0);
will-change: transform;
opacity: 1;
transition: opacity 0.15s ease-in-out;
}

:host(:not([visible])) {
opacity: 0;
pointer-events: none;
}

:host([hidden]) {
display: none;
}
`;
}
Loading
Loading