@rainbow-oh/yee-c 0.4.5 → 0.5.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.
- package/dist/cjs/Dialog/demo/basic.js +1 -1
- package/dist/cjs/Dialog/dialog.js +1 -1
- package/dist/cjs/Field/demo/validation.js +23 -3
- package/dist/cjs/Field/field.js +1 -1
- package/dist/cjs/Form/Field.js +1 -4
- package/dist/cjs/Form/Form.js +1 -1
- package/dist/cjs/Form/Group.js +36 -14
- package/dist/cjs/Form/List.js +23 -3
- package/dist/cjs/Form/demo/async-validate.d.ts +3 -0
- package/dist/cjs/Form/demo/async-validate.js +108 -0
- package/dist/cjs/Form/demo/virtual.js +1 -1
- package/dist/cjs/Form/form-store.d.ts +4 -4
- package/dist/cjs/Form/form-store.js +55 -25
- package/dist/cjs/Form/interface.d.ts +10 -7
- package/dist/cjs/Form/utils/validate.d.ts +23 -2
- package/dist/cjs/Form/utils/validate.js +59 -10
- package/dist/cjs/Select/demo/basic.js +1 -1
- package/dist/cjs/Select/demo/virtual.d.ts +3 -0
- package/dist/cjs/Select/demo/virtual.js +55 -0
- package/dist/cjs/Select/hooks/useSelectKeyboard.d.ts +7 -1
- package/dist/cjs/Select/hooks/useSelectKeyboard.js +16 -6
- package/dist/cjs/Select/interface.d.ts +44 -0
- package/dist/cjs/Select/option.js +3 -2
- package/dist/cjs/Select/options.js +115 -15
- package/dist/cjs/Select/select.js +20 -4
- package/dist/cjs/Select/style/index.less +17 -0
- package/dist/cjs/Table/style/index.less +19 -0
- package/dist/cjs/hooks/index.d.ts +2 -1
- package/dist/cjs/hooks/index.js +3 -1
- package/dist/cjs/hooks/useVirtualList.d.ts +71 -0
- package/dist/cjs/hooks/useVirtualList.js +117 -0
- package/dist/cjs/style/themes.css +1 -1
- package/dist/cjs/style/variables.css +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/Dialog/demo/basic.js +1 -1
- package/dist/esm/Dialog/dialog.js +1 -1
- package/dist/esm/Field/demo/validation.js +30 -9
- package/dist/esm/Field/field.js +2 -1
- package/dist/esm/Form/Field.js +3 -4
- package/dist/esm/Form/Form.js +1 -1
- package/dist/esm/Form/Group.js +142 -53
- package/dist/esm/Form/List.js +61 -42
- package/dist/esm/Form/demo/async-validate.d.ts +3 -0
- package/dist/esm/Form/demo/async-validate.js +95 -0
- package/dist/esm/Form/demo/virtual.js +1 -1
- package/dist/esm/Form/form-store.d.ts +4 -4
- package/dist/esm/Form/form-store.js +187 -93
- package/dist/esm/Form/interface.d.ts +10 -7
- package/dist/esm/Form/utils/validate.d.ts +23 -2
- package/dist/esm/Form/utils/validate.js +122 -17
- package/dist/esm/Select/demo/basic.js +1 -1
- package/dist/esm/Select/demo/virtual.d.ts +3 -0
- package/dist/esm/Select/demo/virtual.js +38 -0
- package/dist/esm/Select/hooks/useSelectKeyboard.d.ts +7 -1
- package/dist/esm/Select/hooks/useSelectKeyboard.js +25 -9
- package/dist/esm/Select/interface.d.ts +44 -0
- package/dist/esm/Select/option.js +4 -2
- package/dist/esm/Select/options.js +132 -13
- package/dist/esm/Select/select.js +19 -4
- package/dist/esm/Select/style/index.less +17 -0
- package/dist/esm/Table/style/index.less +19 -0
- package/dist/esm/hooks/index.d.ts +2 -1
- package/dist/esm/hooks/index.js +2 -1
- package/dist/esm/hooks/useVirtualList.d.ts +71 -0
- package/dist/esm/hooks/useVirtualList.js +129 -0
- package/dist/esm/style/themes.css +1 -1
- package/dist/esm/style/variables.css +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/umd/yee-c.min.css +1 -1
- package/dist/umd/yee-c.min.js +1 -1
- package/package.json +1 -1
- package/src/Dialog/demo/basic.tsx +1 -1
- package/src/Dialog/dialog.tsx +1 -1
- package/src/Field/demo/validation.tsx +2 -2
- package/src/Field/field.tsx +2 -1
- package/src/Field/index.en-US.md +1 -1
- package/src/Field/index.zh-CN.md +1 -1
- package/src/Form/Field.tsx +3 -4
- package/src/Form/Form.tsx +1 -1
- package/src/Form/Group.tsx +15 -12
- package/src/Form/List.tsx +3 -3
- package/src/Form/demo/async-validate.tsx +71 -0
- package/src/Form/demo/virtual.tsx +1 -1
- package/src/Form/form-store.ts +37 -21
- package/src/Form/index.en-US.md +6 -5
- package/src/Form/index.zh-CN.md +6 -5
- package/src/Form/interface.ts +13 -7
- package/src/Form/utils/validate.ts +65 -13
- package/src/Select/demo/basic.tsx +1 -1
- package/src/Select/demo/virtual.tsx +25 -0
- package/src/Select/hooks/useSelectKeyboard.ts +30 -6
- package/src/Select/index.en-US.md +4 -0
- package/src/Select/index.zh-CN.md +4 -0
- package/src/Select/interface.ts +48 -2
- package/src/Select/option.tsx +2 -1
- package/src/Select/options.tsx +139 -8
- package/src/Select/select.tsx +23 -1
- package/src/Select/style/index.less +17 -0
- package/src/Table/style/index.less +19 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useVirtualList.ts +169 -0
- package/src/version.ts +1 -1
|
@@ -15,11 +15,32 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
15
|
return to;
|
|
16
16
|
};
|
|
17
17
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var __async = (__this, __arguments, generator) => {
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
var fulfilled = (value) => {
|
|
21
|
+
try {
|
|
22
|
+
step(generator.next(value));
|
|
23
|
+
} catch (e) {
|
|
24
|
+
reject(e);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var rejected = (value) => {
|
|
28
|
+
try {
|
|
29
|
+
step(generator.throw(value));
|
|
30
|
+
} catch (e) {
|
|
31
|
+
reject(e);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
35
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
36
|
+
});
|
|
37
|
+
};
|
|
18
38
|
|
|
19
39
|
// src/Form/utils/validate.ts
|
|
20
40
|
var validate_exports = {};
|
|
21
41
|
__export(validate_exports, {
|
|
22
|
-
default: () => validate_default
|
|
42
|
+
default: () => validate_default,
|
|
43
|
+
runValidator: () => runValidator
|
|
23
44
|
});
|
|
24
45
|
module.exports = __toCommonJS(validate_exports);
|
|
25
46
|
function isEmpty(v) {
|
|
@@ -80,8 +101,8 @@ function verifyRuleOfRegexp(regexp, value) {
|
|
|
80
101
|
return true;
|
|
81
102
|
}
|
|
82
103
|
}
|
|
83
|
-
function
|
|
84
|
-
const { min, max, minLength, maxLength, regexp
|
|
104
|
+
function verifySyncRules(rule, value) {
|
|
105
|
+
const { min, max, minLength, maxLength, regexp } = rule;
|
|
85
106
|
if (typeof min !== "undefined" && !verifyRuleOfMin(min, value)) {
|
|
86
107
|
return false;
|
|
87
108
|
}
|
|
@@ -97,15 +118,43 @@ function verifyMain(rule, value) {
|
|
|
97
118
|
if (regexp instanceof RegExp && !verifyRuleOfRegexp(regexp, value)) {
|
|
98
119
|
return false;
|
|
99
120
|
}
|
|
100
|
-
if (typeof validator === "function" && !validator(value)) {
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
121
|
return true;
|
|
104
122
|
}
|
|
123
|
+
function runValidator(validator, value) {
|
|
124
|
+
return __async(this, null, function* () {
|
|
125
|
+
try {
|
|
126
|
+
const res = validator(value);
|
|
127
|
+
if (res instanceof Promise) {
|
|
128
|
+
const resolved = yield res;
|
|
129
|
+
if (resolved === false) {
|
|
130
|
+
return { passed: false };
|
|
131
|
+
}
|
|
132
|
+
return { passed: true };
|
|
133
|
+
}
|
|
134
|
+
if (res === false) {
|
|
135
|
+
return { passed: false };
|
|
136
|
+
}
|
|
137
|
+
return { passed: true };
|
|
138
|
+
} catch (e) {
|
|
139
|
+
return {
|
|
140
|
+
passed: false,
|
|
141
|
+
message: e instanceof Error ? e.message : String(e)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
105
146
|
function validate(rule, value) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
147
|
+
return __async(this, null, function* () {
|
|
148
|
+
if (rule.required && isEmpty(value)) {
|
|
149
|
+
return { passed: false };
|
|
150
|
+
}
|
|
151
|
+
if (!verifySyncRules(rule, value)) {
|
|
152
|
+
return { passed: false };
|
|
153
|
+
}
|
|
154
|
+
if (typeof rule.validator === "function") {
|
|
155
|
+
return runValidator(rule.validator, value);
|
|
156
|
+
}
|
|
157
|
+
return { passed: true };
|
|
158
|
+
});
|
|
110
159
|
}
|
|
111
160
|
var validate_default = validate;
|
|
@@ -47,7 +47,7 @@ var options = [
|
|
|
47
47
|
{ label: "Peach", value: "peach" }
|
|
48
48
|
];
|
|
49
49
|
var basic_default = () => {
|
|
50
|
-
const [value, setValue] = (0, import_react.useState)("
|
|
50
|
+
const [value, setValue] = (0, import_react.useState)("mango");
|
|
51
51
|
return /* @__PURE__ */ import_react.default.createElement(
|
|
52
52
|
import_yee_c.Select,
|
|
53
53
|
{
|
|
@@ -0,0 +1,55 @@
|
|
|
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/Select/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 options = Array.from({ length: 5e3 }, (_, i) => ({
|
|
38
|
+
label: `Option ${i + 1}`,
|
|
39
|
+
value: i
|
|
40
|
+
}));
|
|
41
|
+
var virtual_default = () => {
|
|
42
|
+
const [value, setValue] = (0, import_react.useState)(100);
|
|
43
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
44
|
+
import_yee_c.Select,
|
|
45
|
+
{
|
|
46
|
+
virtual: true,
|
|
47
|
+
searchable: true,
|
|
48
|
+
value,
|
|
49
|
+
onChange: (val) => setValue(val),
|
|
50
|
+
options,
|
|
51
|
+
style: { width: 200 },
|
|
52
|
+
placeholder: "Please select"
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
};
|
|
@@ -11,8 +11,14 @@ interface UseSelectKeyboardParams {
|
|
|
11
11
|
onClose?: () => void;
|
|
12
12
|
onOpenChange?: (open: boolean) => void;
|
|
13
13
|
containerRef?: React.RefObject<HTMLElement>;
|
|
14
|
+
/**
|
|
15
|
+
* Virtual-mode scroll hook. When provided, keyboard navigation drives the
|
|
16
|
+
* virtual viewport through this callback instead of calling scrollIntoView
|
|
17
|
+
* (the focused option may not be in the DOM while virtualized).
|
|
18
|
+
*/
|
|
19
|
+
scrollToIndex?: (index: number) => void;
|
|
14
20
|
}
|
|
15
|
-
export default function useSelectKeyboard({ options, open, selectedKeys, onSelect, onClose, onOpenChange, containerRef, }: UseSelectKeyboardParams): {
|
|
21
|
+
export default function useSelectKeyboard({ options, open, selectedKeys, onSelect, onClose, onOpenChange, containerRef, scrollToIndex, }: UseSelectKeyboardParams): {
|
|
16
22
|
focusedKey: string | number;
|
|
17
23
|
onKeyDown: (event: React.KeyboardEvent) => void;
|
|
18
24
|
};
|
|
@@ -41,7 +41,8 @@ function useSelectKeyboard({
|
|
|
41
41
|
onSelect,
|
|
42
42
|
onClose,
|
|
43
43
|
onOpenChange,
|
|
44
|
-
containerRef
|
|
44
|
+
containerRef,
|
|
45
|
+
scrollToIndex
|
|
45
46
|
}) {
|
|
46
47
|
const [focusedKey, setFocusedKey] = (0, import_react.useState)("");
|
|
47
48
|
const latestFocusedKey = (0, import_useLatest.default)(focusedKey);
|
|
@@ -69,6 +70,10 @@ function useSelectKeyboard({
|
|
|
69
70
|
}
|
|
70
71
|
};
|
|
71
72
|
const scrollOptionIntoView = (index) => {
|
|
73
|
+
if (scrollToIndex) {
|
|
74
|
+
scrollToIndex(index);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
72
77
|
const container = containerRef == null ? void 0 : containerRef.current;
|
|
73
78
|
if (!container)
|
|
74
79
|
return;
|
|
@@ -150,18 +155,23 @@ function useSelectKeyboard({
|
|
|
150
155
|
};
|
|
151
156
|
(0, import_react.useEffect)(() => {
|
|
152
157
|
if (open) {
|
|
158
|
+
let focusedValue = "";
|
|
153
159
|
if ((selectedKeys == null ? void 0 : selectedKeys.length) > 0) {
|
|
154
160
|
const firstSelected = options == null ? void 0 : options.find(
|
|
155
161
|
(opt) => opt.value === selectedKeys[0]
|
|
156
162
|
);
|
|
157
163
|
if (firstSelected && !firstSelected.disabled) {
|
|
158
|
-
|
|
159
|
-
|
|
164
|
+
focusedValue = firstSelected.value;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (!focusedValue) {
|
|
168
|
+
const firstEnabled = options == null ? void 0 : options.find((opt) => !opt.disabled);
|
|
169
|
+
if (firstEnabled) {
|
|
170
|
+
focusedValue = firstEnabled.value;
|
|
160
171
|
}
|
|
161
172
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
setFocusedKey(firstEnabled.value);
|
|
173
|
+
if (focusedValue) {
|
|
174
|
+
setFocusedKey(focusedValue);
|
|
165
175
|
}
|
|
166
176
|
} else {
|
|
167
177
|
setFocusedKey("");
|
|
@@ -94,6 +94,26 @@ export interface SelectProps extends DataAttributeProps {
|
|
|
94
94
|
* Callback when searching
|
|
95
95
|
*/
|
|
96
96
|
onFilter?: (value: string, options: Array<Option>) => Array<Option>;
|
|
97
|
+
/**
|
|
98
|
+
* Enable virtual scrolling for the dropdown.
|
|
99
|
+
*
|
|
100
|
+
* When enabled, only the options inside the visible window are rendered
|
|
101
|
+
* (the DOM node count stays constant regardless of how many options there
|
|
102
|
+
* are). Recommended for large option sets (hundreds or thousands).
|
|
103
|
+
* @default false
|
|
104
|
+
*/
|
|
105
|
+
virtual?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Height of each option in pixels. Required to be a fixed value when
|
|
108
|
+
* `virtual` is enabled (the list assumes every option has exactly this height).
|
|
109
|
+
* @default 32
|
|
110
|
+
*/
|
|
111
|
+
itemHeight?: number;
|
|
112
|
+
/**
|
|
113
|
+
* Max height of the dropdown popup in pixels.
|
|
114
|
+
* @default 200
|
|
115
|
+
*/
|
|
116
|
+
listHeight?: number;
|
|
97
117
|
}
|
|
98
118
|
/**
|
|
99
119
|
* Props for the internal Option component (renders a single dropdown option).
|
|
@@ -119,6 +139,11 @@ export interface OptionProps {
|
|
|
119
139
|
* Test id forwarded to the option element
|
|
120
140
|
*/
|
|
121
141
|
dataTestId?: string;
|
|
142
|
+
/**
|
|
143
|
+
* Inline style forwarded to the option element.
|
|
144
|
+
* Used by virtual scrolling to position each option absolutely.
|
|
145
|
+
*/
|
|
146
|
+
style?: React.CSSProperties;
|
|
122
147
|
}
|
|
123
148
|
/**
|
|
124
149
|
* Context value shared between Options and each Option.
|
|
@@ -167,6 +192,25 @@ export interface OptionsProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
|
|
|
167
192
|
* Whether multiple selection mode is active
|
|
168
193
|
*/
|
|
169
194
|
multiple: boolean;
|
|
195
|
+
/**
|
|
196
|
+
* Whether virtual scrolling is enabled
|
|
197
|
+
*/
|
|
198
|
+
virtual?: boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Fixed option height in pixels (only meaningful when `virtual` is enabled)
|
|
201
|
+
*/
|
|
202
|
+
itemHeight?: number;
|
|
203
|
+
/**
|
|
204
|
+
* Max popup height in pixels (only meaningful when `virtual` is enabled)
|
|
205
|
+
*/
|
|
206
|
+
listHeight?: number;
|
|
207
|
+
/**
|
|
208
|
+
* Ref that receives the virtual list API (currently `scrollToIndex`),
|
|
209
|
+
* so the parent can wire keyboard navigation to the virtual viewport.
|
|
210
|
+
*/
|
|
211
|
+
virtualApiRef?: React.MutableRefObject<{
|
|
212
|
+
scrollToIndex: (index: number) => void;
|
|
213
|
+
} | null>;
|
|
170
214
|
/**
|
|
171
215
|
* Callback when an option is selected
|
|
172
216
|
*/
|
|
@@ -37,7 +37,7 @@ var import_lucide_react = require("lucide-react");
|
|
|
37
37
|
var import_react = __toESM(require("react"));
|
|
38
38
|
var import_options = require("./options");
|
|
39
39
|
var Option = (props) => {
|
|
40
|
-
const { label, value, disabled, title, dataTestId } = props;
|
|
40
|
+
const { label, value, disabled, title, dataTestId, style } = props;
|
|
41
41
|
const { prefixCls, selectedKeys, focusedKey, multiple, onSelect } = (0, import_react.useContext)(import_options.OptionsCtx);
|
|
42
42
|
const handleClick = (e) => {
|
|
43
43
|
if (!disabled) {
|
|
@@ -64,7 +64,8 @@ var Option = (props) => {
|
|
|
64
64
|
role: "option",
|
|
65
65
|
tabIndex: disabled ? void 0 : 0,
|
|
66
66
|
title: htmlTitle,
|
|
67
|
-
"data-testid": dataTestId
|
|
67
|
+
"data-testid": dataTestId,
|
|
68
|
+
style
|
|
68
69
|
},
|
|
69
70
|
/* @__PURE__ */ import_react.default.createElement("div", { className: `${prefixCls}-option-content` }, label),
|
|
70
71
|
multiple && selected && /* @__PURE__ */ import_react.default.createElement("span", { className: `${prefixCls}-option-state` }, /* @__PURE__ */ import_react.default.createElement(import_lucide_react.Check, { size: 16 }))
|
|
@@ -64,6 +64,7 @@ __export(options_exports, {
|
|
|
64
64
|
module.exports = __toCommonJS(options_exports);
|
|
65
65
|
var import_clsx = __toESM(require("clsx"));
|
|
66
66
|
var import_react = __toESM(require("react"));
|
|
67
|
+
var import_useVirtualList = __toESM(require("../hooks/useVirtualList"));
|
|
67
68
|
var import_locale = require("../locale");
|
|
68
69
|
var import_option = __toESM(require("./option"));
|
|
69
70
|
var OptionsCtx = (0, import_react.createContext)(
|
|
@@ -82,6 +83,10 @@ var Options = (0, import_react.forwardRef)(
|
|
|
82
83
|
focusedKey,
|
|
83
84
|
dataTestId,
|
|
84
85
|
multiple,
|
|
86
|
+
virtual,
|
|
87
|
+
itemHeight = 32,
|
|
88
|
+
listHeight = 200,
|
|
89
|
+
virtualApiRef,
|
|
85
90
|
onSelect
|
|
86
91
|
} = _a, rest = __objRest(_a, [
|
|
87
92
|
"prefixCls",
|
|
@@ -92,30 +97,125 @@ var Options = (0, import_react.forwardRef)(
|
|
|
92
97
|
"focusedKey",
|
|
93
98
|
"dataTestId",
|
|
94
99
|
"multiple",
|
|
100
|
+
"virtual",
|
|
101
|
+
"itemHeight",
|
|
102
|
+
"listHeight",
|
|
103
|
+
"virtualApiRef",
|
|
95
104
|
"onSelect"
|
|
96
105
|
]);
|
|
97
|
-
const
|
|
106
|
+
const rootRef = (0, import_react.useRef)(null);
|
|
107
|
+
(0, import_react.useImperativeHandle)(ref, () => rootRef.current, []);
|
|
108
|
+
const {
|
|
109
|
+
start,
|
|
110
|
+
end,
|
|
111
|
+
offsetY,
|
|
112
|
+
totalHeight,
|
|
113
|
+
viewportRef,
|
|
114
|
+
onScroll,
|
|
115
|
+
scrollToIndex
|
|
116
|
+
} = (0, import_useVirtualList.default)({
|
|
117
|
+
itemCount: options.length,
|
|
118
|
+
itemHeight
|
|
119
|
+
});
|
|
120
|
+
(0, import_react.useEffect)(() => {
|
|
121
|
+
if (!virtual || !virtualApiRef)
|
|
122
|
+
return;
|
|
123
|
+
virtualApiRef.current = { scrollToIndex };
|
|
124
|
+
return () => {
|
|
125
|
+
if (virtualApiRef.current) {
|
|
126
|
+
virtualApiRef.current = null;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}, [virtual, virtualApiRef, scrollToIndex]);
|
|
130
|
+
(0, import_react.useEffect)(() => {
|
|
131
|
+
if (virtual) {
|
|
132
|
+
scrollToIndex(0);
|
|
133
|
+
}
|
|
134
|
+
}, [options, virtual, scrollToIndex]);
|
|
135
|
+
(0, import_react.useEffect)(() => {
|
|
136
|
+
if (options.length === 0)
|
|
137
|
+
return;
|
|
138
|
+
if (focusedKey === "")
|
|
139
|
+
return;
|
|
140
|
+
const focusedIndex = options.findIndex((o) => o.value === focusedKey);
|
|
141
|
+
if (focusedIndex < 0)
|
|
142
|
+
return;
|
|
143
|
+
if (virtual) {
|
|
144
|
+
scrollToIndex(focusedIndex);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const container = rootRef.current;
|
|
148
|
+
if (!container)
|
|
149
|
+
return;
|
|
150
|
+
const optionElements = container.querySelectorAll('[role="option"]');
|
|
151
|
+
const targetElement = optionElements[focusedIndex];
|
|
152
|
+
if (targetElement) {
|
|
153
|
+
targetElement.scrollIntoView({ block: "nearest" });
|
|
154
|
+
}
|
|
155
|
+
}, [focusedKey, virtual, options, scrollToIndex, rootRef]);
|
|
156
|
+
const isEmpty = options.length === 0;
|
|
157
|
+
const ctxValue = {
|
|
158
|
+
prefixCls,
|
|
159
|
+
selectedKeys,
|
|
160
|
+
focusedKey,
|
|
161
|
+
multiple,
|
|
162
|
+
onSelect
|
|
163
|
+
};
|
|
164
|
+
if (virtual && !isEmpty) {
|
|
165
|
+
const visibleOptions = options.slice(start, end);
|
|
166
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
167
|
+
"div",
|
|
168
|
+
__spreadProps(__spreadValues({}, rest), {
|
|
169
|
+
className: (0, import_clsx.default)(
|
|
170
|
+
`${prefixCls}-popup`,
|
|
171
|
+
`${prefixCls}-popup-virtual`,
|
|
172
|
+
popupClassName
|
|
173
|
+
),
|
|
174
|
+
style: popupStyle,
|
|
175
|
+
ref: rootRef,
|
|
176
|
+
tabIndex: -1
|
|
177
|
+
}),
|
|
178
|
+
/* @__PURE__ */ import_react.default.createElement(OptionsCtx.Provider, { value: ctxValue }, /* @__PURE__ */ import_react.default.createElement(
|
|
179
|
+
"div",
|
|
180
|
+
{
|
|
181
|
+
className: `${prefixCls}-popup-viewport`,
|
|
182
|
+
ref: viewportRef,
|
|
183
|
+
onScroll,
|
|
184
|
+
style: { maxHeight: listHeight, overflowY: "auto" }
|
|
185
|
+
},
|
|
186
|
+
/* @__PURE__ */ import_react.default.createElement("div", { style: { height: totalHeight, position: "relative" } }, visibleOptions.map((option, i) => /* @__PURE__ */ import_react.default.createElement(
|
|
187
|
+
import_option.default,
|
|
188
|
+
__spreadProps(__spreadValues({}, option), {
|
|
189
|
+
key: option.value,
|
|
190
|
+
dataTestId: `${dataTestId}-${start + i}`,
|
|
191
|
+
style: {
|
|
192
|
+
position: "absolute",
|
|
193
|
+
top: 0,
|
|
194
|
+
left: 0,
|
|
195
|
+
right: 0,
|
|
196
|
+
height: itemHeight,
|
|
197
|
+
transform: `translateY(${offsetY + i * itemHeight}px)`
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
)))
|
|
201
|
+
))
|
|
202
|
+
);
|
|
203
|
+
}
|
|
98
204
|
return /* @__PURE__ */ import_react.default.createElement(
|
|
99
205
|
"div",
|
|
100
206
|
__spreadProps(__spreadValues({}, rest), {
|
|
101
207
|
className: (0, import_clsx.default)(`${prefixCls}-popup`, popupClassName),
|
|
102
208
|
style: popupStyle,
|
|
103
|
-
ref:
|
|
209
|
+
ref: rootRef,
|
|
104
210
|
tabIndex: -1
|
|
105
211
|
}),
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
{
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
__spreadProps(__spreadValues({}, option), {
|
|
114
|
-
key: option.value,
|
|
115
|
-
dataTestId: `${dataTestId}-${index}`
|
|
116
|
-
})
|
|
117
|
-
))
|
|
118
|
-
)
|
|
212
|
+
isEmpty ? /* @__PURE__ */ import_react.default.createElement("div", { className: `${prefixCls}-empty` }, select.noData) : /* @__PURE__ */ import_react.default.createElement(OptionsCtx.Provider, { value: ctxValue }, options.map((option, index) => /* @__PURE__ */ import_react.default.createElement(
|
|
213
|
+
import_option.default,
|
|
214
|
+
__spreadProps(__spreadValues({}, option), {
|
|
215
|
+
key: option.value,
|
|
216
|
+
dataTestId: `${dataTestId}-${index}`
|
|
217
|
+
})
|
|
218
|
+
)))
|
|
119
219
|
);
|
|
120
220
|
}
|
|
121
221
|
);
|
|
@@ -83,7 +83,10 @@ var Select = (baseprops) => {
|
|
|
83
83
|
optionFilterProp = "label",
|
|
84
84
|
disabled,
|
|
85
85
|
onChange,
|
|
86
|
-
onFilter
|
|
86
|
+
onFilter,
|
|
87
|
+
virtual,
|
|
88
|
+
itemHeight,
|
|
89
|
+
listHeight
|
|
87
90
|
} = _a, rest = __objRest(_a, [
|
|
88
91
|
"prefixCls",
|
|
89
92
|
"options",
|
|
@@ -94,7 +97,10 @@ var Select = (baseprops) => {
|
|
|
94
97
|
"optionFilterProp",
|
|
95
98
|
"disabled",
|
|
96
99
|
"onChange",
|
|
97
|
-
"onFilter"
|
|
100
|
+
"onFilter",
|
|
101
|
+
"virtual",
|
|
102
|
+
"itemHeight",
|
|
103
|
+
"listHeight"
|
|
98
104
|
]);
|
|
99
105
|
const single = mode !== "multiple" && mode !== "tags" ? true : false;
|
|
100
106
|
const handleState = (value2) => {
|
|
@@ -114,6 +120,11 @@ var Select = (baseprops) => {
|
|
|
114
120
|
const [searchValue, setSearchValue] = (0, import_react.useState)("");
|
|
115
121
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
116
122
|
const popupRef = (0, import_react.useRef)(null);
|
|
123
|
+
const virtualApiRef = (0, import_react.useRef)(null);
|
|
124
|
+
const handleVirtualScrollToIndex = (0, import_react.useCallback)((index) => {
|
|
125
|
+
var _a2;
|
|
126
|
+
(_a2 = virtualApiRef.current) == null ? void 0 : _a2.scrollToIndex(index);
|
|
127
|
+
}, []);
|
|
117
128
|
const getOptions = (keys) => {
|
|
118
129
|
if (keys === "" || keys === null) {
|
|
119
130
|
return void 0;
|
|
@@ -184,7 +195,8 @@ var Select = (baseprops) => {
|
|
|
184
195
|
onSelect: handleSelect,
|
|
185
196
|
onClose: () => setOpen(false),
|
|
186
197
|
onOpenChange: handleOpenChange,
|
|
187
|
-
containerRef: popupRef
|
|
198
|
+
containerRef: popupRef,
|
|
199
|
+
scrollToIndex: virtual ? handleVirtualScrollToIndex : void 0
|
|
188
200
|
});
|
|
189
201
|
const popup = /* @__PURE__ */ import_react.default.createElement(
|
|
190
202
|
import_options.default,
|
|
@@ -196,7 +208,11 @@ var Select = (baseprops) => {
|
|
|
196
208
|
selectedKeys: mergedValue,
|
|
197
209
|
dataTestId: rest["data-testid"],
|
|
198
210
|
onSelect: handleSelect,
|
|
199
|
-
ref: popupRef
|
|
211
|
+
ref: popupRef,
|
|
212
|
+
virtual,
|
|
213
|
+
itemHeight,
|
|
214
|
+
listHeight,
|
|
215
|
+
virtualApiRef
|
|
200
216
|
}
|
|
201
217
|
);
|
|
202
218
|
return /* @__PURE__ */ import_react.default.createElement(
|
|
@@ -8,6 +8,17 @@
|
|
|
8
8
|
overflow: auto;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
// Virtual mode: the popup no longer scrolls itself; the inner viewport does.
|
|
12
|
+
// Without this override there would be two scrollbars.
|
|
13
|
+
&-popup-virtual {
|
|
14
|
+
max-height: none;
|
|
15
|
+
overflow: visible;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
&-popup-viewport {
|
|
19
|
+
overflow-y: auto;
|
|
20
|
+
}
|
|
21
|
+
|
|
11
22
|
&-option {
|
|
12
23
|
display: flex;
|
|
13
24
|
padding: var(--yee-select-option-padding);
|
|
@@ -37,6 +48,12 @@
|
|
|
37
48
|
}
|
|
38
49
|
}
|
|
39
50
|
|
|
51
|
+
// In virtual mode each option has a fixed inline height; center its content
|
|
52
|
+
// vertically so it stays aligned regardless of the inherited line-height.
|
|
53
|
+
&-popup-virtual &-option {
|
|
54
|
+
align-items: center;
|
|
55
|
+
}
|
|
56
|
+
|
|
40
57
|
&-empty {
|
|
41
58
|
padding: var(--yee-select-option-padding);
|
|
42
59
|
}
|
|
@@ -23,13 +23,32 @@
|
|
|
23
23
|
var(--yee-table-tbody-td-borderbottom-color);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
@{pls}-cell {
|
|
28
|
+
&::before {
|
|
29
|
+
display: none;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
&-thead {
|
|
29
35
|
color: var(--yee-table-thead-color);
|
|
30
36
|
|
|
31
37
|
@{pls}-cell {
|
|
38
|
+
position: relative;
|
|
32
39
|
background-color: var(--yee-table-thead-bg-color);
|
|
40
|
+
|
|
41
|
+
&:not(:last-child):not(@{pls}-expand-col) {
|
|
42
|
+
&::before {
|
|
43
|
+
position: absolute;
|
|
44
|
+
content: '';
|
|
45
|
+
width: 1.5px;
|
|
46
|
+
height: 30%;
|
|
47
|
+
top: 35%;
|
|
48
|
+
right: 0;
|
|
49
|
+
background-color: var(--yee-table-head-cell-split-line-color, #eee);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
33
52
|
}
|
|
34
53
|
|
|
35
54
|
&-cell {
|
|
@@ -16,4 +16,5 @@ import useMount from './useMount';
|
|
|
16
16
|
import usePrevious from './usePrevious';
|
|
17
17
|
import useUpdateEffect from './useUpdateEffect';
|
|
18
18
|
import useVirtualForm from './useVirtualForm';
|
|
19
|
-
|
|
19
|
+
import useVirtualList from './useVirtualList';
|
|
20
|
+
export { useBreakpoint, useDebounceFunction, useDebounceValue, useDeepCompareEffect, useDeepCompareMemo, useDeepCompareMemoize, useDelayState, useEsc, useEvent, useIntersectionObserver, useKeyControl, useLatest, useLayoutEffect, useMergedState, useMount, usePrevious, useUpdateEffect, useVirtualForm, useVirtualList, };
|
package/dist/cjs/hooks/index.js
CHANGED
|
@@ -46,7 +46,8 @@ __export(hooks_exports, {
|
|
|
46
46
|
useMount: () => import_useMount.default,
|
|
47
47
|
usePrevious: () => import_usePrevious.default,
|
|
48
48
|
useUpdateEffect: () => import_useUpdateEffect.default,
|
|
49
|
-
useVirtualForm: () => import_useVirtualForm.default
|
|
49
|
+
useVirtualForm: () => import_useVirtualForm.default,
|
|
50
|
+
useVirtualList: () => import_useVirtualList.default
|
|
50
51
|
});
|
|
51
52
|
module.exports = __toCommonJS(hooks_exports);
|
|
52
53
|
var import_useBreakpoint = __toESM(require("./useBreakpoint"));
|
|
@@ -67,3 +68,4 @@ var import_useMount = __toESM(require("./useMount"));
|
|
|
67
68
|
var import_usePrevious = __toESM(require("./usePrevious"));
|
|
68
69
|
var import_useUpdateEffect = __toESM(require("./useUpdateEffect"));
|
|
69
70
|
var import_useVirtualForm = __toESM(require("./useVirtualForm"));
|
|
71
|
+
var import_useVirtualList = __toESM(require("./useVirtualList"));
|