@rainbow-oh/yee-c 0.6.4 → 0.7.0

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.
Files changed (123) hide show
  1. package/dist/cjs/Button/style/index.less +5 -4
  2. package/dist/cjs/Drawer/drawer.js +1 -1
  3. package/dist/cjs/Drawer/interface.d.ts +1 -1
  4. package/dist/cjs/Drawer/style/index.less +1 -0
  5. package/dist/cjs/List/demo/virtual.d.ts +3 -0
  6. package/dist/cjs/List/demo/virtual.js +53 -0
  7. package/dist/cjs/List/hooks/useListKeyboard.d.ts +28 -0
  8. package/dist/cjs/List/hooks/useListKeyboard.js +188 -0
  9. package/dist/cjs/List/interface.d.ts +29 -2
  10. package/dist/cjs/List/list.js +141 -21
  11. package/dist/cjs/List/style/index.less +24 -0
  12. package/dist/cjs/Select/demo/columns.d.ts +3 -0
  13. package/dist/cjs/Select/demo/columns.js +62 -0
  14. package/dist/cjs/Select/hooks/useSelectKeyboard.d.ts +13 -1
  15. package/dist/cjs/Select/hooks/useSelectKeyboard.js +81 -10
  16. package/dist/cjs/Select/interface.d.ts +30 -3
  17. package/dist/cjs/Select/option.js +4 -3
  18. package/dist/cjs/Select/options.js +90 -8
  19. package/dist/cjs/Select/select.js +32 -8
  20. package/dist/cjs/Select/style/index.less +14 -0
  21. package/dist/cjs/Selector/interface.d.ts +4 -0
  22. package/dist/cjs/Selector/selector.js +5 -3
  23. package/dist/cjs/Table/interface.d.ts +1 -1
  24. package/dist/cjs/Tree/demo/draggable.js +2 -0
  25. package/dist/cjs/Tree/interface.d.ts +46 -23
  26. package/dist/cjs/Tree/tree-node.d.ts +1 -1
  27. package/dist/cjs/Tree/tree-node.js +30 -23
  28. package/dist/cjs/Tree/tree.d.ts +13 -12
  29. package/dist/cjs/Tree/tree.js +452 -227
  30. package/dist/cjs/Tree/utils/tree-tools.d.ts +43 -10
  31. package/dist/cjs/Tree/utils/tree-tools.js +129 -91
  32. package/dist/cjs/locale/context.d.ts +5 -4
  33. package/dist/cjs/locale/context.js +15 -8
  34. package/dist/cjs/locale/interface.d.ts +20 -0
  35. package/dist/cjs/locale/util.d.ts +3 -3
  36. package/dist/cjs/style/color.css +1 -0
  37. package/dist/cjs/style/size.css +2 -1
  38. package/dist/cjs/style/themes.css +1 -1
  39. package/dist/cjs/style/variables.css +4 -2
  40. package/dist/cjs/utils/isEqual.js +5 -7
  41. package/dist/cjs/version.d.ts +1 -1
  42. package/dist/cjs/version.js +1 -1
  43. package/dist/esm/Button/style/index.less +5 -4
  44. package/dist/esm/Drawer/drawer.js +2 -1
  45. package/dist/esm/Drawer/interface.d.ts +1 -1
  46. package/dist/esm/Drawer/style/index.less +1 -0
  47. package/dist/esm/List/demo/virtual.d.ts +3 -0
  48. package/dist/esm/List/demo/virtual.js +22 -0
  49. package/dist/esm/List/hooks/useListKeyboard.d.ts +28 -0
  50. package/dist/esm/List/hooks/useListKeyboard.js +173 -0
  51. package/dist/esm/List/interface.d.ts +29 -2
  52. package/dist/esm/List/list.js +171 -14
  53. package/dist/esm/List/style/index.less +24 -0
  54. package/dist/esm/Select/demo/columns.d.ts +3 -0
  55. package/dist/esm/Select/demo/columns.js +36 -0
  56. package/dist/esm/Select/hooks/useSelectKeyboard.d.ts +13 -1
  57. package/dist/esm/Select/hooks/useSelectKeyboard.js +91 -14
  58. package/dist/esm/Select/interface.d.ts +30 -3
  59. package/dist/esm/Select/option.js +6 -2
  60. package/dist/esm/Select/options.js +114 -32
  61. package/dist/esm/Select/select.js +40 -11
  62. package/dist/esm/Select/style/index.less +14 -0
  63. package/dist/esm/Selector/interface.d.ts +4 -0
  64. package/dist/esm/Selector/selector.js +10 -4
  65. package/dist/esm/Table/interface.d.ts +1 -1
  66. package/dist/esm/Tree/demo/draggable.js +2 -0
  67. package/dist/esm/Tree/interface.d.ts +46 -23
  68. package/dist/esm/Tree/tree-node.d.ts +1 -1
  69. package/dist/esm/Tree/tree-node.js +26 -31
  70. package/dist/esm/Tree/tree.d.ts +13 -12
  71. package/dist/esm/Tree/tree.js +572 -163
  72. package/dist/esm/Tree/utils/tree-tools.d.ts +43 -10
  73. package/dist/esm/Tree/utils/tree-tools.js +219 -104
  74. package/dist/esm/locale/context.d.ts +5 -4
  75. package/dist/esm/locale/context.js +25 -9
  76. package/dist/esm/locale/interface.d.ts +20 -0
  77. package/dist/esm/locale/util.d.ts +3 -3
  78. package/dist/esm/style/color.css +1 -0
  79. package/dist/esm/style/size.css +2 -1
  80. package/dist/esm/style/themes.css +1 -1
  81. package/dist/esm/style/variables.css +4 -2
  82. package/dist/esm/utils/isEqual.js +5 -7
  83. package/dist/esm/version.d.ts +1 -1
  84. package/dist/esm/version.js +1 -1
  85. package/dist/umd/yee-c.min.css +2 -2
  86. package/dist/umd/yee-c.min.js +1 -1
  87. package/package.json +1 -1
  88. package/src/Button/style/index.less +5 -4
  89. package/src/Drawer/drawer.tsx +1 -1
  90. package/src/Drawer/interface.ts +1 -0
  91. package/src/Drawer/style/index.less +1 -0
  92. package/src/List/demo/virtual.tsx +20 -0
  93. package/src/List/hooks/useListKeyboard.ts +235 -0
  94. package/src/List/index.en-US.md +6 -0
  95. package/src/List/index.zh-CN.md +6 -0
  96. package/src/List/interface.ts +29 -2
  97. package/src/List/list.tsx +157 -19
  98. package/src/List/style/index.less +24 -0
  99. package/src/Select/demo/columns.tsx +35 -0
  100. package/src/Select/hooks/useSelectKeyboard.ts +112 -15
  101. package/src/Select/index.en-US.md +4 -0
  102. package/src/Select/index.zh-CN.md +4 -0
  103. package/src/Select/interface.ts +31 -4
  104. package/src/Select/option.tsx +9 -3
  105. package/src/Select/options.tsx +119 -26
  106. package/src/Select/select.tsx +41 -8
  107. package/src/Select/style/index.less +14 -0
  108. package/src/Selector/interface.ts +4 -0
  109. package/src/Selector/selector.tsx +8 -3
  110. package/src/Table/interface.ts +1 -1
  111. package/src/Tree/demo/draggable.tsx +2 -0
  112. package/src/Tree/interface.ts +46 -23
  113. package/src/Tree/tree-node.tsx +26 -29
  114. package/src/Tree/tree.tsx +573 -274
  115. package/src/Tree/utils/tree-tools.ts +231 -125
  116. package/src/locale/_README.md +22 -13
  117. package/src/locale/context.tsx +33 -16
  118. package/src/locale/interface.ts +24 -0
  119. package/src/locale/util.ts +6 -6
  120. package/src/style/color.css +1 -0
  121. package/src/style/size.css +2 -1
  122. package/src/utils/isEqual.ts +5 -7
  123. package/src/version.ts +1 -1
