package webui import "kjol/wasmruntime/vdom" // Port of web/kit/PrettyTable.tsx. // // PrettyTable renders only the table chrome: the container/wrapper, the styled // , and an empty-styled
into which the CALLER passes body rows as // children. That matches the TSX, whose body is `props.children` (rows built with // AutoTable's TdLeft/TdRight/TdCenter cells). Those cell helpers live in AutoTable // (not ported here), so callers build rows with the vdom tag builders directly, // e.g. vdom.Tr(vdom.Td(vdom.Attr("class","text-right"), vdom.Text(...))). // (CellGrid is the component that models columns + a per-cell Render func.) // // The enum values, class maps, and shared class strings that PrettyTable.tsx // imports from AutoTable.tsx are inlined here (prefixed pt*/PrettyTable*) so this // file compiles on its own and never clashes with a parallel AutoTable port. // PrettyTableColumnPosition controls header + cell alignment. type PrettyTableColumnPosition int const ( PrettyTableColLeft PrettyTableColumnPosition = 0 PrettyTableColRight PrettyTableColumnPosition = 1 PrettyTableColCenter PrettyTableColumnPosition = 2 ) // PrettyTableHeaderColor selects the header background/text palette. type PrettyTableHeaderColor int const ( PrettyTableColorDefault PrettyTableHeaderColor = 0 PrettyTableColorBlue PrettyTableHeaderColor = 1 PrettyTableColorGreen PrettyTableHeaderColor = 2 PrettyTableColorGray PrettyTableHeaderColor = 3 PrettyTableColorDarkBlue PrettyTableHeaderColor = 4 ) // PrettyTableSize selects header/body padding density. type PrettyTableSize int const ( PrettyTableSizeDefault PrettyTableSize = 0 PrettyTableSizeCompact PrettyTableSize = 1 PrettyTableSizeSuperCompact PrettyTableSize = 2 ) const ptTblContainer = "relative flex flex-col w-full h-full bg-surface rounded-default overflow-hidden" const ptTblWrapper = "overflow-x-auto w-full" const ptTblBase = "min-w-full" const ptHeaderContent = "transition-transform duration-150 ease-in-out" const ptHeaderInnerBase = "flex justify-between gap-2 items-center" var ptHeaderColorCls = map[PrettyTableHeaderColor]string{ PrettyTableColorDefault: "bg-surface-muted", PrettyTableColorBlue: "bg-sky-700 text-white", PrettyTableColorGreen: "bg-green-700 text-white", PrettyTableColorGray: "bg-neutral-600 text-white", PrettyTableColorDarkBlue: "bg-sky-900 text-white", } var ptHeaderTextCls = map[PrettyTableHeaderColor]string{ PrettyTableColorDefault: "font-bold uppercase tracking-wider", PrettyTableColorBlue: "font-semibold", PrettyTableColorGreen: "font-semibold", PrettyTableColorGray: "font-semibold", PrettyTableColorDarkBlue: "font-semibold", } // ptRowHoverCls is applied to the tbody when Hover is on (matches the TSX // PT_ROW_HOVER_CLS map). var ptRowHoverCls = map[PrettyTableHeaderColor]string{ PrettyTableColorDefault: "[&_tr:hover]:!bg-surface-strong", PrettyTableColorBlue: "[&_tr:hover]:!bg-sky-100 dark:bg-sky-900", PrettyTableColorGreen: "[&_tr:hover]:!bg-green-100 dark:bg-green-900", PrettyTableColorGray: "[&_tr:hover]:!bg-surface-strong", PrettyTableColorDarkBlue: "[&_tr:hover]:!bg-sky-100 dark:bg-sky-900", } var ptHeaderPaddingCls = map[PrettyTableSize]string{ PrettyTableSizeDefault: "p-4 text-sm", PrettyTableSizeCompact: "py-1.5 px-2 text-sm", PrettyTableSizeSuperCompact: "py-1 px-2 text-ss", } var ptBodyPaddingCls = map[PrettyTableSize]string{ PrettyTableSizeDefault: "text-sm [&_td]:p-4", PrettyTableSizeCompact: "text-sm [&_td]:py-1 [&_td]:px-2", PrettyTableSizeSuperCompact: "text-ss [&_td]:py-0.5 [&_td]:px-2", } var ptPosCls = map[PrettyTableColumnPosition]string{ PrettyTableColLeft: "text-left", PrettyTableColRight: "text-right", PrettyTableColCenter: "text-center", } var ptHeaderInnerPos = map[PrettyTableColumnPosition]string{ PrettyTableColLeft: "", PrettyTableColRight: "flex-row-reverse", PrettyTableColCenter: "justify-center", } // PrettyTableColumn is one header column definition. type PrettyTableColumn struct { DisplayName string DisplayPosition PrettyTableColumnPosition HeaderClasses string } // PrettyTableOptions configures the table chrome. The Go zero value matches the // TSX defaults exactly (size default, all flags off, default color, left align), // so an unset PrettyTableOptions{} needs no merge. type PrettyTableOptions struct { Size PrettyTableSize Shadow bool Hover bool Alternate bool HeaderBorderY bool SurroundingBorder bool BorderX bool BorderY bool Color PrettyTableHeaderColor TableLayoutAuto bool } func prettyTableBodyClass(o PrettyTableOptions) string { c := ptBodyPaddingCls[o.Size] if o.BorderY { c = cx(c, "[&_td+td]:border-l [&_td+td]:border-line-strong") } if o.Alternate { c = cx(c, "[&_tr:nth-child(even)]:bg-surface-raised") } if o.BorderX { c = cx(c, "[&_tr:not(:last-child)]:border-b [&_tr:not(:last-child)]:border-line-strong") } if o.Hover { c = cx(c, ptRowHoverCls[o.Color]) } return c } // PrettyTable renders the table container + styled header, with body rows passed // as children (see the file comment). opts may be the zero value for defaults. func PrettyTable(columns []PrettyTableColumn, opts PrettyTableOptions, children ...*vdom.VNode) *vdom.VNode { containerCls := ptTblContainer if opts.SurroundingBorder { containerCls = cx(containerCls, "border border-line-strong") } if opts.Shadow { containerCls = cx(containerCls, "shadow-sm") } tableCls := ptTblBase if !opts.TableLayoutAuto { tableCls = cx(tableCls, "table-fixed") } var headerCells []*vdom.VNode for displayIdx, col := range columns { pos := col.DisplayPosition thCls := cx(ptHeaderPaddingCls[opts.Size], ptHeaderColorCls[opts.Color], ptPosCls[pos]) if opts.HeaderBorderY && displayIdx > 0 { thCls = cx(thCls, "border-l border-l-neutral-300") } thCls = cx(thCls, col.HeaderClasses) innerCls := cx(ptHeaderInnerBase, ptHeaderInnerPos[pos]) headerCells = append(headerCells, vdom.Th(vdom.Attr("class", thCls), vdom.Div(vdom.Attr("class", ptHeaderContent), vdom.Div(vdom.Attr("class", innerCls), vdom.Div(vdom.Attr("class", cx("grow text-sm", ptHeaderTextCls[opts.Color])), vdom.Text(col.DisplayName), ), ), ), )) } thead := vdom.Thead(vdom.Attr("class", "[&_th]:border-b [&_th]:border-line-strong"), vdom.Tr(kids(nil, headerCells)...), ) tbody := vdom.Tbody(kids([]vdom.Mod{vdom.Attr("class", prettyTableBodyClass(opts))}, children)...) return vdom.Div(vdom.Attr("class", containerCls), vdom.Div(vdom.Attr("class", ptTblWrapper), vdom.Table(vdom.Attr("class", tableCls), thead, tbody), ), ) }