iter(g305): 新增瀑布流布局 masonry
This commit is contained in:
@@ -88,3 +88,4 @@ export { heatmap } from './heatmap.js';
|
||||
export { progressRing } from './progressRing.js';
|
||||
export { noticeBar } from './noticeBar.js';
|
||||
export { sortableList } from './sortableList.js';
|
||||
export { masonry } from './masonry.js';
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { h } from '@ui-arch/frame';
|
||||
import type { MasonryProps } from './types.js';
|
||||
|
||||
/*** 瀑布流:CSS 多列布局,列数按容器宽度自适应或显式指定;每项单独包一层才能 break-inside 不拆断 ***/
|
||||
export function masonry(props: MasonryProps): HTMLElement {
|
||||
// —— 状态集中声明 ——
|
||||
const adaptive = !props.columns; // 未指定列数即自适应(column-width 让浏览器自己算列数)
|
||||
const width = props.minColumnWidth ?? 240; // 自适应时的最小列宽(像素)
|
||||
const gap = props.gap ?? 'var(--ua-space-3)'; // 列间距与行间距同源,避免两处各写一份
|
||||
const root = h('div', { class: 'ua-masonry' }) as HTMLElement;
|
||||
root.style.columnGap = gap;
|
||||
if (adaptive) root.style.columnWidth = `${width}px`; // 自适应:容器越宽列数越多,窄屏自动降到一列
|
||||
else root.style.columnCount = String(props.columns); // 显式列数:与 column-width 互斥,固定几列就几列
|
||||
|
||||
props.items.forEach((item) => {
|
||||
const cell = h('div', { class: 'ua-masonry-item' }, item);
|
||||
cell.style.marginBottom = gap; // 行间距与列间距同值,视觉上才是均匀网格
|
||||
root.append(cell);
|
||||
});
|
||||
return root;
|
||||
}
|
||||
@@ -1146,3 +1146,11 @@ export interface SortableListHandle {
|
||||
move: (from: number, to: number) => void; // 程序化搬位:下标越界或禁用时静默忽略
|
||||
order: () => string[]; // 读取当前顺序(以 DOM 为唯一真相)
|
||||
}
|
||||
|
||||
/*** 瀑布流入参 ***/
|
||||
export interface MasonryProps {
|
||||
items: unknown[]; // 每个卡片内容(字符串 / DOM / 响应式值),按数组顺序铺进最短列
|
||||
columns?: number; // 固定列数;传了即不随容器宽度变化,与 minColumnWidth 互斥
|
||||
minColumnWidth?: number; // 自适应列宽下限(像素);缺省 240,容器越宽列数越多
|
||||
gap?: string; // 列间距与行间距(CSS 长度或令牌值);缺省 var(--ua-space-3)
|
||||
}
|
||||
|
||||
@@ -102,7 +102,8 @@
|
||||
"heatmap(props):日历热力图,按周列 × 星期行铺格子、四档浓度表示当天数量,悬停看明细",
|
||||
"progressRing(props):环形进度,SVG 双圆靠 dasharray 画弧 + 中心百分比,value 可传信号自动重绘",
|
||||
"noticeBar(props):单行通知条,语义色 + 左侧符号 + 可选跑马灯与关闭,适合页顶常驻播报",
|
||||
"sortableList(props):拖拽排序列表,整行可拖 + Alt+↑↓ 键盘搬位,返回 { el, move, order } 句柄"
|
||||
"sortableList(props):拖拽排序列表,整行可拖 + Alt+↑↓ 键盘搬位,返回 { el, move, order } 句柄",
|
||||
"masonry(props):瀑布流多列布局,列宽自适应或固定列数,卡片不被拆到两列"
|
||||
],
|
||||
"keyTypes": [
|
||||
"ButtonProps",
|
||||
@@ -4567,6 +4568,45 @@
|
||||
"外部要按代码调整顺序用句柄 move(from, to),下标越界或禁用时静默忽略;order() 以 DOM 为唯一真相回读当前顺序",
|
||||
"什么时候别用:条目超过一屏(拖到边缘不会自动滚动,改用筛选或上下按钮)、需要跨列表搬运(用两个实例并自己管状态)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "masonry",
|
||||
"title": "瀑布流 Masonry",
|
||||
"demo": "sec-masonry",
|
||||
"props": [
|
||||
{
|
||||
"n": "items",
|
||||
"t": "unknown[]",
|
||||
"r": 1,
|
||||
"d": "每个卡片内容(字符串 / DOM / 响应式值);数组顺序即铺放顺序,列高不等由内容自己决定"
|
||||
},
|
||||
{
|
||||
"n": "columns",
|
||||
"t": "number",
|
||||
"d": "固定列数;传了即不随容器宽度变化,与 minColumnWidth 互斥"
|
||||
},
|
||||
{
|
||||
"n": "minColumnWidth",
|
||||
"t": "number",
|
||||
"d": "自适应列宽下限(像素);缺省 240,容器越宽列数越多",
|
||||
"df": "240"
|
||||
},
|
||||
{
|
||||
"n": "gap",
|
||||
"t": "string",
|
||||
"d": "列间距与行间距(CSS 长度或令牌值);缺省 var(--ua-space-3)",
|
||||
"df": "var(--ua-space-3)"
|
||||
}
|
||||
],
|
||||
"example": "masonry({ minColumnWidth: 220, items: shots.map((s) => card({ title: s.title }, image({ src: s.url }))) })",
|
||||
"steps": [
|
||||
"items 里直接放 card / image / 任意 DOM:每项由组件包一层 .ua-masonry-item,只有这一层带 break-inside: avoid,卡片才不会在列边界断成两截",
|
||||
"不传 columns 就按 minColumnWidth 自适应:容器变宽自动加列、窄屏自动降到一列,不需要自己监听 window.resize",
|
||||
"要固定几列(比如大屏看板恒 4 列)就传 columns,此时 minColumnWidth 不再生效——两者互斥,别同时传指望它俩协商",
|
||||
"间距传一次就够:gap 同时给 column-gap 与每项的 margin-bottom,列间距和行间距天然一致;改间距只改这一处",
|
||||
"列高不等才是瀑布流的价值所在(图片墙、评论流、看板):等高内容请用 grid,瀑布流会把等高卡片铺成奇怪的错位",
|
||||
"什么时候别用:需要严格的行对齐(表格化数据)、需要按列独立滚动(用 splitter / 多个 virtualList),以及首屏内容需要按阅读顺序严格横向(多列布局是竖向填充,读屏顺序与视觉列序一致但不等同于行序)"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6089,3 +6089,12 @@ h5.ua-type-title { font-size: var(--ua-font-size-md); }
|
||||
transition-property: color, background-color, border-color, box-shadow, opacity, fill, stroke; /* 只保留不产生空间位移的属性 */
|
||||
}
|
||||
}
|
||||
|
||||
/* —— 瀑布流:多列布局,列宽自适应或固定列数 —— */
|
||||
.ua-masonry {
|
||||
display: block; /* 多列容器不能是 flex/grid,否则 column-width 失效 */
|
||||
}
|
||||
.ua-masonry-item {
|
||||
break-inside: avoid; /* 卡片不被拆到两列:图片墙里断半截最刺眼 */
|
||||
page-break-inside: avoid; /* 打印时同样不拆断 */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user