export let datatable_columns_from_blocks = (b) => {
let cols = filter(wdoc::block_children(b), (child) => child.kind == "wdoc::draw::datatable_column")
let result = map(cols, (col) => {
id = attr_or(col, "key", col.id),
label = attr_or(col, "label", attr_or(col, "title", col.id)),
width = attr_or(col, "width", 0)
})
result
}
export let datatable_columns_from_names = (names) => {
let result = map(names, (name) => {
id = trim(name),
label = trim(name),
width = 0
})
result
}
export let datatable_columns_from_rows = (rows) => {
let row_keys = len(rows) > 0 ? keys(rows[0]) : []
let result = map(row_keys, (key) => {
id = key,
label = key,
width = 0
})
result
}
export let datatable_columns = (b, rows) => {
let block_cols = wdoc::datatable_columns_from_blocks(b)
let names = split(",", attr_or(b, "columns", ""))
len(block_cols) > 0 ? block_cols : (
attr_or(b, "columns", "") != "" ? wdoc::datatable_columns_from_names(names) : wdoc::datatable_columns_from_rows(rows)
)
}
export let datatable_column_width = (cols, index, table_w) => {
let explicit = cols[index].width
let explicit_total = sum(map(cols, col => col.width))
let flexible_count = len(filter(cols, col => col.width <= 0))
explicit > 0 ? explicit : ((table_w - explicit_total) / (flexible_count > 0 ? flexible_count : len(cols)))
}
export let datatable_column_x = (cols, index, table_w) => {
let widths = map(range(0, index), i => wdoc::datatable_column_width(cols, i, table_w))
sum(widths)
}
export let datatable_cell_block = (row, col_id) => {
let cells = filter(wdoc::block_children(row), cell =>
cell.kind == "wdoc::draw::datatable_cell" &&
(to_string(cell.id) == col_id || attr_or(cell, "column", "") == col_id || attr_or(cell, "key", "") == col_id)
)
len(cells) > 0 ? cells[0] : null
}
export let datatable_cell_text_items = (cell) => {
let cell_children = cell == null ? [] : wdoc::block_children(cell)
let text_children = filter(cell_children, child =>
child.kind == "wdoc::draw::paragraph" || child.kind == "wdoc::draw::p" || child.kind == "wdoc::draw::code" ||
child.kind == "wdoc::paragraph" || child.kind == "wdoc::p" || child.kind == "wdoc::code" ||
child.kind == "paragraph" || child.kind == "p" || child.kind == "code"
)
let result = map(text_children, child => {
kind = (child.kind == "wdoc::draw::code" || child.kind == "wdoc::code" || child.kind == "code") ? "code" : "paragraph"
content = attr_or(child, "content", "")
language = attr_or(child, "language", "")
})
result
}
export let datatable_cell_controls = (cell) => {
let cell_children = cell == null ? [] : wdoc::block_children(cell)
let result = filter(cell_children, child =>
child.kind != "wdoc::draw::paragraph" && child.kind != "wdoc::draw::p" && child.kind != "wdoc::draw::code" &&
child.kind != "wdoc::paragraph" && child.kind != "wdoc::p" && child.kind != "wdoc::code" &&
child.kind != "paragraph" && child.kind != "p" && child.kind != "code"
)
result
}
export let datatable_text_shape = (x, y, w, h, content, items, cell_padding, font_size, fill) => {
let has_text = content != "" || len(items) > 0
has_text ? [{
kind = "text_block",
x = x + cell_padding,
y = y + cell_padding,
width = w - cell_padding * 2,
height = h - cell_padding * 2,
content = content,
items = items,
font_size = font_size,
line_height = 1.25,
gap = 4,
fill = fill
}] : []
}
export let datatable_control_group = (x, y, w, h, controls, cell_padding) => {
let groups = [{
kind = "group",
x = x + cell_padding,
y = y + cell_padding,
width = w - cell_padding * 2,
height = h - cell_padding * 2,
children = controls
}]
len(controls) > 0 ? groups : []
}
export let datatable_block_cell_shapes = (row, col, x, y, w, h, cell_padding, font_size, fill) => {
let cell = wdoc::datatable_cell_block(row, to_string(col.id))
let content = cell == null ? "" : attr_or(cell, "content", "")
concat(
wdoc::datatable_text_shape(x, y, w, h, content, wdoc::datatable_cell_text_items(cell), cell_padding, font_size, fill),
wdoc::datatable_control_group(x, y, w, h, wdoc::datatable_cell_controls(cell), cell_padding)
)
}
export let datatable_compact_cell_shapes = (row, col, x, y, w, h, cell_padding, font_size, fill) => {
let result = wdoc::datatable_text_shape(x, y, w, h, to_string(row[col.id]), [], cell_padding, font_size, fill)
result
}
export let datatable_row_y = (index, header_h, row_h) => header_h + index * row_h
export let datatable_row_shapes = (rows, block_rows, cols, row_index, table_w, header_h, row_h, cell_padding, font_size, fill) => {
let y = wdoc::datatable_row_y(row_index, header_h, row_h)
let is_block = row_index < len(block_rows)
let row = is_block ? block_rows[row_index] : rows[row_index - len(block_rows)]
flatten(map(range(0, len(cols)), col_index => {
let col = cols[col_index]
let x = wdoc::datatable_column_x(cols, col_index, table_w)
let cw = wdoc::datatable_column_width(cols, col_index, table_w)
is_block ? wdoc::datatable_block_cell_shapes(row, col, x, y, cw, row_h, cell_padding, font_size, fill) : wdoc::datatable_compact_cell_shapes(row, col, x, y, cw, row_h, cell_padding, font_size, fill)
}))
}
export let datatable_grid_shapes = (cols, row_count, table_w, table_h, header_h, row_h, grid_stroke, border_stroke) => {
let verticals = map(range(1, len(cols)), i => {
kind = "line"
x1 = wdoc::datatable_column_x(cols, i, table_w)
y1 = 0
x2 = wdoc::datatable_column_x(cols, i, table_w)
y2 = table_h
stroke = grid_stroke
stroke_width = 1
})
let horizontals = map(range(0, row_count + 1), i => {
kind = "line"
x1 = 0
y1 = header_h + i * row_h
x2 = table_w
y2 = header_h + i * row_h
stroke = i == 0 ? border_stroke : grid_stroke
stroke_width = i == 0 ? 1.5 : 1
})
concat(verticals, horizontals)
}
export let datatable_header_shapes = (cols, table_w, header_h, cell_padding, font_size, fill) => {
let result = flatten(map(range(0, len(cols)), i => {
let col = cols[i]
let x = wdoc::datatable_column_x(cols, i, table_w)
let cw = wdoc::datatable_column_width(cols, i, table_w)
[{
kind = "text",
x = x + cell_padding,
y = 0,
width = cw - cell_padding * 2,
height = header_h,
content = col.label,
font_size = font_size,
font_weight = "600",
anchor = "start",
fill = fill
}]
}))
result
}
export let widget_datatable = (b) => {
let rows = attr_or(b, "rows", [])
let block_rows = filter(wdoc::block_children(b), child => child.kind == "wdoc::draw::datatable_row")
let cols = wdoc::datatable_columns(b, rows)
let row_count = len(block_rows) + len(rows)
let w = attr_or(b, "width", 420)
let row_h = attr_or(b, "row_height", 40)
let header_h = attr_or(b, "show_header", "true") == "false" ? 0 : attr_or(b, "header_height", 34)
let h = attr_or(b, "height", header_h + row_count * row_h)
let cell_padding = attr_or(b, "cell_padding", 10)
let radius = attr_or(b, "radius", 8)
let surface_fill = attr_or(b, "surface_fill", "var(--color-bg)")
let header_fill = attr_or(b, "header_fill", "var(--color-nav-bg)")
let border_stroke = attr_or(b, "border_stroke", "var(--color-nav-border)")
let grid_stroke = attr_or(b, "grid_stroke", border_stroke)
let label_fill = attr_or(b, "label_fill", "currentColor")
let header_label_fill = attr_or(b, "header_label_fill", label_fill)
let font_size = attr_or(b, "font_size", 12)
let header_font_size = attr_or(b, "header_font_size", 12)
let base = [
{ kind = "rect", x = 0, y = 0, width = w, height = h, rx = radius,
fill = surface_fill, stroke = border_stroke, stroke_width = 1.5,
_wdoc_full_container = "true" }
]
let header_bg = header_h > 0 ? [
{ kind = "rect", x = 0, y = 0, width = w, height = header_h, rx = radius, fill = header_fill },
{ kind = "rect", x = 0, y = header_h - radius, width = w, height = radius, fill = header_fill }
] : []
let headers = header_h > 0 ? wdoc::datatable_header_shapes(cols, w, header_h, cell_padding, header_font_size, header_label_fill) : []
let body = flatten(map(range(0, row_count), i => wdoc::datatable_row_shapes(rows, block_rows, cols, i, w, header_h, row_h, cell_padding, font_size, label_fill)))
concat(concat(concat(concat(base, header_bg), headers), body), wdoc::datatable_grid_shapes(cols, row_count, w, h, header_h, row_h, grid_stroke, border_stroke))
}