@@ -171,7 +171,7 @@
171
171
  --m-btn-hover-color: var(--yee-primary-color-hover);
172
172
  --m-btn-active-color: var(--yee-primary-color-active);
173
173
  --m-btn-bg-color: var(--yee-btn-primary-bg-color);
174
- --m-btn-hover-bg-color: var(--yee-primary-color-hover);
174
+ --m-btn-hover-bg-color: var(--yee-primary-color-border);
175
175
  --m-btn-active-bg-color: var(--yee-primary-color-active);
176
176
  --m-btn-border-color: var(--yee-primary-color);
177
177
  --m-btn-border-hover-color: var(--yee-primary-color-hover);
@@ -186,7 +186,7 @@
186
186
  --m-btn-border-color: var(--yee-success-color);
187
187
  --m-btn-border-hover-color: var(--yee-success-color-hover);
188
188
  --m-btn-border-active-color: var(--yee-success-color-active);
189
- --m-btn-hover-bg-color: var(--yee-success-color-hover);
189
+ --m-btn-hover-bg-color: var(--yee-success-color-border);
190
190
  --m-btn-active-bg-color: var(--yee-success-color-active);
191
191
  --m-btn-active-shadow-color: var(--yee-success-color-active);
192
192
  }
@@ -198,7 +198,8 @@
198
198
  --m-btn-border-color: var(--yee-error-color);
