feat(quick-260921-qd3): XFrame-Widget - Webseite als Rahmen im Dashboard, Sandbox ohne Top-Navigation, Neuladen-Intervall
- xframe-config.ts: Resolver (https-Pruefung via isHttpsUrl des Bilderrahmens, Titel bis 100 Zeichen, Neuladen 0/60/300/600/1800/3600 s geklemmt), XFRAME_SANDBOX ohne allow-top-navigation und allow-modals; 12 Tests zuerst rot - xframe-widget.tsx: genau ein <iframe> (sandbox, allow="", no-referrer, lazy), Kopfleiste mit Titel oder Ecksymbol "In neuem Tab oeffnen", Neuladen ueber key-Wechsel mit Timer-Raeumung, transparente Flaeche im Bearbeitungsmodus damit die Kachel Ziehgriff bleibt; 12 Tests zuerst rot - xframe-config-form.tsx: Adresse/Titel mit Uebernahme bei Blur/Enter, http wird mit Meldung abgewiesen und nicht gespeichert, Intervall-Auswahl, dauerhafter Hinweis auf verweigertes Einbetten; 8 Tests - Panel-Zweig samt "— Titel" in der Kopfzeile, Registry (12x12, Fenster-Symbol), Katalog, Seite, DTO @IsIn, de/en widgets.xframe (15 Schluessel), Umlaut-Allowlist "neuem"; der Server ruft die Adresse nie ab Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import type { ComponentType } from 'react';
|
||||
* Einzel-Schnellzugriffs-Typ wurde in quick-260916-iex entfernt — Favoriten
|
||||
* decken den Fall ab).
|
||||
* picture-frame: Bilderrahmen (quick-260921-pi9).
|
||||
* xframe: Webseite als Rahmen (quick-260921-qd3).
|
||||
*/
|
||||
export type WidgetType =
|
||||
| 'clock'
|
||||
@@ -16,7 +17,8 @@ export type WidgetType =
|
||||
| 'calculator'
|
||||
| 'favorites'
|
||||
| 'stopwatch'
|
||||
| 'picture-frame';
|
||||
| 'picture-frame'
|
||||
| 'xframe';
|
||||
|
||||
/**
|
||||
* Props contract that every widget component must accept.
|
||||
@@ -60,6 +62,11 @@ export const WIDGET_CONSTRAINTS: Record<
|
||||
// Browser-Rundgang mit 216 px Hoehe zu flach. 4x4 ist die kleinste Kachel,
|
||||
// in der Bild und Unterschrift-Streifen noch erkennbar sind.
|
||||
'picture-frame': { minW: 4, minH: 4, defaultW: 8, defaultH: 12 },
|
||||
// quick-260921-qd3: eine Webseite braucht Breite UND Hoehe — 12x12 = halbe
|
||||
// Rasterbreite bei rund 330 px Hoehe (8 Zeilen waeren nur 216 px, zu flach
|
||||
// fuer eine Seite; vgl. Bilderrahmen 8x12). 4x4 kleinste Kachel, in der ein
|
||||
// Rahmen noch Sinn hat.
|
||||
xframe: { minW: 4, minH: 4, defaultW: 12, defaultH: 12 },
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -277,6 +284,29 @@ function PictureFrameIcon({ className }: { className?: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
function XframeIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className={className}
|
||||
>
|
||||
<rect x="3" y="4" width="18" height="16" rx="2" />
|
||||
<line x1="3" y1="9" x2="21" y2="9" />
|
||||
<circle cx="6.5" cy="6.5" r="0.5" />
|
||||
<circle cx="9.5" cy="6.5" r="0.5" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registry of all widget types. Used by the widget catalog modal
|
||||
* and the grid renderer to look up components and constraints.
|
||||
@@ -346,6 +376,14 @@ export const WIDGET_REGISTRY: Record<WidgetType, WidgetDefinition> = {
|
||||
...WIDGET_CONSTRAINTS['picture-frame'],
|
||||
component: PlaceholderWidget, // Replaced via wirePictureFrameWidget()
|
||||
},
|
||||
xframe: {
|
||||
type: 'xframe',
|
||||
nameKey: 'xframe.name',
|
||||
descriptionKey: 'xframe.description',
|
||||
icon: XframeIcon,
|
||||
...WIDGET_CONSTRAINTS.xframe,
|
||||
component: PlaceholderWidget, // Replaced via wireXframeWidget()
|
||||
},
|
||||
};
|
||||
|
||||
// Wire actual widget components lazily to avoid circular deps
|
||||
@@ -415,3 +453,11 @@ export function wirePictureFrameWidget(component: ComponentType<WidgetProps>) {
|
||||
pictureFrameWired = true;
|
||||
}
|
||||
}
|
||||
|
||||
let xframeWired = false;
|
||||
export function wireXframeWidget(component: ComponentType<WidgetProps>) {
|
||||
if (!xframeWired) {
|
||||
WIDGET_REGISTRY.xframe.component = component;
|
||||
xframeWired = true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user