sync issue fixes, and add more comments.

This commit is contained in:
Chen Lily 2024-02-19 17:32:11 +08:00
parent 3fd1b5982a
commit 7770aa10a0
6 changed files with 762 additions and 788 deletions

View File

@ -19,6 +19,7 @@
--row-bg-color: #fff;
--row-active-bg-color: #fafafa;
--row-selected-bg-color: #e6f2fb;
--total-row-bg-color: #b3b3b3;
--text-disabled-color: gray;
--filter-shadow: 0 3px 6px -4px rgba(0, 0, 0, .12), 0 6px 16px 0 rgba(0, 0, 0, .08), 0 9px 28px 8px rgba(0, 0, 0, .05);
@ -79,8 +80,9 @@
table-layout: fixed;
>thead {
color: var(--header-fore-color);
tr {
color: var(--header-fore-color);
position: sticky;
top: 0;
z-index: 2;
@ -251,15 +253,54 @@
}
}
>tbody {
color: var(--cell-fore-color);
>tbody,
>tfoot {
>.ui-grid-row {
line-height: var(--line-height);
white-space: nowrap;
box-sizing: border-box;
>td {
padding: 0;
&.sticky {
position: sticky;
z-index: 1;
}
>span {
padding: var(--spacing-cell);
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: pre;
}
}
}
}
>tfoot {
color: var(--header-fore-color);
position: absolute;
width: 100%;
background-color: var(--total-row-bg-color);
>.ui-grid-row>td {
font-weight: bold;
&.sticky {
background-color: var(--total-row-bg-color);
}
}
}
>tbody {
color: var(--cell-fore-color);
>.ui-grid-row {
background-color: var(--row-bg-color);
border-bottom: 1px solid var(--cell-border-color);
box-sizing: border-box;
&:hover {
background-color: var(--row-active-bg-color);
@ -278,11 +319,8 @@
}
>td {
padding: 0;
&.sticky {
position: sticky;
z-index: 1;
background-color: var(--row-bg-color);
}
@ -302,14 +340,6 @@
}
}
>span {
padding: var(--spacing-cell);
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: pre;
}
>input[type="text"],
>textarea {
border: none;
@ -387,6 +417,7 @@
justify-content: center;
align-items: center;
position: relative;
padding: var(--spacing-s);
>svg {
width: 16px;

View File

@ -1,370 +0,0 @@
import { Grid, GridItem, GridItemWrapper, GridSourceItem } from "./grid";
import { Dropdown, DropdownOptions } from "../dropdown";
/** 列类型枚举 */
declare enum GridColumnType {
/** 通用列 */
Common = 0,
/** 单行文本框列 */
Input = 1,
/** 下拉选择列 */
Dropdown = 2,
/** 复选框列 */
Checkbox = 3,
/** 图标列 */
Icon = 4,
/** 多行文本列 */
Text = 5,
/** 日期选择列 */
Date = 6
}
/** 列定义接口 */
export interface GridColumnDefinition {
/** 列关键字,默认以该关键字从行数据中提取单元格值,行数据的关键字属性值里包含 DisplayValue 则优先显示此值 */
key?: string;
/** 列的类型,可以为 {@linkcode GridColumn} 的子类,或者内置类型 {@linkcode GridColumnType} */
type?: GridColumnType | typeof GridColumn;
/** 列标题文本 */
caption?: string;
/** 列标题的元素样式 */
captionStyle?: { [key: string]: string };
/** 大于 0 则设置为该宽度,否则根据列内容自动调整列宽 */
width?: number;
/** 列对齐方式 */
align?: "left" | "center" | "right";
/**
* <br/><br/>
* `boolean` 使<br/><br/>
* `string` <br/><br/>
* `(item: GridItem) => boolean` <br/><br/>
*/
enabled?: boolean | string | ((item: GridItem) => boolean);
/**
*
* @param item
* @param editing
* @param body Grid `&lt;tbody&gt;`
*/
filter?: (item: GridItem, editing: boolean, body?: HTMLElement) => any;
/** 单元格以该值填充内容忽略filter与关键字属性 */
text?: string;
/** 列是否可见 */
visible?: boolean;
/** 列是否允许调整宽度 */
resizable?: boolean;
/** 列是否允许排序 */
sortable?: boolean;
/** 列是否允许重排顺序 */
orderable?: boolean;
/** 列为复选框类型时是否在列头增加全选复选框 */
allcheck?: boolean;
/** 单元格css样式对象仅在重建行元素时读取 */
css?: { [key: string]: string };
/** 根据返回值填充单元格样式(填充行列数据时读取) */
styleFilter?: (item: GridItem) => { [key: string]: string };
/** 根据返回值设置单元格背景色 */
bgFilter?: (item: GridItem) => string;
/** 给单元格元素附加事件(事件函数上下文为数据行对象) */
events?: { [event: string]: Function };
/** 根据返回值设置单元格元素的附加属性,允许直接设置对象也支持函数返回对象 */
attrs?: { [key: string]: string } | ((item: GridItem) => { [key: string]: string });
/** 是否允许进行列头过滤 */
allowFilter?: boolean;
/** 自定义列过滤器的数据源函数上下文为Grid */
filterSource?: Array<GridItem> | ((col: GridColumnDefinition) => Array<GridItem>);
/** 自定义列排序函数 */
sortFilter?: (a: GridItem, b: GridItem) => -1 | 0 | 1;
/** 列为下拉列表类型时以该值设置下拉框的参数 */
dropOptions?: DropdownOptions;
/** 列为下拉列表类型时以该值设置下拉列表数据源,支持函数返回,也支持返回异步对象 */
source?: Array<GridSourceItem> | ((item: GridItem) => Array<GridSourceItem> | Promise<Array<GridSourceItem>>);
/** 下拉列表数据源是否缓存结果即行数据未发生变化时仅从source属性获取一次值 */
sourceCache?: boolean;
/** 列为图标类型时以该值设置图标样式(函数上下文为列定义对象),默认值 `fa-light` */
iconType?: "fa-light" | "fa-regular" | "fa-solid";
/** 列为图标类型时以该值作为单元格元素的额外样式类型(函数上下文为列定义对象) */
iconClassName?: string | ((item: GridItem) => string);
/** 列为日期类型时以该值作为最小可选日期值 */
dateMin?: string;
/** 列为日期类型时以该值作为最大可选日期值 */
dateMax?: string;
/** 列为日期类型时自定义日期转字符串函数 */
dateValueFormatter?: (date: Date) => string;
/** 以返回值额外设置单元格的tooltip函数上下文为列定义对象 */
tooltip?: string | ((item: GridItem) => string);
/**
*
* @param this Grid
* @param col
* @param flag
* @eventProperty
*/
onAllChecked?: (this: Grid, col: GridColumnDefinition, flag: boolean) => void;
/**
*
* @param this Grid
* @param item
* @param value
* @param oldValue
* @param e
* @eventProperty
*/
onChanged?: (this: Grid, item: GridItem, value: boolean | string | number, oldValue: boolean | string | number, e?: any) => void;
/**
*
* @param this Grid
* @param item
* @param value
* @eventProperty
*/
onInputEnded?: (this: Grid, item: GridItem, value: string) => void;
/**
* OK时触发的事件
* @param this Grid
* @param col
* @param selected
* @eventProperty
*/
onFilterOk?: (this: Grid, col: GridColumnDefinition, selected: Array<GridItem>) => void;
/**
*
* @param this Grid
* @param col
* @eventProperty
*/
onFiltered?: (this: Grid, col: GridColumnDefinition) => void;
/**
*
* @param this
* @param item
* @param drop
* @eventProperty
*/
onDropExpanded?: (this: GridColumnDefinition, item: GridItem, drop: Dropdown) => void;
}
/** 列定义基类 */
export class GridColumn {
/** @ignore */
constructor();
/**
*
* @param col
* @returns
* @virtual
*/
static create(col: GridColumnDefinition): HTMLElement;
/**
* <br/><br/>
* `__editing` {@linkcode leaveEdit} <br/>
* {@linkcode GridDropdownColumn}
* @param trigger e {@linkcode getValue}
* @param col
* @param container
* @param vals `values`
* @returns
* @virtual
*/
static createEdit(trigger: (e: any) => void, col: GridColumnDefinition, container: HTMLElement, vals: GridItemWrapper): HTMLElement;
/**
*
* @param col
* @returns
* @virtual
*/
static createCaption?(col: GridColumnDefinition): HTMLElement;
/**
*
* @param element
* @param val
* @param vals
* @param col
* @param grid {@linkcode Grid}
* @virtual
*/
static setValue(element: HTMLElement, val: string | boolean | number, vals: GridItemWrapper, col: GridColumnDefinition, grid: Grid): void;
/**
*
* @param e {@linkcode createEdit} `trigger`
* @param col
* @returns
* @virtual
*/
static getValue(e: any, col: GridColumnDefinition): string | boolean | number;
/**
*
* @param element
* @param style
* @virtual
*/
static setStyle(element: HTMLElement, style: { [key: string]: string }): void;
/**
*
* @param element
* @param enabled false时代表禁用
* @virtual
*/
static setEnabled(element: HTMLElement, enabled?: boolean): void;
/**
* `__editing`
* @param element
* @param container
* @virtual
*/
static leaveEdit?(element: HTMLElement, container: HTMLElement): void;
}
/** 单行文本列 */
export class GridInputColumn extends GridColumn {
/**
* {@linkcode GridColumnDefinition.onInputEnded} <br/>
* `true` `__editing` {@linkcode GridColumnDefinition.onInputEnded} `onchange` <br/>
* {@linkcode GridInputColumn}
*/
static get editing(): boolean;
/**
* @inheritdoc GridColumn.createEdit
* @override
*/
static createEdit(trigger: (e: any) => void, col: GridColumnDefinition, container: HTMLElement, vals: GridItemWrapper): HTMLElement;
/**
* @inheritdoc GridColumn.setValue
* @override
*/
static setValue(element: HTMLElement, val: string, vals: GridItemWrapper, col: GridColumnDefinition, grid: Grid): void;
/**
* @inheritdoc GridColumn.getValue
* @override
*/
static getValue(e: any): string;
/**
* @inheritdoc GridColumn.setEnabled
* @override
*/
static setEnabled(element: HTMLElement, enabled?: boolean): void;
}
/** 多行文本列 */
export class GridTextColumn extends GridInputColumn {
/**
* @inheritdoc GridInputColumn.createEdit
* @override
*/
static createEdit(trigger: (e: any) => void, col: GridColumnDefinition, container: HTMLElement, vals: GridItemWrapper): HTMLElement;
/**
* @inheritdoc GridInputColumn.setValue
* @override
*/
static setValue(element: HTMLElement, val: string, vals: GridItemWrapper, col: GridColumnDefinition, grid: Grid): void;
}
/** 下拉选择列 */
export class GridDropdownColumn extends GridColumn {
/**
* @inheritdoc GridColumn.createEdit
* @override
*/
static createEdit(trigger: (e: any) => void, col: GridColumnDefinition, container: HTMLElement, vals: GridItemWrapper): HTMLElement;
/**
* @inheritdoc GridColumn.setValue
* @override
*/
static setValue(element: HTMLElement, val: string, vals: GridItemWrapper, col: GridColumnDefinition): void;
/**
* @inheritdoc GridColumn.getValue
* @override
*/
static getValue(e: any, col: GridColumnDefinition): string;
/**
* @inheritdoc GridColumn.setEnabled
* @override
*/
static setEnabled(element: HTMLElement, enabled?: boolean): void;
/**
* @inheritdoc GridColumn.leaveEdit
* @override
*/
static leaveEdit?(element: HTMLElement, container: HTMLElement): void;
}
/** 复选框列 */
export class GridCheckboxColumn extends GridColumn {
/**
* @inheritdoc GridColumn.createEdit
* @override
*/
static createEdit(trigger: (e: any) => void): HTMLElement;
/**
* @inheritdoc GridColumn.setValue
* @override
*/
static setValue(element: HTMLElement, val: boolean): void;
/**
* @inheritdoc GridColumn.getValue
* @override
*/
static getValue(e: any): boolean;
/**
* @inheritdoc GridColumn.setEnabled
* @override
*/
static setEnabled(element: HTMLElement, enabled?: boolean): void;
}
/** 图标列 */
export class GridIconColumn extends GridColumn {
/**
* @inheritdoc GridColumn.create
* @override
*/
static create(): HTMLElement;
/**
* @inheritdoc GridColumn.setValue
* @override
*/
static setValue(element: HTMLElement, val: string, vals: GridItemWrapper, col: GridColumnDefinition): void;
/**
* @inheritdoc GridColumn.setEnabled
* @override
*/
static setEnabled(element: HTMLElement, enabled?: boolean): void;
}
/** 日期选择列 */
export class GridDateColumn extends GridColumn {
/**
* @inheritdoc GridColumn.createEdit
* @override
*/
static createEdit(trigger: (e: any) => void, col: GridColumnDefinition, container: HTMLElement, vals: GridItemWrapper): HTMLElement;
/**
* <br/><br/>
* <br/><br/>
* `"2024-01-26"`<br/>
* `"1/26/2024"`<br/>
* `"638418240000000000"`<br/>
* `new Date('2024-01-26')`<br/>
* @param element
* @param val
* @override
*/
static setValue(element: HTMLElement, val: string | number): void;
/**
* @inheritdoc GridColumn.getValue
* @override
*/
static getValue(e: any): string | number;
/**
* @inheritdoc GridColumn.setEnabled
* @override
*/
static setEnabled(element: HTMLElement, enabled?: boolean): void;
/**
* M/d/yyyy
* @param date
* @returns
*/
static formatDate(date: Date): string;
}

View File

@ -254,6 +254,12 @@ export class GridDropdownColumn extends GridColumn {
return drop;
}
/**
* @private
* @param {Map<string, ValueItem>} item
* @param {GridColumnDefinition} col
* @returns {GridSourceItem[]}
*/
static _getSource(item, col) {
let source;
if (col.sourceCache !== false) {

323
lib/ui/grid/grid.d.ts vendored
View File

@ -1,323 +0,0 @@
import { GridColumnDefinition } from "./column"
/**
*
*
* @param {number} index -
* @param {number} colIndex -
* @returns {boolean} `false`
*/
declare function cellClickedCallback(index: number, colIndex: number): boolean;
/** 列数据接口 */
interface GridItem {
/** 值 */
Value: any;
/** 显示值 */
DisplayValue: string;
}
/** 列数据行包装接口 */
interface GridItemWrapper {
/** 真实数据对象 */
values: { [key: string]: GridItem | any };
/** 下拉数据源缓存对象 */
source: { [key: string]: Array<GridSourceItem> };
}
/** 下拉框列数据源接口 */
interface GridSourceItem {
/** 值 */
value: string;
/** 显示文本 */
text: string;
}
/** Grid 语言资源接口 */
interface GridLanguages {
/**
* `( All )` */
all: string;
/** “确定”文本,默认值 `OK` */
ok: string;
/** “重置”文本,默认值 `Reset` */
reset: string;
cancel: string;
/** “空”文本,默认值 `( Null )` */
null: string;
addLevel: string;
deleteLevel: string;
copyLevel: string;
asc: string;
desc: string;
column: string;
order: string;
sort: string;
requirePrompt: string;
duplicatePrompt: string;
}
/** Grid 列排序定义接口 */
interface GridColumnSortDefinition {
/** 排序列的关键字 */
column: string;
/** 升序或降序 */
order: "asc" | "desc";
}
/** 列排序枚举 */
declare enum GridColumnDirection {
/** 倒序 */
Descending = -1,
/** 升序 */
Ascending = 1
}
/** 列事件枚举 */
declare enum GridColumnEvent {
/** 重排事件 */
Reorder = "reorder",
/** 宽调整事件 */
Resize = "resize",
/** 排序事件 */
Sort = "sort"
}
/** Grid 控件基础类 */
export class Grid {
/** 列类型枚举 */
static ColumnTypes: {
/** 通用列(只读) */
Common: 0,
/** 单行文本列 */
Input: 1,
/** 下拉选择列 */
Dropdown: 2,
/** 复选框列 */
Checkbox: 3,
/** 图标列 */
Icon: 4,
/** 多行文本列 */
Text: 5,
/** 日期选择列 */
Date: 6,
/**
*
* @param type
*/
isCheckbox(type: number): boolean;
};
/** 列定义的数组 */
columns: Array<GridColumnDefinition>;
/** 多语言资源对象 */
langs?: GridLanguages;
/** 行数大于等于该值则启用虚模式,默认值 `100` */
virtualCount?: number;
/** 表格行高,默认值 `36` */
rowHeight?: number;
/** 文本行高,默认值 `24` */
lineHeight?: number;
/** 列表底部留出额外行的空白,默认值 `0` */
extraRows?: number;
/** 过滤条件列表的行高,默认值 `30` */
filterRowHeight?: number;
/** 列表高度值,为 0 时列表始终显示全部内容(自增高),为非数字或者小于 0 则根据容器高度来确定虚模式的渲染行数,默认值 `null` */
height?: number;
/** 列表是否为只读,默认值 `false` */
readonly?: boolean;
/** 是否允许多选,默认值 `false` */
multiSelect?: boolean;
/** 为 false 时只有点击在单元格内才会选中行,默认值 `true` */
fullrowClick?: boolean;
/** 单元格 tooltip 是否禁用,默认值 `false` */
tooltipDisabled?: boolean;
/** 列头是否显示,默认值 `true` */
headerVisible?: boolean;
/** 监听事件的窗口载体,默认值 `window` */
window?: Window
/** 排序列的索引,默认值 `-1` */
sortIndex?: number;
/** 排序方式,正数升序,负数倒序,默认值 `1` */
sortDirection?: GridColumnDirection;
/** 排序列 */
sortArray?: Array<GridColumnSortDefinition>;
/**
* Grid
* @param container Grid string HTMLElement <br/><br/>
* <i> init </i>
* @param getText
*/
constructor(container: string | HTMLElement, getText?: (id: string, def?: string) => string);
/**
* falsenullundefined0
* @param index
* @param colIndex
* @eventProperty
*/
willSelect?: (index: number, colIndex: number) => boolean;
/**
* colIndex -1 false
* @eventProperty
*/
cellClicked?: typeof cellClickedCallback;
/**
*
* @param index
* @eventProperty
*/
onSelectedRowChanged?: (index?: number) => void;
/**
* colIndex -1
* @param index
* @param colIndex
* @eventProperty
*/
onCellDblClicked?: (index: number, colIndex: number) => void;
/**
*
* @param index
* @eventProperty
*/
onRowDblClicked?: (index: number) => void;
/**
*
* @param type <br/><br/>
* "reorder" value <br/>
* "resize" value <br/>
* "sort" value 1 -1
* @param colIndex
* @param value
* @eventProperty
*/
onColumnChanged?: (type: GridColumnEvent, colIndex: number, value: number | GridColumnDirection) => void;
/**
*
* @param e
* @eventProperty
*/
onBodyScrolled?: (e: Event) => void;
/**
*
* @param array
* @eventProperty
*/
onSorted?: (array?: Array<GridColumnSortDefinition>) => void;
/** 返回所有数据的数据(未过滤) */
get allSource(): Array<GridItem>;
/** 获取数据数组(已过滤) */
get source(): Array<GridItem>;
/** 设置数据,并刷新列表 */
set source(list: Array<GridItem>);
/** 获取当前选中的行索引的数组 */
get selectedIndexes(): Array<number>;
/** 设置当前选中的行索引的数组,并刷新列表 */
set selectedIndexes(indexes: Array<number>);
/** 获取 Grid 当前是否处于加载状态 */
get loading(): boolean;
/** 使 Grid 进入加载状态 */
set loading(flag: boolean);
/** 获取 Grid 当前滚动的偏移量 */
get scrollTop(): number;
/** 设置 Grid 滚动偏移量 */
set scrollTop(top: number);
/** 获取 Grid 的页面元素 */
get element(): HTMLElement;
/** 获取当前 Grid 是否已发生改变 */
get changed(): boolean;
/** 获取当前是否为虚模式状态 */
get virtual(): boolean;
/** 获取当前排序的列关键字,为 null 则当前无排序列 */
get sortKey(): string | undefined;
/** 获取当前选中行的索引,为 -1 则当前没有选中行 */
get selectedIndex(): number | -1;
/**
* Grid控件
* @param container
*/
init(container?: HTMLElement): void;
/**
* set source
* @param source
*/
setData(source: Array<GridItem>): void;
/**
*
* @param index
* @param item
*/
setItem(index: number, item: GridItem): void;
/**
*
* @param item
* @param index
* @returns
*/
addItem(item: GridItem, index?: number): GridItem;
/**
*
* @param array
* @param index
* @returns
*/
addItems(array: Array<GridItem>, index?: number): Array<GridItem>
/**
*
* @param index
* @returns
*/
removeItem(index: number): GridItem;
/**
*
* @param indexes
* @returns
*/
removeItems(indexes?: Array<number>): Array<GridItem>;
/**
*
* @param index
*/
scrollToIndex(index: number): void;
/**
* Grid
* @param force {@linkcode reload}
* @param keep
*/
resize(force?: boolean, keep?: boolean): void;
/**
*
* @param keep
*/
reload(keep?: boolean): void;
/**
* Grid单元格数据
*/
refresh(): void;
/**
*
*/
resetChange(): void;
/**
*
* @param reload true {@linkcode Grid.reload}
*/
sortColumn(reload?: boolean): void;
/**
*
* @param reload true {@linkcode Grid.reload}
*/
sort(reload?: boolean): void;
/**
*
*/
clearHeaderCheckbox(): void;
/**
*
*/
showSortPanel(): void;
}

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,8 @@ import './css/tooltip.scss';
import { createElement } from "../functions";
// import { global } from "../utility";
const pointerHeight = 12;
export function setTooltip(container, content, flag = false, parent = null) {
const isParent = parent instanceof HTMLElement;
if (isParent) {
@ -77,9 +79,9 @@ export function setTooltip(container, content, flag = false, parent = null) {
const offsetHeight = wrapper.offsetHeight;
const offsetWidth = wrapper.offsetWidth;
if (isParent) {
top -= offsetHeight + 14;
if (top < -offsetHeight) {
top += c.offsetHeight + offsetHeight + 14;
top -= offsetHeight + pointerHeight;
if (top < 0) {
top += c.offsetHeight + offsetHeight + pointerHeight * 2;
wrapper.classList.add('ui-tooltip-down');
}
left += (c.offsetWidth - offsetWidth) / 2;
@ -125,20 +127,20 @@ export function setTooltip(container, content, flag = false, parent = null) {
p = p.parentElement;
}
}
if (t - offsetHeight - 14 < 0) {
if (t - offsetHeight - pointerHeight < 0) {
const containerOffsetHeight = c.offsetHeight;
if (t + containerOffsetHeight + offsetHeight + 14 > lastHeight) {
if (t + containerOffsetHeight + offsetHeight + pointerHeight > lastHeight) {
top = t + (containerOffsetHeight - offsetHeight) / 2;
if (top + offsetHeight + 1 > lastHeight) {
top = lastHeight - offsetHeight - 1;
}
wrapper.classList.add('ui-tooltip-no');
} else {
top += containerOffsetHeight + 14;
top += containerOffsetHeight + pointerHeight;
wrapper.classList.add('ui-tooltip-down');
}
} else {
top -= offsetHeight + 14;
top -= offsetHeight + pointerHeight;
wrapper.classList.remove('ui-tooltip-down');
}
left += (c.offsetWidth - offsetWidth) / 2;