初始化项目
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* @kuge/ui 的唯一公开入口。
|
||||
*
|
||||
* 约定(见 ADR-001 / ADR-003):HAR 模块只通过本文件暴露能力。
|
||||
*/
|
||||
export { Breakpoint, BreakpointUtil } from './src/main/ets/layout/Breakpoint';
|
||||
export { AdaptiveScaffold } from './src/main/ets/layout/AdaptiveScaffold';
|
||||
export { GridMetrics, GridSpec } from './src/main/ets/layout/GridSpec';
|
||||
export { ResponsiveGrid } from './src/main/ets/layout/ResponsiveGrid';
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"apiType": "stageMode",
|
||||
"buildOption": {},
|
||||
"targets": [
|
||||
{
|
||||
"name": "default"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { harTasks } from '@ohos/hvigor-ohos-plugin';
|
||||
|
||||
export default {
|
||||
system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
||||
plugins: [] /* Custom plugin to extend the functionality of Hvigor. */
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@kuge/ui",
|
||||
"version": "1.0.0",
|
||||
"description": "Kuge UI base: breakpoints, adaptive layout, shared components",
|
||||
"main": "Index.ets",
|
||||
"author": "Kuge Team",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 自适应工作区骨架(1.3.3)。
|
||||
*
|
||||
* 结构:左侧导航栏(可选)+ 对象树(可选)+ 主内容区。
|
||||
* sm 下隐藏导航与对象树,主内容占满;md/lg 按断点给出栏宽。
|
||||
* 具体页面由 feature 模块通过 @BuilderParam 注入。
|
||||
*/
|
||||
import { Breakpoint, BreakpointUtil } from './Breakpoint';
|
||||
|
||||
@Component
|
||||
export struct AdaptiveScaffold {
|
||||
@State private widthVp: number = 0;
|
||||
@BuilderParam rail: () => void = this.emptyBuilder;
|
||||
@BuilderParam tree: () => void = this.emptyBuilder;
|
||||
@BuilderParam content: () => void = this.emptyBuilder;
|
||||
|
||||
@Builder
|
||||
emptyBuilder() {
|
||||
}
|
||||
|
||||
private currentBreakpoint(): Breakpoint {
|
||||
return BreakpointUtil.of(this.widthVp);
|
||||
}
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
if (BreakpointUtil.railWidthOf(this.currentBreakpoint()) > 0) {
|
||||
Column() {
|
||||
this.rail()
|
||||
}
|
||||
.width(BreakpointUtil.railWidthOf(this.currentBreakpoint()))
|
||||
.height('100%')
|
||||
}
|
||||
if (BreakpointUtil.showsTree(this.currentBreakpoint())) {
|
||||
Column() {
|
||||
this.tree()
|
||||
}
|
||||
.width(BreakpointUtil.treeWidthOf(this.currentBreakpoint()))
|
||||
.height('100%')
|
||||
}
|
||||
Column() {
|
||||
this.content()
|
||||
}
|
||||
.layoutWeight(1)
|
||||
.height('100%')
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.onAreaChange((_oldArea: Area, newArea: Area) => {
|
||||
this.widthVp = Number(newArea.width);
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 断点体系(1.23.1 / 1.3.3)。
|
||||
*
|
||||
* 纯计算逻辑,不依赖 UI 框架,便于单元测试与在任意入口复用。
|
||||
* 断点定义与 ARCH-001 §7、交互原型 UX-001 保持一致:
|
||||
* sm < 600vp 单栏(平板竖屏)
|
||||
* md 600–840vp 双栏(平板横屏)
|
||||
* lg > 840vp 三栏(PC / 2in1)
|
||||
*/
|
||||
export enum Breakpoint {
|
||||
SM = 0,
|
||||
MD = 1,
|
||||
LG = 2
|
||||
}
|
||||
|
||||
export class BreakpointUtil {
|
||||
/** sm 的上界(不含)。 */
|
||||
static readonly SM_LIMIT: number = 600;
|
||||
/** md 的上界(不含)。 */
|
||||
static readonly MD_LIMIT: number = 840;
|
||||
|
||||
/** 由可用宽度(vp)判定断点。 */
|
||||
static of(widthVp: number): Breakpoint {
|
||||
if (widthVp < BreakpointUtil.SM_LIMIT) {
|
||||
return Breakpoint.SM;
|
||||
}
|
||||
if (widthVp < BreakpointUtil.MD_LIMIT) {
|
||||
return Breakpoint.MD;
|
||||
}
|
||||
return Breakpoint.LG;
|
||||
}
|
||||
|
||||
/** 主内容列数。 */
|
||||
static columnsOf(bp: Breakpoint): number {
|
||||
switch (bp) {
|
||||
case Breakpoint.SM:
|
||||
return 1;
|
||||
case Breakpoint.MD:
|
||||
return 2;
|
||||
default:
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
/** 左侧导航栏宽度(vp);sm 下为 0(改用抽屉)。 */
|
||||
static railWidthOf(bp: Breakpoint): number {
|
||||
switch (bp) {
|
||||
case Breakpoint.SM:
|
||||
return 0;
|
||||
case Breakpoint.MD:
|
||||
return 64;
|
||||
default:
|
||||
return 72;
|
||||
}
|
||||
}
|
||||
|
||||
/** 对象树宽度(vp);sm 下为 0(作为独立页面)。 */
|
||||
static treeWidthOf(bp: Breakpoint): number {
|
||||
switch (bp) {
|
||||
case Breakpoint.SM:
|
||||
return 0;
|
||||
case Breakpoint.MD:
|
||||
return 240;
|
||||
default:
|
||||
return 280;
|
||||
}
|
||||
}
|
||||
|
||||
/** 是否显示对象树(sm 下不并排显示)。 */
|
||||
static showsTree(bp: Breakpoint): boolean {
|
||||
return bp !== Breakpoint.SM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* 响应式栅格计算(1.23.2)。
|
||||
*
|
||||
* 纯逻辑:由可用宽度推导栅格列数、边距、间距与列宽,并提供跨列宽度计算。
|
||||
* 与 UX-003 规范一致:sm 4 列 / md 8 列 / lg 12 列;边距 16/24/32;间距 8/12/16。
|
||||
* ArkUI 组件(ResponsiveGrid)只负责渲染,所有数值来自本类,保证页面间一致。
|
||||
*/
|
||||
import { Breakpoint, BreakpointUtil } from './Breakpoint';
|
||||
|
||||
export interface GridMetrics {
|
||||
breakpoint: Breakpoint;
|
||||
columns: number;
|
||||
margin: number;
|
||||
gutter: number;
|
||||
contentWidth: number;
|
||||
columnWidth: number;
|
||||
}
|
||||
|
||||
export class GridSpec {
|
||||
/** 列数。 */
|
||||
static columnsOf(bp: Breakpoint): number {
|
||||
switch (bp) {
|
||||
case Breakpoint.SM:
|
||||
return 4;
|
||||
case Breakpoint.MD:
|
||||
return 8;
|
||||
default:
|
||||
return 12;
|
||||
}
|
||||
}
|
||||
|
||||
/** 左右边距(单侧)。 */
|
||||
static marginOf(bp: Breakpoint): number {
|
||||
switch (bp) {
|
||||
case Breakpoint.SM:
|
||||
return 16;
|
||||
case Breakpoint.MD:
|
||||
return 24;
|
||||
default:
|
||||
return 32;
|
||||
}
|
||||
}
|
||||
|
||||
/** 列间距。 */
|
||||
static gutterOf(bp: Breakpoint): number {
|
||||
switch (bp) {
|
||||
case Breakpoint.SM:
|
||||
return 8;
|
||||
case Breakpoint.MD:
|
||||
return 12;
|
||||
default:
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
/** 由宽度推导完整栅格度量。 */
|
||||
static metricsOf(widthVp: number): GridMetrics {
|
||||
const bp: Breakpoint = BreakpointUtil.of(widthVp);
|
||||
const columns: number = GridSpec.columnsOf(bp);
|
||||
const margin: number = GridSpec.marginOf(bp);
|
||||
const gutter: number = GridSpec.gutterOf(bp);
|
||||
const contentWidth: number = Math.max(0, widthVp - margin * 2);
|
||||
const columnWidth: number = (contentWidth - gutter * (columns - 1)) / columns;
|
||||
return {
|
||||
breakpoint: bp,
|
||||
columns: columns,
|
||||
margin: margin,
|
||||
gutter: gutter,
|
||||
contentWidth: contentWidth,
|
||||
columnWidth: columnWidth
|
||||
};
|
||||
}
|
||||
|
||||
/** 跨 span 列的元素宽度;span 会被裁剪到 [1, columns]。 */
|
||||
static spanWidth(metrics: GridMetrics, span: number): number {
|
||||
let safeSpan: number = Math.floor(span);
|
||||
if (safeSpan < 1) {
|
||||
safeSpan = 1;
|
||||
}
|
||||
if (safeSpan > metrics.columns) {
|
||||
safeSpan = metrics.columns;
|
||||
}
|
||||
return safeSpan * metrics.columnWidth + (safeSpan - 1) * metrics.gutter;
|
||||
}
|
||||
|
||||
/** 一行可放置的元素个数(按最小宽度计算),至少 1 个。 */
|
||||
static fitCount(metrics: GridMetrics, minItemWidth: number): number {
|
||||
if (minItemWidth <= 0) {
|
||||
return 1;
|
||||
}
|
||||
const count: number = Math.floor((metrics.contentWidth + metrics.gutter) / (minItemWidth + metrics.gutter));
|
||||
return count < 1 ? 1 : count;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 响应式栅格容器(1.23.2)。
|
||||
*
|
||||
* 按可用宽度自动折算列宽,子项通过 GridSpec 计算自身宽度。
|
||||
* 由于 ArkUI 不支持在子组件内读取父容器度量,这里以「回调参数」方式
|
||||
* 把 GridMetrics 传给内容构建器,避免每个页面重复算一遍。
|
||||
*/
|
||||
import { GridMetrics, GridSpec } from './GridSpec';
|
||||
|
||||
@Component
|
||||
export struct ResponsiveGrid {
|
||||
@State private widthVp: number = 0;
|
||||
@BuilderParam content: (metrics: GridMetrics) => void = this.emptyContent;
|
||||
|
||||
@Builder
|
||||
emptyContent(_metrics: GridMetrics) {
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
this.content(GridSpec.metricsOf(this.widthVp))
|
||||
}
|
||||
.width('100%')
|
||||
.onAreaChange((_oldArea: Area, newArea: Area) => {
|
||||
this.widthVp = Number(newArea.width);
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"module": {
|
||||
"name": "ui",
|
||||
"type": "har",
|
||||
"deviceTypes": [
|
||||
"tablet",
|
||||
"2in1"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "ui_module_desc",
|
||||
"value": "库阁 UI 基座:断点、自适应布局与通用组件"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user