Dash-math_Database / layout /page /sections.py
Mochi0622's picture
update files
d5d9742
Raw
History Blame Contribute Delete
3.35 kB
"""
layout/page/sections.py
------------------------
Section(分段)相關的資料邏輯與 UI 元件。
只依賴 Dash / DMC,不含任何 @callback。
公開 API:
split_blocks_into_sections(blocks) → List[section_dict]
get_section_blocks(sections, section_id) → List[block_dict]
make_section_control(sections, active_id) → html.Div | None
"""
from __future__ import annotations
from typing import Any
from dash import html
import dash_mantine_components as dmc
# ---------------------------------------------------------------------------
# 資料邏輯
# ---------------------------------------------------------------------------
def split_blocks_into_sections(blocks: list[dict]) -> list[dict]:
"""
把平坦的 block 清單按 H2 heading 切割成 section 清單。
回傳格式:
[
{"id": "sec-all", "title": "全部", "blocks": [...]}, # 永遠第一筆
{"id": "sec-1", "title": "標題文字", "blocks": [...]},
...
]
"""
sections: list[dict] = [
{"id": "sec-all", "title": "全部", "blocks": blocks[:]}
]
current: dict | None = None
sec_idx = 0
for b in blocks:
if b.get("type") == "heading" and int(b.get("level", 0)) == 2:
if current:
sections.append(current)
sec_idx += 1
current = {
"id": f"sec-{sec_idx}",
"title": (b.get("content") or f"段落 {sec_idx}").strip(),
"blocks": [b],
}
else:
if current is not None:
current["blocks"].append(b)
if current:
sections.append(current)
return sections
def get_section_blocks(
sections: list[dict], section_id: str | None
) -> list[dict]:
"""
取得指定 section_id 的 block 清單。
找不到時退回第一個 section;sections 為空時回傳空清單。
"""
if not sections:
return []
if not section_id:
return sections[0].get("blocks") or []
for s in sections:
if (s.get("id") or "") == section_id:
return s.get("blocks") or []
return sections[0].get("blocks") or []
# ---------------------------------------------------------------------------
# UI 元件
# ---------------------------------------------------------------------------
def make_section_control(
sections: list[dict], active_id: str | None
) -> html.Div | None:
"""
產生水平捲動的 section 切換按鈕列。
若 sections 為空,回傳 None。
"""
if not sections:
return None
buttons: list[Any] = []
for i, s in enumerate(sections):
sid = s.get("id") or f"sec-{i + 1}"
title = s.get("title") or f"段落 {i + 1}"
buttons.append(
dmc.Button(
title,
id={"type": "section-btn", "sid": sid},
variant="filled" if sid == active_id else "light",
size="sm",
style={"flex": "0 0 auto"},
)
)
return html.Div(
dmc.Group(buttons, gap="sm", wrap="nowrap"),
style={
"overflowX": "auto",
"overflowY": "hidden",
"whiteSpace": "nowrap",
"paddingBottom": "6px",
},
)