199
199
  --m-btn-border-hover-color: var(--yee-error-color-hover);
200
200
  --m-btn-border-active-color: var(--yee-error-color-active);
201
- --m-btn-hover-bg-color: var(--yee-error-color-hover);
201
+ // --m-btn-hover-bg-color: var(--yee-error-color-hover);
202
+ --m-btn-hover-bg-color: var(--yee-error-color-border);
202
203
  --m-btn-active-bg-color: var(--yee-error-color-active);
203
204
  --m-btn-active-shadow-color: var(--yee-error-color-active);
204
205
  }
@@ -210,7 +211,7 @@
210
211
  --m-btn-border-color: var(--yee-warning-color);
211
212
  --m-btn-border-hover-color: var(--yee-warning-color-hover);
212
213
  --m-btn-border-active-color: var(--yee-warning-color-active);
213
- --m-btn-hover-bg-color: var(--yee-warning-color-hover);
214
+ --m-btn-hover-bg-color: var(--yee-warning-color-border);
214
215
  --m-btn-active-bg-color: var(--yee-warning-color-active);
215
216
  --m-btn-active-shadow-color: var(--yee-warning-color-active);
216
217
  }
@@ -256,7 +256,7 @@ var Drawer = (baseprops) => {
256
256
  className: (0, import_clsx.default)(`${prefixCls}-header`, classNames == null ? void 0 : classNames.header),
257
257
  style: styles == null ? void 0 : styles.header
258
258
  },
259
- /* @__PURE__ */ import_react2.default.createElement("div", { className: `${prefixCls}-title` }, title)
259
+ /* @__PURE__ */ import_react2.default.createElement("div", { className: (0, import_clsx.default)(`${prefixCls}-title`, classNames == null ? void 0 : classNames.title), style: styles == null ? void 0 : styles.title }, title)
260
260
  ) : null,
