@beppla/tapas-ui 1.0.55 → 1.0.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/DataCell/DataCell.tsx +129 -16
- package/components/Dropdown/Dropdown.tsx +24 -2
- package/components/Dropdown/InputDropdown.tsx +7 -0
- package/components/Grid/StaticFixedSizeGrid.tsx +21 -10
- package/components/ListItem/ListItem.tsx +16 -0
- package/package/CHANGELOG.md +383 -0
- package/package/README.md +103 -0
- package/package/assets/assets/adaptive-icon.png +0 -0
- package/package/assets/assets/favicon.png +0 -0
- package/package/assets/assets/fonts/customfont.ttf +0 -0
- package/package/assets/assets/icon.png +0 -0
- package/package/assets/assets/logo.png +0 -0
- package/package/assets/assets/splash.png +0 -0
- package/package/assets/assets/svg/customfont.svg +332 -0
- package/package/assets/assets/svg/logo.svg +9 -0
- package/package/assets/assets/tapas/favicon.png +0 -0
- package/package/assets/assets/tapas/logo.png +0 -0
- package/package/assets/assets/tapas/logo_no_word.png +0 -0
- package/package/assets/assets/tapas/logo_transparent_white.png +0 -0
- package/package/commonjs/DataCell/DataCell.js +122 -17
- package/package/commonjs/DataCell/DataCell.js.map +1 -1
- package/package/commonjs/Dropdown/Dropdown.js +32 -6
- package/package/commonjs/Dropdown/Dropdown.js.map +1 -1
- package/package/commonjs/Dropdown/InputDropdown.js +7 -1
- package/package/commonjs/Dropdown/InputDropdown.js.map +1 -1
- package/package/commonjs/Grid/StaticFixedSizeGrid.js +23 -11
- package/package/commonjs/Grid/StaticFixedSizeGrid.js.map +1 -1
- package/package/commonjs/ListItem/ListItem.js +13 -1
- package/package/commonjs/ListItem/ListItem.js.map +1 -1
- package/package/init.js +179 -0
- package/package/module/DataCell/DataCell.js +121 -17
- package/package/module/DataCell/DataCell.js.map +1 -1
- package/package/module/Dropdown/Dropdown.js +32 -6
- package/package/module/Dropdown/Dropdown.js.map +1 -1
- package/package/module/Dropdown/InputDropdown.js +7 -1
- package/package/module/Dropdown/InputDropdown.js.map +1 -1
- package/package/module/Grid/StaticFixedSizeGrid.js +23 -11
- package/package/module/Grid/StaticFixedSizeGrid.js.map +1 -1
- package/package/module/ListItem/ListItem.js +13 -1
- package/package/module/ListItem/ListItem.js.map +1 -1
- package/package/package.json +84 -0
- package/package/typescript/DataCell/DataCell.d.ts +10 -1
- package/package/typescript/DataCell/DataCell.d.ts.map +1 -1
- package/package/typescript/Dropdown/Dropdown.d.ts.map +1 -1
- package/package/typescript/Dropdown/InputDropdown.d.ts.map +1 -1
- package/package/typescript/Grid/StaticFixedSizeGrid.d.ts.map +1 -1
- package/package/typescript/ListItem/ListItem.d.ts +4 -0
- package/package/typescript/ListItem/ListItem.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -9,10 +9,12 @@ const globalDropdownState: {
|
|
|
9
9
|
activeColumn: number | null;
|
|
10
10
|
activeRow: number | null;
|
|
11
11
|
closeAll: () => void;
|
|
12
|
+
onDropdownStateChange?: (columnIndex: number | null, rowIndex: number | null) => void;
|
|
12
13
|
} = {
|
|
13
14
|
activeColumn: null,
|
|
14
15
|
activeRow: null,
|
|
15
16
|
closeAll: () => {},
|
|
17
|
+
onDropdownStateChange: undefined,
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
// 注册和注销下拉菜单的函数
|
|
@@ -20,12 +22,16 @@ const registerDropdown = (columnIndex: number, rowIndex: number, closeCallback:
|
|
|
20
22
|
globalDropdownState.activeColumn = columnIndex;
|
|
21
23
|
globalDropdownState.activeRow = rowIndex;
|
|
22
24
|
globalDropdownState.closeAll = closeCallback;
|
|
25
|
+
// 通知状态变化
|
|
26
|
+
globalDropdownState.onDropdownStateChange?.(columnIndex, rowIndex);
|
|
23
27
|
};
|
|
24
28
|
|
|
25
29
|
const unregisterDropdown = () => {
|
|
26
30
|
globalDropdownState.activeColumn = null;
|
|
27
31
|
globalDropdownState.activeRow = null;
|
|
28
32
|
globalDropdownState.closeAll = () => {};
|
|
33
|
+
// 通知状态变化
|
|
34
|
+
globalDropdownState.onDropdownStateChange?.(null, null);
|
|
29
35
|
};
|
|
30
36
|
|
|
31
37
|
const closeAllDropdowns = () => {
|
|
@@ -34,6 +40,11 @@ const closeAllDropdowns = () => {
|
|
|
34
40
|
}
|
|
35
41
|
};
|
|
36
42
|
|
|
43
|
+
// 设置下拉菜单状态变化监听器
|
|
44
|
+
const setDropdownStateChangeListener = (callback: (columnIndex: number | null, rowIndex: number | null) => void) => {
|
|
45
|
+
globalDropdownState.onDropdownStateChange = callback;
|
|
46
|
+
};
|
|
47
|
+
|
|
37
48
|
export type DataType =
|
|
38
49
|
| "text"
|
|
39
50
|
| "number"
|
|
@@ -120,6 +131,14 @@ export interface TapasDataCellProps extends ViewProps {
|
|
|
120
131
|
minHeight?: number;
|
|
121
132
|
/** 是否为空白单元格 */
|
|
122
133
|
isBlank?: boolean;
|
|
134
|
+
/** 下拉菜单状态变化回调 */
|
|
135
|
+
onDropdownStateChange?: (isOpen: boolean) => void;
|
|
136
|
+
/** Grid 相关信息,用于计算下拉菜单位置 */
|
|
137
|
+
gridInfo?: {
|
|
138
|
+
totalRows?: number;
|
|
139
|
+
rowHeight?: number;
|
|
140
|
+
gridHeight?: number;
|
|
141
|
+
};
|
|
123
142
|
}
|
|
124
143
|
|
|
125
144
|
const TapasDataCell: React.FC<TapasDataCellProps> = ({
|
|
@@ -152,6 +171,8 @@ const TapasDataCell: React.FC<TapasDataCellProps> = ({
|
|
|
152
171
|
disabled = false,
|
|
153
172
|
minHeight = 40,
|
|
154
173
|
isBlank = false,
|
|
174
|
+
onDropdownStateChange,
|
|
175
|
+
gridInfo,
|
|
155
176
|
style,
|
|
156
177
|
...otherProps
|
|
157
178
|
}) => {
|
|
@@ -254,6 +275,73 @@ const TapasDataCell: React.FC<TapasDataCellProps> = ({
|
|
|
254
275
|
// 下拉菜单状态
|
|
255
276
|
const [dropdownVisible, setDropdownVisible] = useState(false);
|
|
256
277
|
const [dropdownPosition, setDropdownPosition] = useState({ top: 32, right: 0 });
|
|
278
|
+
|
|
279
|
+
// 计算下拉菜单的最佳位置
|
|
280
|
+
const calculateDropdownPosition = useCallback(() => {
|
|
281
|
+
// 更准确地计算下拉菜单的实际高度
|
|
282
|
+
const itemHeight = 32; // 每个选项的高度
|
|
283
|
+
const borderWidth = 2; // 边框宽度
|
|
284
|
+
const padding = 8; // 内边距
|
|
285
|
+
const shadowHeight = 4; // 阴影高度
|
|
286
|
+
|
|
287
|
+
// 考虑文本长度对高度的影响
|
|
288
|
+
const maxTextLength = Math.max(...actions.map(action => action.label.length));
|
|
289
|
+
const textHeightAdjustment = maxTextLength > 10 ? 4 : 0; // 长文本可能需要更多高度
|
|
290
|
+
|
|
291
|
+
// 计算下拉菜单的宽度(考虑文本长度)
|
|
292
|
+
// const minWidth = 120; // 最小宽度
|
|
293
|
+
// const textWidth = maxTextLength * 8; // 估算文本宽度
|
|
294
|
+
// const _actualWidth = Math.max(minWidth, textWidth + 24); // 24px 为内边距和图标空间
|
|
295
|
+
|
|
296
|
+
const actualHeight = actions.length * itemHeight + borderWidth + padding + shadowHeight + textHeightAdjustment;
|
|
297
|
+
|
|
298
|
+
const buttonHeight = 32; // 按钮高度
|
|
299
|
+
const cellHeight = gridInfo?.rowHeight || 56; // 使用传入的 rowHeight 或默认值
|
|
300
|
+
const gridHeight = gridInfo?.gridHeight || 400; // 使用传入的 gridHeight 或默认值
|
|
301
|
+
|
|
302
|
+
// 根据行索引估算当前单元格在 Grid 中的位置
|
|
303
|
+
const currentRowIndex = rowIndex || 0;
|
|
304
|
+
|
|
305
|
+
// 计算当前单元格距离 Grid 底部的距离
|
|
306
|
+
const currentCellBottom = (currentRowIndex + 1) * cellHeight;
|
|
307
|
+
const spaceBelow = gridHeight - currentCellBottom;
|
|
308
|
+
|
|
309
|
+
// 计算上方可用空间
|
|
310
|
+
const currentCellTop = currentRowIndex * cellHeight;
|
|
311
|
+
const spaceAbove = currentCellTop;
|
|
312
|
+
|
|
313
|
+
// 添加安全边距,确保下拉菜单不会紧贴边界
|
|
314
|
+
const safetyMargin = 8;
|
|
315
|
+
const requiredSpace = actualHeight + safetyMargin;
|
|
316
|
+
|
|
317
|
+
// 智能选择显示位置
|
|
318
|
+
if (requiredSpace > spaceBelow && requiredSpace <= spaceAbove) {
|
|
319
|
+
// 下方空间不够,但上方空间足够,显示在上方
|
|
320
|
+
return {
|
|
321
|
+
top: -actualHeight - 4, // 按钮上方,留 4px 间距
|
|
322
|
+
right: 0,
|
|
323
|
+
};
|
|
324
|
+
} else if (requiredSpace > spaceBelow && requiredSpace > spaceAbove) {
|
|
325
|
+
// 上下空间都不够,选择空间较大的一侧
|
|
326
|
+
if (spaceAbove > spaceBelow) {
|
|
327
|
+
return {
|
|
328
|
+
top: -actualHeight - 4, // 按钮上方
|
|
329
|
+
right: 0,
|
|
330
|
+
};
|
|
331
|
+
} else {
|
|
332
|
+
return {
|
|
333
|
+
top: buttonHeight + 4, // 按钮下方
|
|
334
|
+
right: 0,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
} else {
|
|
338
|
+
// 下方空间足够,显示在下方
|
|
339
|
+
return {
|
|
340
|
+
top: buttonHeight + 4, // 按钮下方,留 4px 间距
|
|
341
|
+
right: 0,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
}, [actions.length, rowIndex, gridInfo]);
|
|
257
345
|
|
|
258
346
|
// 全局下拉菜单管理
|
|
259
347
|
useEffect(() => {
|
|
@@ -275,8 +363,20 @@ const TapasDataCell: React.FC<TapasDataCellProps> = ({
|
|
|
275
363
|
};
|
|
276
364
|
}, [dropdownVisible, columnIndex, rowIndex]);
|
|
277
365
|
|
|
366
|
+
// 通知父组件下拉菜单状态变化
|
|
367
|
+
useEffect(() => {
|
|
368
|
+
onDropdownStateChange?.(dropdownVisible);
|
|
369
|
+
}, [dropdownVisible, onDropdownStateChange]);
|
|
370
|
+
|
|
278
371
|
// 监听全局关闭事件
|
|
279
372
|
useEffect(() => {
|
|
373
|
+
// const _handleGlobalClose = () => {
|
|
374
|
+
// if (globalDropdownState.activeColumn !== columnIndex ||
|
|
375
|
+
// globalDropdownState.activeRow !== rowIndex) {
|
|
376
|
+
// setDropdownVisible(false);
|
|
377
|
+
// }
|
|
378
|
+
// };
|
|
379
|
+
|
|
280
380
|
// 这里可以添加全局事件监听器
|
|
281
381
|
// 为了简化,我们在点击其他单元格时关闭当前下拉菜单
|
|
282
382
|
}, [columnIndex, rowIndex]);
|
|
@@ -323,26 +423,34 @@ const TapasDataCell: React.FC<TapasDataCellProps> = ({
|
|
|
323
423
|
|
|
324
424
|
// 多个操作显示下拉菜单
|
|
325
425
|
return (
|
|
326
|
-
<View style={
|
|
426
|
+
<View style={[
|
|
427
|
+
styles.dropdownContainer,
|
|
428
|
+
{
|
|
429
|
+
// 只有当前激活的下拉菜单容器才有高 z-index
|
|
430
|
+
zIndex: globalDropdownState.activeColumn === columnIndex && globalDropdownState.activeRow === rowIndex ? 2147483646 : 1,
|
|
431
|
+
}
|
|
432
|
+
]}>
|
|
327
433
|
<Pressable
|
|
328
434
|
style={styles.actionButton}
|
|
329
435
|
onPress={(event) => {
|
|
330
436
|
// 阻止事件冒泡,避免触发外层的 attachCellPress
|
|
331
437
|
event.stopPropagation();
|
|
332
438
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
//
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
439
|
+
if (dropdownVisible) {
|
|
440
|
+
// 如果当前下拉菜单已经打开,直接关闭
|
|
441
|
+
setDropdownVisible(false);
|
|
442
|
+
} else {
|
|
443
|
+
// 如果当前下拉菜单关闭,先关闭其他所有下拉菜单,然后打开当前菜单
|
|
444
|
+
closeAllDropdowns();
|
|
445
|
+
|
|
446
|
+
// 计算并设置下拉菜单位置
|
|
447
|
+
setDropdownPosition(calculateDropdownPosition());
|
|
448
|
+
|
|
449
|
+
// 延迟打开当前下拉菜单,确保其他菜单已关闭
|
|
450
|
+
setTimeout(() => {
|
|
451
|
+
setDropdownVisible(true);
|
|
452
|
+
}, 0);
|
|
343
453
|
}
|
|
344
|
-
|
|
345
|
-
setDropdownVisible(!dropdownVisible);
|
|
346
454
|
}}
|
|
347
455
|
disabled={disabled}
|
|
348
456
|
>
|
|
@@ -509,7 +617,10 @@ const useStyles = makeStyles((theme, props?: {
|
|
|
509
617
|
},
|
|
510
618
|
dropdownContainer: {
|
|
511
619
|
position: "relative",
|
|
512
|
-
|
|
620
|
+
// 默认使用较低的 z-index,只有激活的下拉菜单容器才有高 z-index
|
|
621
|
+
zIndex: 1,
|
|
622
|
+
// 确保容器本身不会创建新的 stacking context
|
|
623
|
+
isolation: "auto",
|
|
513
624
|
},
|
|
514
625
|
dropdownMenu: {
|
|
515
626
|
position: "absolute", // 使用绝对定位
|
|
@@ -526,9 +637,11 @@ const useStyles = makeStyles((theme, props?: {
|
|
|
526
637
|
shadowRadius: 3.84,
|
|
527
638
|
elevation: 5,
|
|
528
639
|
minWidth: 120,
|
|
529
|
-
zIndex:
|
|
640
|
+
zIndex: 2147483647, // 更高的 z-index,确保显示在所有元素之上
|
|
530
641
|
// 确保下拉菜单不被父容器的 overflow 隐藏
|
|
531
642
|
overflow: "visible",
|
|
643
|
+
// 确保下拉菜单在正确的层级上
|
|
644
|
+
isolation: "isolate",
|
|
532
645
|
},
|
|
533
646
|
dropdownItem: {
|
|
534
647
|
paddingHorizontal: 12,
|
|
@@ -554,4 +667,4 @@ export default withTheme(TapasDataCell);
|
|
|
554
667
|
|
|
555
668
|
// Export aliases for compatibility
|
|
556
669
|
export const DataCell = withTheme(TapasDataCell);
|
|
557
|
-
export { TapasDataCell };
|
|
670
|
+
export { TapasDataCell, setDropdownStateChangeListener };
|
|
@@ -136,8 +136,8 @@ const useStyles = makeStyles((theme) => ({
|
|
|
136
136
|
// Modal 模式样式
|
|
137
137
|
modalContainer: {
|
|
138
138
|
flex: 1,
|
|
139
|
-
justifyContent: "
|
|
140
|
-
alignItems: "
|
|
139
|
+
justifyContent: "flex-start", // 改为顶部对齐,与 CustomDropdown 保持一致
|
|
140
|
+
alignItems: "stretch", // 改为拉伸对齐,与 CustomDropdown 保持一致
|
|
141
141
|
},
|
|
142
142
|
modalIcon: {
|
|
143
143
|
color: theme.colors.primary,
|
|
@@ -198,6 +198,7 @@ const useStyles = makeStyles((theme) => ({
|
|
|
198
198
|
display: "flex",
|
|
199
199
|
flexDirection: "row",
|
|
200
200
|
justifyContent: "space-between",
|
|
201
|
+
alignItems: "center", // 确保垂直居中对齐
|
|
201
202
|
minHeight: 40,
|
|
202
203
|
width: "100%",
|
|
203
204
|
overflow: "hidden",
|
|
@@ -212,6 +213,7 @@ const useStyles = makeStyles((theme) => ({
|
|
|
212
213
|
paddingRight: 12,
|
|
213
214
|
paddingTop: 9,
|
|
214
215
|
paddingBottom: 9,
|
|
216
|
+
alignItems: "center", // 确保垂直居中对齐
|
|
215
217
|
},
|
|
216
218
|
alignCenter: {
|
|
217
219
|
alignSelf: "center",
|
|
@@ -471,10 +473,13 @@ const Dropdown: React.FC<DropdownProps> = ({
|
|
|
471
473
|
(showSelectedValue || (noLabelAnim && label)) ? styles.modalBtn : null,
|
|
472
474
|
dropdownType === "solid" ? styles.modalSolidBtn : null,
|
|
473
475
|
dropdownType === "solid" && radius ? { borderRadius: radius } : null,
|
|
476
|
+
// 统一主体容器的位置,无论是否使用 customPopoverContent
|
|
474
477
|
label && !noLabelAnim ? { marginTop: 7 } : null,
|
|
475
478
|
noLabelAnim && label && backgroundColor ? { backgroundColor } : null,
|
|
476
479
|
state === "error" ? { borderColor: theme.theme.colors.error } : null,
|
|
477
480
|
props.disabled ? { borderColor: theme.theme.colors.grey3 } : null,
|
|
481
|
+
// 确保主体容器始终有统一的垂直对齐
|
|
482
|
+
{ alignItems: "center" },
|
|
478
483
|
]}
|
|
479
484
|
disabled={props.disabled}
|
|
480
485
|
onPress={openDropdown}
|
|
@@ -581,6 +586,16 @@ const Dropdown: React.FC<DropdownProps> = ({
|
|
|
581
586
|
? theme.theme.colors.grey4 || "#f0f0f0"
|
|
582
587
|
: "transparent",
|
|
583
588
|
},
|
|
589
|
+
// 第一个 item 添加左上和右上圆角
|
|
590
|
+
index === 0 && {
|
|
591
|
+
borderTopLeftRadius: 12,
|
|
592
|
+
borderTopRightRadius: 12,
|
|
593
|
+
},
|
|
594
|
+
// 最后一个 item 添加左下和右下圆角
|
|
595
|
+
index === dropdownItems.length - 1 && {
|
|
596
|
+
borderBottomLeftRadius: 12,
|
|
597
|
+
borderBottomRightRadius: 12,
|
|
598
|
+
},
|
|
584
599
|
showCheckedStatusInList && selectedItemKey === item.key ? {
|
|
585
600
|
backgroundColor: theme.theme.colors.grey4 || "#f0f0f0",
|
|
586
601
|
} : null,
|
|
@@ -758,6 +773,11 @@ const Dropdown: React.FC<DropdownProps> = ({
|
|
|
758
773
|
</Pressable>
|
|
759
774
|
<ScrollView style={{width: subWidth, height: subHeight}}>
|
|
760
775
|
{options?.map((item, index) => {
|
|
776
|
+
const visibleItems = options.filter(item => !item.hide);
|
|
777
|
+
const currentVisibleIndex = visibleItems.findIndex(visibleItem => visibleItem === item);
|
|
778
|
+
const isFirst = currentVisibleIndex === 0;
|
|
779
|
+
const isLast = currentVisibleIndex === visibleItems.length - 1;
|
|
780
|
+
|
|
761
781
|
return (
|
|
762
782
|
!item.hide && (
|
|
763
783
|
<CustomListItem
|
|
@@ -773,6 +793,8 @@ const Dropdown: React.FC<DropdownProps> = ({
|
|
|
773
793
|
key={index}
|
|
774
794
|
item={item}
|
|
775
795
|
selected={selected_old}
|
|
796
|
+
isFirst={isFirst}
|
|
797
|
+
isLast={isLast}
|
|
776
798
|
/>
|
|
777
799
|
)
|
|
778
800
|
);
|
|
@@ -152,6 +152,11 @@ const InputDropdown: React.FC<InputDropdownProps> = ({
|
|
|
152
152
|
{Array.isArray(list) ? (
|
|
153
153
|
<ScrollView style={{width: subWidth, maxHeight: subHeight}}>
|
|
154
154
|
{list?.map((item, index) => {
|
|
155
|
+
const visibleItems = list.filter(item => !item.hide);
|
|
156
|
+
const currentVisibleIndex = visibleItems.findIndex(visibleItem => visibleItem === item);
|
|
157
|
+
const isFirst = currentVisibleIndex === 0;
|
|
158
|
+
const isLast = currentVisibleIndex === visibleItems.length - 1;
|
|
159
|
+
|
|
155
160
|
return (
|
|
156
161
|
!item.hide && (
|
|
157
162
|
<CustomListItem
|
|
@@ -164,6 +169,8 @@ const InputDropdown: React.FC<InputDropdownProps> = ({
|
|
|
164
169
|
key={index}
|
|
165
170
|
item={item}
|
|
166
171
|
selected={selected}
|
|
172
|
+
isFirst={isFirst}
|
|
173
|
+
isLast={isLast}
|
|
167
174
|
/>
|
|
168
175
|
)
|
|
169
176
|
);
|
|
@@ -58,6 +58,7 @@ const ItemWrapper: React.FC<any> = ({ data, columnIndex, rowIndex, style }) => {
|
|
|
58
58
|
columnHeaderHeight,
|
|
59
59
|
border,
|
|
60
60
|
theme,
|
|
61
|
+
hasActions,
|
|
61
62
|
} = data;
|
|
62
63
|
|
|
63
64
|
if (
|
|
@@ -68,13 +69,17 @@ const ItemWrapper: React.FC<any> = ({ data, columnIndex, rowIndex, style }) => {
|
|
|
68
69
|
return null;
|
|
69
70
|
}
|
|
70
71
|
|
|
72
|
+
// 检测当前列是否有 actions 按钮
|
|
73
|
+
const shouldShowActions = hasActions && hasActions(columnIndex ?? 0, rowIndex ?? 0);
|
|
74
|
+
|
|
71
75
|
// 确保传递正确的参数给children函数
|
|
72
76
|
const childrenProps: ChildrenProps = {
|
|
73
77
|
columnIndex: columnIndex ?? 0,
|
|
74
78
|
rowIndex: rowIndex ?? 0,
|
|
75
79
|
style: {
|
|
76
80
|
...style,
|
|
77
|
-
overflow: "visible"
|
|
81
|
+
// 根据 hasActions 决定是否允许 overflow: "visible"
|
|
82
|
+
overflow: shouldShowActions ? "visible" : "hidden",
|
|
78
83
|
borderBottom: border
|
|
79
84
|
? `1px solid ${theme.grey3 ?? "rgba(0, 0, 0, 0.12)"}`
|
|
80
85
|
: "none",
|
|
@@ -210,6 +215,7 @@ const InnerElementType = forwardRef(
|
|
|
210
215
|
columnHeaderHeight,
|
|
211
216
|
}}
|
|
212
217
|
style={{
|
|
218
|
+
// 保持列头的 overflow: "hidden" 以确保正确的滚动行为
|
|
213
219
|
overflow: "hidden",
|
|
214
220
|
// borderTopLeftRadius: theme?.radius?.mini ?? 4,
|
|
215
221
|
backgroundColor:
|
|
@@ -223,7 +229,11 @@ const InnerElementType = forwardRef(
|
|
|
223
229
|
)}
|
|
224
230
|
<div ref={ref} {...rest} style={{
|
|
225
231
|
...style,
|
|
226
|
-
width:
|
|
232
|
+
width: totalWidth,
|
|
233
|
+
// width: rest.width, // 使用正确的 grid 宽度减去 sticky 列宽度
|
|
234
|
+
// width: rest.width - stickyColumnsWidth, // 使用正确的 grid 宽度减去 sticky 列宽度
|
|
235
|
+
// position: "sticky", // 固定容器位置,不随滚动移动
|
|
236
|
+
// left: 0, // 固定在左侧
|
|
227
237
|
}}>
|
|
228
238
|
{scrollLeft > 0 && (
|
|
229
239
|
<StickyColumn
|
|
@@ -231,7 +241,7 @@ const InnerElementType = forwardRef(
|
|
|
231
241
|
backgroundColor: theme?.background ?? "#F9F2E8",
|
|
232
242
|
zIndex: 5,
|
|
233
243
|
top: 0,
|
|
234
|
-
width:
|
|
244
|
+
width: 1, // 左侧阴影条宽度应该是 1
|
|
235
245
|
height: height,
|
|
236
246
|
left: 0,
|
|
237
247
|
marginTop: headersRender ? -1 * (columnHeaderHeight || 40) : 0,
|
|
@@ -268,7 +278,7 @@ const InnerElementType = forwardRef(
|
|
|
268
278
|
top: 0,
|
|
269
279
|
width: stickyColumnsWidth,
|
|
270
280
|
height: columnHeaderHeight || 40,
|
|
271
|
-
left: width - stickyColumnsWidth - (border ? 1 : 0),
|
|
281
|
+
left: width - stickyColumnsWidth - (border ? 1 : 0), // 使用总宽度计算位置
|
|
272
282
|
marginTop:
|
|
273
283
|
scrollLeft === 0
|
|
274
284
|
? -1 * (columnHeaderHeight || 40)
|
|
@@ -278,7 +288,6 @@ const InnerElementType = forwardRef(
|
|
|
278
288
|
borderLeft: border
|
|
279
289
|
? `1px solid ${theme?.grey3 ?? "rgba(0, 0, 0, 0.12)"}`
|
|
280
290
|
: "none",
|
|
281
|
-
// borderTopRightRadius: theme?.radius?.mini ?? 4,
|
|
282
291
|
}}
|
|
283
292
|
>
|
|
284
293
|
<VariableSizeGrid
|
|
@@ -292,8 +301,7 @@ const InnerElementType = forwardRef(
|
|
|
292
301
|
width={stickyColumnsWidth}
|
|
293
302
|
itemData={{ ItemRenderer: headersRender, stickyColumnIndices }}
|
|
294
303
|
style={{
|
|
295
|
-
overflow: "
|
|
296
|
-
// borderTopRightRadius: theme?.radius?.mini ?? 4,
|
|
304
|
+
overflow: "hidden",
|
|
297
305
|
backgroundColor:
|
|
298
306
|
columnHeaderBackgroundColor ||
|
|
299
307
|
(theme?.colors?.grey4 ?? "rgba(0, 0, 0, 0.08)"),
|
|
@@ -309,7 +317,7 @@ const InnerElementType = forwardRef(
|
|
|
309
317
|
backgroundColor: theme?.background ?? "#F9F2E8",
|
|
310
318
|
zIndex: 2,
|
|
311
319
|
top: headersRender ? columnHeaderHeight || 40 : 0,
|
|
312
|
-
left:
|
|
320
|
+
left: width - stickyColumnsWidth - (border ? 1 : 0), // 使用总宽度计算位置
|
|
313
321
|
width: stickyColumnsWidth,
|
|
314
322
|
height: "100%",
|
|
315
323
|
position: "sticky",
|
|
@@ -329,7 +337,9 @@ const InnerElementType = forwardRef(
|
|
|
329
337
|
rowHeight={rowHeight}
|
|
330
338
|
width={stickyColumnsWidth}
|
|
331
339
|
itemData={{ ItemRenderer, stickyColumnIndices, border, hasActions: hasActionsFn }}
|
|
332
|
-
style={{
|
|
340
|
+
style={{
|
|
341
|
+
overflow: hasActions ? "visible": "hidden"
|
|
342
|
+
}}
|
|
333
343
|
>
|
|
334
344
|
{StickyColumnCell}
|
|
335
345
|
</VariableSizeGrid>
|
|
@@ -433,7 +443,8 @@ const StickyList = ({
|
|
|
433
443
|
: rest.theme.radius.mini ?? 4,
|
|
434
444
|
scrollbarWidth: "none",
|
|
435
445
|
msOverflowStyle: "none",
|
|
436
|
-
overflow: "visible"
|
|
446
|
+
// 移除 overflow: "visible",恢复 Grid 的正常滚动功能
|
|
447
|
+
// Modal 下拉菜单不需要这个设置
|
|
437
448
|
}}
|
|
438
449
|
itemData={{
|
|
439
450
|
ItemRenderer: children,
|
|
@@ -32,6 +32,10 @@ export interface Props extends ListItemProps {
|
|
|
32
32
|
searchHighlightStyle?: StyleProp<TextStyle>;
|
|
33
33
|
titleStyle?: StyleProp<TextStyle>;
|
|
34
34
|
descStyle?: StyleProp<TextStyle>;
|
|
35
|
+
/** 是否为第一个 item */
|
|
36
|
+
isFirst?: boolean;
|
|
37
|
+
/** 是否为最后一个 item */
|
|
38
|
+
isLast?: boolean;
|
|
35
39
|
search?: string;
|
|
36
40
|
testID?: string;
|
|
37
41
|
}
|
|
@@ -140,6 +144,8 @@ const CustomListItem: React.FC<Props> = ({
|
|
|
140
144
|
searchHighlightStyle,
|
|
141
145
|
titleStyle,
|
|
142
146
|
descStyle,
|
|
147
|
+
isFirst,
|
|
148
|
+
isLast,
|
|
143
149
|
testID,
|
|
144
150
|
...props
|
|
145
151
|
}) => {
|
|
@@ -184,6 +190,16 @@ const CustomListItem: React.FC<Props> = ({
|
|
|
184
190
|
selected?.value === item?.value
|
|
185
191
|
? styles.selectedItem
|
|
186
192
|
: isHovered && styles.hovered,
|
|
193
|
+
// 第一个 item 添加左上和右上圆角
|
|
194
|
+
isFirst && {
|
|
195
|
+
borderTopLeftRadius: 12,
|
|
196
|
+
borderTopRightRadius: 12,
|
|
197
|
+
},
|
|
198
|
+
// 最后一个 item 添加左下和右下圆角
|
|
199
|
+
isLast && {
|
|
200
|
+
borderBottomLeftRadius: 12,
|
|
201
|
+
borderBottomRightRadius: 12,
|
|
202
|
+
},
|
|
187
203
|
]}
|
|
188
204
|
>
|
|
189
205
|
<Hoverable
|