expose h_align/v_align through full stack

display_hint becomes {kind, h_align, v_align} object in API, SQLite
gets alignment columns, SPA widget form gets alignment selects, layout
preview reflects actual alignment instead of hardcoded center
This commit is contained in:
2026-06-19 10:28:09 +02:00
parent ca2ef61097
commit b448fa15fe
8 changed files with 200 additions and 43 deletions

View File

@@ -7,7 +7,7 @@ import {
useWidgetPreview,
} from "@/api/widgets"
import { useDataSources } from "@/api/data-sources"
import type { Widget, DisplayHint, KeyMapping } from "@/api/types"
import type { Widget, DisplayHintKind, HAlign, VAlign, KeyMapping } from "@/api/types"
import { Button } from "@/components/ui/button"
import {
Card,
@@ -46,13 +46,12 @@ import { Badge } from "@/components/ui/badge"
import { Plus, Pencil, Trash2, X, Eye } from "lucide-react"
import { toast } from "sonner"
const DISPLAY_HINTS: DisplayHint[] = ["icon_value", "text_block", "key_value"]
const DISPLAY_HINT_KINDS: DisplayHintKind[] = ["icon_value", "text_block", "key_value"]
const EMPTY: Widget = {
id: 0,
name: "",
display_hint: "icon_value",
display_hint: { kind: "icon_value", h_align: "left", v_align: "top" },
data_source_id: 0,
mappings: [],
max_data_size: 2048,
@@ -141,7 +140,7 @@ export function WidgetsPage() {
<div className="space-y-1">
<CardTitle className="text-base">{w.name}</CardTitle>
<CardDescription className="flex items-center gap-2">
<Badge variant="secondary">{w.display_hint}</Badge>
<Badge variant="secondary">{w.display_hint.kind}</Badge>
<span>source: {sourceName(w.data_source_id)}</span>
<span>{w.mappings.length} mapping(s)</span>
</CardDescription>
@@ -326,14 +325,14 @@ function WidgetForm({
<div className="grid gap-2">
<Label>Display Hint</Label>
<Select
value={value.display_hint}
onValueChange={(v) => set("display_hint", v as DisplayHint)}
value={value.display_hint.kind}
onValueChange={(v) => set("display_hint", { ...value.display_hint, kind: v as DisplayHintKind })}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
{DISPLAY_HINTS.map((h) => (
{DISPLAY_HINT_KINDS.map((h) => (
<SelectItem key={h} value={h}>
{h}
</SelectItem>
@@ -341,6 +340,40 @@ function WidgetForm({
</SelectContent>
</Select>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid gap-2">
<Label>H Align</Label>
<Select
value={value.display_hint.h_align}
onValueChange={(v) => set("display_hint", { ...value.display_hint, h_align: v as HAlign })}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="left">Left</SelectItem>
<SelectItem value="center">Center</SelectItem>
<SelectItem value="right">Right</SelectItem>
</SelectContent>
</Select>
</div>
<div className="grid gap-2">
<Label>V Align</Label>
<Select
value={value.display_hint.v_align}
onValueChange={(v) => set("display_hint", { ...value.display_hint, v_align: v as VAlign })}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="top">Top</SelectItem>
<SelectItem value="middle">Middle</SelectItem>
<SelectItem value="bottom">Bottom</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div className="grid gap-2">
<Label>Data Source</Label>
<Select