261
261
  /* @__PURE__ */ import_react2.default.createElement(
262
262
  "div",
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import type { DataAttributeProps } from '../utils/types';
3
- export type SemanticDOM = 'mask' | 'wrapper' | 'close' | 'header' | 'content' | 'body' | 'footer';
3
+ export type SemanticDOM = 'mask' | 'wrapper' | 'close' | 'header' | 'title' | 'content' | 'body' | 'footer';
4
4
  export interface DrawerProps extends DataAttributeProps {
5
5
  /**
6
6
  * Custom prefix class name
@@ -38,6 +38,7 @@
38
38
  }
39
39
 
40
40
  &-title {
41
+ font-size: var(--yee-drawer-title-font-size);
41
42
  font-weight: var(--yee-drawer-title-font-weight);
42
43
  }
43
44
 
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const _default: () => React.JSX.Element;
3
+ export default _default;
@@ -0,0 +1,53 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/List/demo/virtual.tsx
30
+ var virtual_exports = {};
31
+ __export(virtual_exports, {
32
+ default: () => virtual_default
33
+ });
34
+ module.exports = __toCommonJS(virtual_exports);
35
+ var import_yee_c = require("../..");
36
+ var import_react = __toESM(require("react"));
37
+ var items = Array.from({ length: 1e4 }, (_, i) => ({
38
+ key: String(i),
39
+ label: `List item ${i + 1}`,
40
+ value: String(i)
41
+ }));
42
+ var virtual_default = () => {
43
+ return /* @__PURE__ */ import_react.default.createElement(
44
+ import_yee_c.List,
45
+ {
46
+ virtual: true,
47
+ height: 300,
48
+ itemHeight: 32,
49
+ items,
50
+ onClick: (item) => console.log("Clicked:", item.label)
51
+ }
52
+ );
53
+ };
@@ -0,0 +1,28 @@
1
+ import type { ListItemProps } from '../interface';
2
+ interface UseListKeyboardParams {
3
+ items: Array<ListItemProps>;
4
+ /**
5
+ * Number of columns in the grid layout.
6
+ * Affects ArrowUp/Down (jump by columns) and ArrowLeft/Right behavior.
7
+ * @default 1
8
+ */
9
+ columns?: number;
10
+ /**
11
+ * Controlled focused key from the parent.
12
+ * When provided, the hook uses this value instead of internal state.
13
+ */
14
+ focusedKey?: string | number;
15
+ /**
16
+ * Callback when focused key changes.
17
+ */
18
+ onFocusChange?: (key: string | number) => void;
19
+ /**
20
+ * Callback when Enter is pressed on a focused item.
21
+ */
22
+ onClick?: (item: ListItemProps) => void;
23
+ }
24
+ export default function useListKeyboard({ items, columns, focusedKey: controlledFocusedKey, onFocusChange, onClick, }: UseListKeyboardParams): {
25
+ focusedKey: string | number;
26
+ onKeyDown: (event: React.KeyboardEvent) => void;
27
+ };
28
+ export {};
@@ -0,0 +1,188 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/List/hooks/useListKeyboard.ts
20
+ var useListKeyboard_exports = {};
21
+ __export(useListKeyboard_exports, {
22
+ default: () => useListKeyboard
23
+ });
24
+ module.exports = __toCommonJS(useListKeyboard_exports);
25
+ var import_react = require("react");
26
+ function useListKeyboard({
27
+ items,
28
+ columns = 1,
29
+ focusedKey: controlledFocusedKey,
30
+ onFocusChange,
31
+ onClick
32
+ }) {
33
+ const [internalFocusedKey, setInternalFocusedKey] = (0, import_react.useState)("");
34
+ const isControlled = controlledFocusedKey !== void 0;
35
+ const focusedKey = isControlled ? controlledFocusedKey : internalFocusedKey;
36
+ const setFocusedKey = (0, import_react.useCallback)(
37
+ (key) => {
38
+ if (!isControlled) {
39
+ setInternalFocusedKey(key);
40
+ }
41
+ onFocusChange == null ? void 0 : onFocusChange(key);
42
+ },
43
+ [isControlled, onFocusChange]
44
+ );
45
+ (0, import_react.useEffect)(() => {
46
+ if (!isControlled && internalFocusedKey !== "" && !items.some((item) => item.key === internalFocusedKey)) {
47
+ setInternalFocusedKey("");
48
+ }
49
+ }, [items, isControlled, internalFocusedKey]);
50
+ const getFocusedIndex = () => {
51
+ if (focusedKey === "" || focusedKey === void 0)
52
+ return -1;
53
+ return items.findIndex((item) => item.key === focusedKey);
54
+ };
55
+ const findNextEnabledIndex = (startIndex, direction) => {
56
+ const count = items.length;
57
+ if (count === 0)
58
+ return -1;
59
+ let next = direction === 1 ? startIndex + 1 >= count ? 0 : startIndex + 1 : startIndex - 1 < 0 ? count - 1 : startIndex - 1;
60
+ let attempts = 0;
61
+ while (items[next].disabled && attempts < count) {
62
+ next = direction === 1 ? next + 1 >= count ? 0 : next + 1 : next - 1 < 0 ? count - 1 : next - 1;
63
+ attempts++;
64
+ }
65
+ return items[next].disabled ? -1 : next;
66
+ };
67
+ const handleArrowUp = () => {
68
+ var _a;
69
+ const focusedIndex = getFocusedIndex();
70
+ let nextIndex;
71
+ if (columns > 1) {
72
+ if (focusedIndex === -1) {
73
+ nextIndex = findNextEnabledIndex(items.length - 1, -1);
74
+ } else {
75
+ const target = focusedIndex - columns;
76
+ if (target >= 0) {
77
+ nextIndex = items[target].disabled ? findNextEnabledIndex(target, -1) : target;
78
+ } else {
79
+ const lastRowStart = Math.floor((items.length - 1) / columns) * columns;
80
+ const col = focusedIndex % columns;
81
+ const wrapTarget = Math.min(lastRowStart + col, items.length - 1);
82
+ nextIndex = ((_a = items[wrapTarget]) == null ? void 0 : _a.disabled) ? findNextEnabledIndex(wrapTarget, -1) : wrapTarget;
83
+ }
84
+ }
85
+ } else {
86
+ if (focusedIndex === -1) {
87
+ nextIndex = findNextEnabledIndex(items.length - 1, -1);
88
+ } else {
89
+ nextIndex = findNextEnabledIndex(focusedIndex, -1);
90
+ }
91
+ }
92
+ if (nextIndex !== -1) {
93
+ setFocusedKey(items[nextIndex].key);
94
+ }
95
+ };
96
+ const handleArrowDown = () => {
97
+ var _a;
98
+ const focusedIndex = getFocusedIndex();
99
+ let nextIndex;
100
+ if (columns > 1) {
101
+ if (focusedIndex === -1) {
102
+ nextIndex = findNextEnabledIndex(-1, 1);
103
+ } else {
104
+ const target = focusedIndex + columns;
105
+ if (target < items.length) {
106
+ nextIndex = items[target].disabled ? findNextEnabledIndex(target, 1) : target;
107
+ } else {
108
+ const col = focusedIndex % columns;
109
+ const wrapTarget = col;
110
+ nextIndex = ((_a = items[wrapTarget]) == null ? void 0 : _a.disabled) ? findNextEnabledIndex(wrapTarget, 1) : wrapTarget;
111
+ }
112
+ }
113
+ } else {
114
+ if (focusedIndex === -1) {
115
+ nextIndex = findNextEnabledIndex(-1, 1);
116
+ } else {
117
+ nextIndex = findNextEnabledIndex(focusedIndex, 1);
118
+ }
119
+ }
120
+ if (nextIndex !== -1) {
121
+ setFocusedKey(items[nextIndex].key);
122
+ }
123
+ };
124
+ const handleArrowLeft = () => {
125
+ const focusedIndex = getFocusedIndex();
126
+ if (focusedIndex <= 0)
127
+ return;
128
+ const nextIndex = findNextEnabledIndex(focusedIndex, -1);
129
+ if (nextIndex !== -1) {
130
+ setFocusedKey(items[nextIndex].key);
131
+ }
132
+ };
133
+ const handleArrowRight = () => {
134
+ const focusedIndex = getFocusedIndex();
135
+ if (focusedIndex >= items.length - 1 && focusedIndex !== -1)
136
+ return;
137
+ const nextIndex = findNextEnabledIndex(
138
+ focusedIndex === -1 ? -1 : focusedIndex,
139
+ 1
140
+ );
141
+ if (nextIndex !== -1) {
142
+ setFocusedKey(items[nextIndex].key);
143
+ }
144
+ };
145
+ const handleEnter = () => {
146
+ if (focusedKey === "" || focusedKey === void 0)
147
+ return;
148
+ const item = items.find((i) => i.key === focusedKey);
149
+ if (item && !item.disabled) {
150
+ onClick == null ? void 0 : onClick(item);
151
+ }
152
+ };
153
+ const onKeyDown = (event) => {
154
+ if (!items || items.length === 0)
155
+ return;
156
+ switch (event.key) {
157
+ case "ArrowUp":
158
+ event.preventDefault();
159
+ handleArrowUp();
160
+ break;
161
+ case "ArrowDown":
162
+ event.preventDefault();
163
+ handleArrowDown();
164
+ break;
165
+ case "ArrowLeft":
166
+ if (columns > 1) {
167
+ event.preventDefault();
168
+ handleArrowLeft();
169
+ }
170
+ break;
171
+ case "ArrowRight":
172
+ if (columns > 1) {
173
+ event.preventDefault();
174
+ handleArrowRight();
175
+ }
176
+ break;
177
+ case "Enter":
178
+ event.preventDefault();
179
+ handleEnter();
180
+ break;
181
+ default:
182
+ }
183
+ };
184
+ return {
185
+ focusedKey,
186
+ onKeyDown
187
+ };
188
+ }
@@ -47,8 +47,8 @@ export interface ListProps extends Omit<React.HTMLAttributes<HTMLUListElement>,
47
47
  */
48
48
  bordered?: boolean;
49
49
  /**
50
- * Set the focused item
51
- * */
50
+ * Set the focused item (controlled)
51
+ */
52
52
  focusedKey?: string | number;
53
53
  /**
54
54
  * Render list item as a function
@@ -58,6 +58,33 @@ export interface ListProps extends Omit<React.HTMLAttributes<HTMLUListElement>,
58
58
  * Click event for list items
59
59
  */
60
60
  onClick?: (item: ListItemProps) => void;
61
+ /**
62
+ * Callback when focused item changes via keyboard navigation
63
+ */
64
+ onFocusChange?: (key: string | number) => void;
65
+ /**
66
+ * Enable virtual scrolling for large lists.
67
+ * Requires `height` to be set.
68
+ * @default false
69
+ */
70
+ virtual?: boolean;
71
+ /**
72
+ * Height of the scrollable container in pixels.
73
+ * Required when `virtual` is true.
74
+ */
75
+ height?: number;
76
+ /**
77
+ * Fixed height of each list item row in pixels.
78
+ * Used for virtual scroll calculation.
79
+ * @default 32
80
+ */
81
+ itemHeight?: number;
82
+ /**
83
+ * Number of columns in the list layout.
84
+ * When greater than 1, items are displayed in a grid.
85
+ * @default 1
86
+ */
87
+ columns?: number;
61
88
  }
