feat(treetable): optionale Kopfzeile und abschaltbare Expand-Buttons
Neues Attribut header rendert eine sticky Spaltenüberschriftenzeile. showExpandButtons=false blendet die Ein-/Ausklappen-Buttons aus; die Topbar entfällt dann ganz, wenn auch keine Children oder Filter vorhanden sind — der scrollbare Bereich nutzt in dem Fall die volle Höhe. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
1 parent
3a6732e36b
commit
981b28df03
1 file changed
+55
-4
@@ -39,6 +39,20 @@ export interface iTreetable {
|
||||
* <tr>-Zeile; die columnmapper-Inhalte brauchen dann kein eigenes
|
||||
* Selektions-Styling mehr. */
|
||||
isSelected?: (node: iTreenode) => boolean
|
||||
/** Optional: Spaltenüberschriften (ein Titel je columnmapper-Spalte,
|
||||
* 1:1 von links nach rechts). Wenn gesetzt, rendert das Widget eine
|
||||
* Kopfzeile über den Datenzeilen. Hinweis zur ersten Spalte: Die
|
||||
* Einrückung/der Expand-Pfeil der Baumdarstellung liegt im selben
|
||||
* td wie die ERSTE columnmapper-Zelle — der erste Titel steht
|
||||
* daher direkt über der ersten Datenspalte. Die Kopfzeile bleibt
|
||||
* beim Scrollen sticky sichtbar. */
|
||||
header?: string[]
|
||||
/** Optional: Ein-/Ausklappen-Buttons (unfold_more/unfold_less) in der
|
||||
* Topbar anzeigen. Default true. Für flache Listen ohne Hierarchie
|
||||
* auf false setzen — die Topbar entfällt dann ganz, sofern auch
|
||||
* keine Children (z.B. TopbarButtons) übergeben und kein filter
|
||||
* gesetzt ist. */
|
||||
showExpandButtons?: boolean
|
||||
}
|
||||
|
||||
export const Treetable: m.ClosureComponent<iTreetable> = (vnode) => {
|
||||
@@ -58,8 +72,21 @@ export const Treetable: m.ClosureComponent<iTreetable> = (vnode) => {
|
||||
const topHasSiblingsWithChildren = vnode.attrs.treenodes.some(
|
||||
(tn: iTreenode) => tn.hasChildren
|
||||
)
|
||||
// Topbar (Expand-Buttons, Children, Suchfeld) nur rendern, wenn
|
||||
// tatsächlich Inhalt vorhanden ist — bei flachen Listen ohne
|
||||
// Expand-Buttons, Children und filter bleibt sie komplett weg.
|
||||
const showExpand = vnode.attrs.showExpandButtons !== false
|
||||
// vnode.children kann ein Array oder ein Primitiv sein
|
||||
// (Mithril-Typ ChildArrayOrPrimitive).
|
||||
const hatChildren = Array.isArray(vnode.children)
|
||||
? vnode.children.length > 0
|
||||
: vnode.children != null
|
||||
const hatTopbar = showExpand || hatChildren || vnode.attrs.filter != undefined
|
||||
return m("div.w3-border-theme", {style: {height: '99%', overflow: 'hidden', 'border-style': 'solid', 'border-width': '1px'}},
|
||||
m("div.w3-bar.w3-theme",
|
||||
hatTopbar
|
||||
? m("div.w3-bar.w3-theme",
|
||||
showExpand
|
||||
? [
|
||||
m(TopbarButton, {
|
||||
onclick: () => {
|
||||
expandtoggle = true; changeTreenodes(vnode.attrs.treenodes, expandtoggle)
|
||||
@@ -71,13 +98,37 @@ export const Treetable: m.ClosureComponent<iTreetable> = (vnode) => {
|
||||
expandtoggle = false; changeTreenodes(vnode.attrs.treenodes, expandtoggle)
|
||||
}},
|
||||
m("i.material-icons", "unfold_less")
|
||||
),
|
||||
)
|
||||
]
|
||||
: null,
|
||||
vnode.children,
|
||||
(vnode.attrs.filter != undefined) ? m(SearchField, {setSearchvalue: setSearchvalue} as iSearchfield) : null
|
||||
),
|
||||
)
|
||||
: null,
|
||||
m("div", {style: {height: '100%'}},
|
||||
m("div", {style: {height: 'calc(100% - 32px', overflow: 'auto', width: '100%'}},
|
||||
// Ohne Topbar nutzt der scrollbare Bereich die volle Höhe.
|
||||
m("div", {style: {height: hatTopbar ? 'calc(100% - 32px' : '100%', overflow: 'auto', width: '100%'}},
|
||||
m("table.w3-table", {style: {'overflow-y': 'auto'}},
|
||||
// Optionale Spaltenüberschriften: Ein Titel je
|
||||
// columnmapper-Spalte, 1:1 von links nach rechts
|
||||
// (die Einrückung teilt sich das td mit der
|
||||
// ersten Datenspalte, keine Führungs-Spalte).
|
||||
// Die Kopfzeile bleibt beim Scrollen sticky.
|
||||
vnode.attrs.header
|
||||
? m("thead",
|
||||
m("tr.w3-theme",
|
||||
vnode.attrs.header.map((titel: string) =>
|
||||
m("th", {
|
||||
style: {
|
||||
position: 'sticky',
|
||||
top: '0',
|
||||
'z-index': '1',
|
||||
'text-align': 'left',
|
||||
'white-space': 'nowrap'
|
||||
},
|
||||
title: titel
|
||||
}, titel))))
|
||||
: null,
|
||||
vnode.attrs.treenodes.map((tn:iTreenode, z) => {
|
||||
if (vnode.attrs.filter == undefined || (vnode.attrs.filter != undefined && vnode.attrs.filter(tn, searchvalue) == true)) {
|
||||
return m(Treerow, {
|
||||
|
||||
Reference in new issue
Block a user