wcl_wdoc 0.11.2-alpha

WCL documentation format — build structured docs with WCL, render to HTML
    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))
    }