62
89
  export type ListCtxType = {
63
90
  prefixCls: string;
@@ -65,7 +65,9 @@ module.exports = __toCommonJS(list_exports);
65
65
  var import_clsx = __toESM(require("clsx"));
66
66
  var import_react = __toESM(require("react"));
67
67
  var import_Config_Provider = require("../Config-Provider");
68
+ var import_useVirtualList = __toESM(require("../hooks/useVirtualList"));
68
69
  var import_mergeContextToProps = __toESM(require("../utils/mergeContextToProps"));
70
+ var import_useListKeyboard = __toESM(require("./hooks/useListKeyboard"));
69
71
  var import_list_item = __toESM(require("./list-item"));
70
72
  var import_style = require("./style/index.less");
71
73
  var ListCtx = (0, import_react.createContext)({});
@@ -75,46 +77,164 @@ var List = (0, import_react.forwardRef)((baseprops, ref) => {
75
77
  const _a = props, {
76
78
  prefixCls = "yee-list",
77
79
  className,
80
+ style,
78
81
  items,
79
82
  bordered,
80
- focusedKey,
83
+ focusedKey: controlledFocusedKey,
81
84
  itemRender,
82
- onClick
85
+ onClick,
86
+ onFocusChange,
87
+ virtual = false,
88
+ height,
89
+ itemHeight = 32,
90
+ columns = 1
83
91
  } = _a, rest = __objRest(_a, [
84
92
  "prefixCls",
85
93
  "className",
94
+ "style",
86
95
  "items",
87
96
  "bordered",
88
97
  "focusedKey",
89
98
  "itemRender",
90
- "onClick"
99
+ "onClick",
100
+ "onFocusChange",
101
+ "virtual",
102
+ "height",
103
+ "itemHeight",
104
+ "columns"
91
105
  ]);
106
+ const multiColumn = columns > 1;
107
+ const useVirtual = virtual && height !== null && height !== void 0 && Array.isArray(items);
108
+ const safeItems = Array.isArray(items) ? items : [];
109
+ const { focusedKey, onKeyDown } = (0, import_useListKeyboard.default)({
110
+ items: safeItems,
111
+ columns,
112
+ focusedKey: controlledFocusedKey,
113
+ onFocusChange,
114
+ onClick
115
+ });
116
+ const rowCount = multiColumn ? Math.ceil(safeItems.length / columns) : safeItems.length;
117
+ const { start, end, offsetY, totalHeight, viewportRef, onScroll } = (0, import_useVirtualList.default)({
118
+ itemCount: useVirtual ? rowCount : 0,
119
+ itemHeight,
120
+ overscan: 4
121
+ });
92
122
  const cls = (0, import_clsx.default)(
93
123
  prefixCls,
94
124
  {
95
- [`${prefixCls}-bordered`]: bordered
125
+ [`${prefixCls}-bordered`]: bordered,
126
+ [`${prefixCls}-grid`]: multiColumn && !useVirtual
96
127
  },
97
128
  className
98
129
  );
99
- const itemRenders = () => {
100
- return Array.isArray(items) ? items.map((item, index) => {
101
- if (typeof itemRender === "function") {
102
- return itemRender(item);
103
- }
104
- return /* @__PURE__ */ import_react.default.createElement(import_list_item.default, __spreadProps(__spreadValues({}, item), { $key: item.key, key: item.key || index }));
105
- }) : null;
130
+ const renderItem = (item, index) => {
131
+ if (typeof itemRender === "function") {
132
+ return itemRender(item);
133
+ }
134
+ return /* @__PURE__ */ import_react.default.createElement(import_list_item.default, __spreadProps(__spreadValues({}, item), { $key: item.key, key: item.key || index }));
106
135
  };
107
- return /* @__PURE__ */ import_react.default.createElement("ul", __spreadValues({ ref, className: cls, tabIndex: 0, "aria-label": "list" }, rest), /* @__PURE__ */ import_react.default.createElement(
108
- ListCtx.Provider,
109
- {
110
- value: {
111
- prefixCls,
112
- focusedKey,
113
- onClick
136
+ if (useVirtual && multiColumn) {
137
+ const visibleRows = [];
138
+ for (let rowIdx = start; rowIdx < end; rowIdx++) {
139
+ const rowItems = [];
140
+ for (let col = 0; col < columns; col++) {
141
+ const flatIdx = rowIdx * columns + col;
142
+ if (flatIdx < safeItems.length) {
143
+ rowItems.push({ item: safeItems[flatIdx], flatIdx });
144
+ }
114
145
  }
115
- },
116
- itemRenders()
117
- ));
146
+ visibleRows.push({ rowIdx, rowItems });
147
+ }
148
+ return /* @__PURE__ */ import_react.default.createElement(
149
+ "ul",
150
+ __spreadValues({
151
+ ref,
152
+ className: cls,
153
+ tabIndex: 0,
154
+ "aria-label": "list",
155
+ onKeyDown
156
+ }, rest),
157
+ /* @__PURE__ */ import_react.default.createElement(ListCtx.Provider, { value: { prefixCls, focusedKey, onClick } }, /* @__PURE__ */ import_react.default.createElement(
158
+ "div",
159
+ {
160
+ ref: viewportRef,
161
+ onScroll,
162
+ style: { height, overflowY: "auto" }
163
+ },
164
+ /* @__PURE__ */ import_react.default.createElement("div", { style: { height: totalHeight, position: "relative" } }, visibleRows.map(({ rowIdx, rowItems }, ri) => /* @__PURE__ */ import_react.default.createElement(
165
+ "div",
166
+ {
167
+ key: rowIdx,
168
+ className: `${prefixCls}-grid-row`,
169
+ style: {
170
+ position: "absolute",
171
+ top: 0,
172
+ left: 0,
173
+ right: 0,
174
+ height: itemHeight,
175
+ transform: `translateY(${offsetY + ri * itemHeight}px)`,
176
+ display: "grid",
177
+ gridTemplateColumns: `repeat(${columns}, 1fr)`
178
+ }
179
+ },
180
+ rowItems.map(
181
+ ({ item, flatIdx }) => renderItem(item, flatIdx)
182
+ )
183
+ )))
184
+ ))
185
+ );
186
+ }
187
+ if (useVirtual) {
188
+ const slicedItems = safeItems.slice(start, end);
189
+ return /* @__PURE__ */ import_react.default.createElement(
190
+ "ul",
191
+ __spreadValues({
192
+ ref,
193
+ className: cls,
194
+ tabIndex: 0,
195
+ "aria-label": "list",
196
+ onKeyDown
197
+ }, rest),
198
+ /* @__PURE__ */ import_react.default.createElement(ListCtx.Provider, { value: { prefixCls, focusedKey, onClick } }, /* @__PURE__ */ import_react.default.createElement(
199
+ "div",
200
+ {
201
+ ref: viewportRef,
202
+ onScroll,
203
+ style: { height, overflowY: "auto" }
204
+ },
205
+ /* @__PURE__ */ import_react.default.createElement("div", { style: { height: totalHeight, position: "relative" } }, slicedItems.map((item, i) => {
206
+ const element = renderItem(item, start + i);
207
+ return /* @__PURE__ */ import_react.default.createElement(
208
+ "div",
209
+ {
210
+ key: item.key || start + i,
211
+ style: {
212
+ position: "absolute",
213
+ top: 0,
214
+ left: 0,
215
+ width: "100%",
216
+ height: itemHeight,
217
+ transform: `translateY(${offsetY + i * itemHeight}px)`
218
+ }
219
+ },
220
+ element
221
+ );
222
+ }))
223
+ ))
224
+ );
225
+ }
226
+ return /* @__PURE__ */ import_react.default.createElement(
227
+ "ul",
228
+ __spreadValues({
229
+ ref,
230
+ className: cls,
231
+ tabIndex: 0,
232
+ "aria-label": "list",
233
+ onKeyDown,
234
+ style: multiColumn ? __spreadValues({ "--yee-list-columns": columns }, style) : style
235
+ }, rest),
236
+ /* @__PURE__ */ import_react.default.createElement(ListCtx.Provider, { value: { prefixCls, focusedKey, onClick } }, safeItems.map((item, index) => renderItem(item, index)))
237
+ );
118
238
  });
119
239
  List.displayName = "List";
120
240
  var list_default = List;
@@ -6,18 +6,42 @@
6
6
  list-style: none;
7
7
  background-color: var(--yee-list-bg-color);
8
8
 
9
+ &:focus {
10
+ outline: none;
11
+ }
12
+
9
13
  &-item {
10
14
  padding: var(--yee-list-item-padding);
11
15
 
12
16
  &:hover:not(&-disabled) {
13
17
  background-color: var(--yee-list-item-bg-hover-color);
18
+ }
19
+
20
+ &-disabled {
14
21
  cursor: not-allowed;
22
+ opacity: 0.5;
23
+ }
24
+
25
+ &-clickable:not(&-disabled) {
26
+ cursor: pointer;
15
27
  }
16
28
 
17
29
  &-focused {
18
30
  background-color: var(--yee-list-item-bg-hover-color);
19
31
  }
20
32
  }
33
+
34
+ // Multi-column grid layout (non-virtual mode).
35
+ // Column count driven by CSS custom property --yee-list-columns set inline.
36
+ &-grid {
37
+ display: grid;
38
+ grid-template-columns: repeat(var(--yee-list-columns, 1), 1fr);
39
+ }
40
+
41
+ // Virtual multi-column: each row is already a grid via inline style.
42
+ &-grid-row {
43
+ align-items: center;
44
+ }
21
45
  }
22
46
 
23
47
  @{pls}-bordered {
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const _default: () => React.JSX.Element;
3
+ export default _default;