@rainbow-oh/yee-c 0.8.5 → 0.8.7
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/Alert/alert.js +1 -0
- package/dist/cjs/Anchor/anchor.js +195 -12
- package/dist/cjs/Anchor/interface.d.ts +1 -1
- package/dist/cjs/Input/input.js +3 -0
- package/dist/cjs/Input/style/index.less +2 -2
- package/dist/cjs/Select/option.js +2 -1
- package/dist/cjs/Select/options.js +6 -0
- package/dist/cjs/Selector/selector.js +20 -1
- package/dist/cjs/Spin/style/index.less +11 -6
- package/dist/cjs/Table/theader/filter.js +1 -1
- package/dist/cjs/Tag/tag.js +23 -8
- package/dist/cjs/Tree/interface.d.ts +2 -1
- package/dist/cjs/Tree/tree-node.js +6 -1
- package/dist/cjs/Tree/tree.js +56 -12
- package/dist/cjs/Trigger/interface.d.ts +2 -1
- 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/Alert/alert.js +1 -0
- package/dist/esm/Anchor/anchor.js +133 -12
- package/dist/esm/Anchor/interface.d.ts +1 -1
- package/dist/esm/Input/input.js +3 -0
- package/dist/esm/Input/style/index.less +2 -2
- package/dist/esm/Select/option.js +2 -1
- package/dist/esm/Select/options.js +6 -0
- package/dist/esm/Selector/selector.js +13 -1
- package/dist/esm/Spin/style/index.less +11 -6
- package/dist/esm/Table/theader/filter.js +1 -1
- package/dist/esm/Tag/tag.js +6 -1
- package/dist/esm/Tree/interface.d.ts +2 -1
- package/dist/esm/Tree/tree-node.js +6 -1
- package/dist/esm/Tree/tree.js +14 -5
- package/dist/esm/Trigger/interface.d.ts +2 -1
- 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/Alert/alert.tsx +1 -0
- package/src/Anchor/anchor.tsx +224 -13
- package/src/Anchor/index.en-US.md +1 -1
- package/src/Anchor/index.zh-CN.md +1 -1
- package/src/Anchor/interface.ts +1 -1
- package/src/Input/input.tsx +3 -0
- package/src/Input/style/index.less +2 -2
- package/src/Select/option.tsx +2 -1
- package/src/Select/options.tsx +6 -0
- package/src/Selector/selector.tsx +16 -1
- package/src/Spin/style/index.less +11 -6
- package/src/Table/theader/filter.tsx +1 -1
- package/src/Tag/tag.tsx +14 -1
- package/src/Tree/interface.ts +3 -1
- package/src/Tree/tree-node.tsx +5 -0
- package/src/Tree/tree.tsx +8 -0
- package/src/Trigger/interface.ts +2 -1
- package/src/version.ts +1 -1
package/package.json
CHANGED
package/src/Alert/alert.tsx
CHANGED
package/src/Anchor/anchor.tsx
CHANGED
|
@@ -25,6 +25,20 @@ export const AnchorContext = createContext<AnchorContextType>(
|
|
|
25
25
|
{} as AnchorContextType,
|
|
26
26
|
);
|
|
27
27
|
|
|
28
|
+
const NAVIGATION_LOCK_TIMEOUT = 5000;
|
|
29
|
+
const NAVIGATION_SETTLE_DELAY = 100;
|
|
30
|
+
const TARGET_POSITION_TOLERANCE = 2;
|
|
31
|
+
const SCROLL_KEYS = new Set([
|
|
32
|
+
'ArrowUp',
|
|
33
|
+
'ArrowDown',
|
|
34
|
+
'PageUp',
|
|
35
|
+
'PageDown',
|
|
36
|
+
'Home',
|
|
37
|
+
'End',
|
|
38
|
+
' ',
|
|
39
|
+
'Spacebar',
|
|
40
|
+
]);
|
|
41
|
+
|
|
28
42
|
const Anchor = forwardRef<HTMLDivElement, AnchorProps>((baseprops, ref) => {
|
|
29
43
|
const { anchor } = useContext(GlobalContext);
|
|
30
44
|
const props = mergeContextToProps(baseprops, anchor);
|
|
@@ -57,11 +71,89 @@ const Anchor = forwardRef<HTMLDivElement, AnchorProps>((baseprops, ref) => {
|
|
|
57
71
|
const [anchorList, setAnchorList] = useState<Array<AnchorItemType>>([]);
|
|
58
72
|
|
|
59
73
|
const containerRef = useRef<HTMLElement | Window | null>(null);
|
|
74
|
+
const anchorRootRef = useRef<HTMLDivElement | null>(null);
|
|
60
75
|
const activeKeyRef = useRef(mergedActiveKey);
|
|
76
|
+
const handleScrollRef = useRef<() => void>(() => {});
|
|
77
|
+
const pendingTargetKeyRef = useRef<string | undefined>(undefined);
|
|
78
|
+
const navigationTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(
|
|
79
|
+
null,
|
|
80
|
+
);
|
|
81
|
+
const navigationSettleTimeoutRef = useRef<
|
|
82
|
+
ReturnType<typeof setTimeout> | null
|
|
83
|
+
>(null);
|
|
84
|
+
|
|
61
85
|
useEffect(() => {
|
|
62
86
|
activeKeyRef.current = mergedActiveKey;
|
|
63
87
|
}, [mergedActiveKey]);
|
|
64
88
|
|
|
89
|
+
const setAnchorRootRef = useCallback(
|
|
90
|
+
(node: HTMLDivElement | null) => {
|
|
91
|
+
anchorRootRef.current = node;
|
|
92
|
+
if (typeof ref === 'function') {
|
|
93
|
+
ref(node);
|
|
94
|
+
} else if (ref) {
|
|
95
|
+
ref.current = node;
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
[ref],
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const clearNavigationSettleTimer = useCallback(() => {
|
|
102
|
+
if (navigationSettleTimeoutRef.current !== null) {
|
|
103
|
+
clearTimeout(navigationSettleTimeoutRef.current);
|
|
104
|
+
navigationSettleTimeoutRef.current = null;
|
|
105
|
+
}
|
|
106
|
+
}, []);
|
|
107
|
+
|
|
108
|
+
const clearNavigationLock = useCallback(() => {
|
|
109
|
+
pendingTargetKeyRef.current = undefined;
|
|
110
|
+
clearNavigationSettleTimer();
|
|
111
|
+
if (navigationTimeoutRef.current !== null) {
|
|
112
|
+
clearTimeout(navigationTimeoutRef.current);
|
|
113
|
+
navigationTimeoutRef.current = null;
|
|
114
|
+
}
|
|
115
|
+
}, [clearNavigationSettleTimer]);
|
|
116
|
+
|
|
117
|
+
const scheduleNavigationUnlock = useCallback(
|
|
118
|
+
(key: string) => {
|
|
119
|
+
clearNavigationSettleTimer();
|
|
120
|
+
navigationSettleTimeoutRef.current = setTimeout(() => {
|
|
121
|
+
if (pendingTargetKeyRef.current === key) {
|
|
122
|
+
clearNavigationLock();
|
|
123
|
+
}
|
|
124
|
+
}, NAVIGATION_SETTLE_DELAY);
|
|
125
|
+
},
|
|
126
|
+
[clearNavigationLock, clearNavigationSettleTimer],
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const startNavigationLock = useCallback(
|
|
130
|
+
(key: string) => {
|
|
131
|
+
clearNavigationLock();
|
|
132
|
+
pendingTargetKeyRef.current = key;
|
|
133
|
+
navigationTimeoutRef.current = setTimeout(() => {
|
|
134
|
+
if (pendingTargetKeyRef.current === key) {
|
|
135
|
+
clearNavigationLock();
|
|
136
|
+
handleScrollRef.current();
|
|
137
|
+
}
|
|
138
|
+
}, NAVIGATION_LOCK_TIMEOUT);
|
|
139
|
+
},
|
|
140
|
+
[clearNavigationLock],
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
useEffect(() => clearNavigationLock, [clearNavigationLock]);
|
|
144
|
+
|
|
145
|
+
const commitActiveKey = useCallback(
|
|
146
|
+
(key: string, forceNotify = false) => {
|
|
147
|
+
const changed = activeKeyRef.current !== key;
|
|
148
|
+
activeKeyRef.current = key;
|
|
149
|
+
setMergedActiveKey(key);
|
|
150
|
+
if (changed || forceNotify) {
|
|
151
|
+
onChange?.(key);
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
[onChange],
|
|
155
|
+
);
|
|
156
|
+
|
|
65
157
|
// Auto-generate anchor list from DOM
|
|
66
158
|
const generateAnchorList = useCallback(() => {
|
|
67
159
|
if (!auto || !name) return;
|
|
@@ -107,11 +199,51 @@ const Anchor = forwardRef<HTMLDivElement, AnchorProps>((baseprops, ref) => {
|
|
|
107
199
|
return currentScroll + (target.getBoundingClientRect().top - containerTop);
|
|
108
200
|
}, []);
|
|
109
201
|
|
|
202
|
+
const hasReachedTarget = useCallback(
|
|
203
|
+
(key: string) => {
|
|
204
|
+
const container = containerRef.current;
|
|
205
|
+
const target = document.getElementById(key);
|
|
206
|
+
if (!container || !target) return false;
|
|
207
|
+
|
|
208
|
+
const currentScroll =
|
|
209
|
+
container === window
|
|
210
|
+
? window.pageYOffset || document.documentElement.scrollTop
|
|
211
|
+
: (container as HTMLElement).scrollTop;
|
|
212
|
+
const maxScroll =
|
|
213
|
+
container === window
|
|
214
|
+
? Math.max(
|
|
215
|
+
document.documentElement.scrollHeight,
|
|
216
|
+
document.body?.scrollHeight || 0,
|
|
217
|
+
) - window.innerHeight
|
|
218
|
+
: (container as HTMLElement).scrollHeight -
|
|
219
|
+
(container as HTMLElement).clientHeight;
|
|
220
|
+
const targetScroll = Math.min(
|
|
221
|
+
Math.max(getTargetOffsetTop(target) - offsetTop, 0),
|
|
222
|
+
Math.max(maxScroll, 0),
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
return (
|
|
226
|
+
Math.abs(currentScroll - targetScroll) <= TARGET_POSITION_TOLERANCE
|
|
227
|
+
);
|
|
228
|
+
},
|
|
229
|
+
[getTargetOffsetTop, offsetTop],
|
|
230
|
+
);
|
|
231
|
+
|
|
110
232
|
// Handle scroll to update active key
|
|
111
233
|
const handleScroll = useCallback(() => {
|
|
112
234
|
const container = containerRef.current;
|
|
113
235
|
if (!container) return;
|
|
114
236
|
|
|
237
|
+
const pendingTargetKey = pendingTargetKeyRef.current;
|
|
238
|
+
if (pendingTargetKey) {
|
|
239
|
+
if (hasReachedTarget(pendingTargetKey)) {
|
|
240
|
+
scheduleNavigationUnlock(pendingTargetKey);
|
|
241
|
+
} else {
|
|
242
|
+
clearNavigationSettleTimer();
|
|
243
|
+
}
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
115
247
|
const scrollTop =
|
|
116
248
|
container === window
|
|
117
249
|
? window.pageYOffset || document.documentElement.scrollTop
|
|
@@ -145,11 +277,25 @@ const Anchor = forwardRef<HTMLDivElement, AnchorProps>((baseprops, ref) => {
|
|
|
145
277
|
nextActiveKey = first?.key;
|
|
146
278
|
}
|
|
147
279
|
|
|
148
|
-
if (nextActiveKey
|
|
149
|
-
|
|
150
|
-
onChange?.(nextActiveKey);
|
|
280
|
+
if (nextActiveKey) {
|
|
281
|
+
commitActiveKey(nextActiveKey);
|
|
151
282
|
}
|
|
152
|
-
}, [
|
|
283
|
+
}, [
|
|
284
|
+
auto,
|
|
285
|
+
anchorList,
|
|
286
|
+
items,
|
|
287
|
+
offsetTop,
|
|
288
|
+
getTargetOffsetTop,
|
|
289
|
+
hasReachedTarget,
|
|
290
|
+
scheduleNavigationUnlock,
|
|
291
|
+
clearNavigationSettleTimer,
|
|
292
|
+
clearNavigationLock,
|
|
293
|
+
commitActiveKey,
|
|
294
|
+
]);
|
|
295
|
+
|
|
296
|
+
useEffect(() => {
|
|
297
|
+
handleScrollRef.current = handleScroll;
|
|
298
|
+
}, [handleScroll]);
|
|
153
299
|
|
|
154
300
|
useEffect(() => {
|
|
155
301
|
// Resolve in a passive effect: parent-owned refs passed via `getContainer`
|
|
@@ -161,31 +307,83 @@ const Anchor = forwardRef<HTMLDivElement, AnchorProps>((baseprops, ref) => {
|
|
|
161
307
|
// rAF throttle so the active key tracks scroll live.
|
|
162
308
|
let rafId: ReturnType<typeof requestAnimationFrame> | null = null;
|
|
163
309
|
const onScroll = () => {
|
|
310
|
+
if (pendingTargetKeyRef.current) {
|
|
311
|
+
clearNavigationSettleTimer();
|
|
312
|
+
}
|
|
164
313
|
if (rafId !== null) return;
|
|
165
314
|
rafId = requestAnimationFrame(() => {
|
|
166
315
|
rafId = null;
|
|
167
316
|
handleScroll();
|
|
168
317
|
});
|
|
169
318
|
};
|
|
319
|
+
const onScrollEnd = () => {
|
|
320
|
+
const pendingTargetKey = pendingTargetKeyRef.current;
|
|
321
|
+
if (pendingTargetKey && hasReachedTarget(pendingTargetKey)) {
|
|
322
|
+
scheduleNavigationUnlock(pendingTargetKey);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
const onUserInterrupt = (event: Event) => {
|
|
326
|
+
if (event.type === 'pointerdown' && event.target instanceof Element) {
|
|
327
|
+
const item = event.target.closest(
|
|
328
|
+
`.${CSS.escape(`${prefixCls}-item`)}`,
|
|
329
|
+
);
|
|
330
|
+
const owner = item?.closest(`.${CSS.escape(prefixCls)}`);
|
|
331
|
+
if (owner === anchorRootRef.current) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (
|
|
336
|
+
event.type === 'keydown' &&
|
|
337
|
+
!SCROLL_KEYS.has((event as KeyboardEvent).key)
|
|
338
|
+
) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
clearNavigationLock();
|
|
342
|
+
};
|
|
343
|
+
|
|
170
344
|
container.addEventListener('scroll', onScroll as EventListener);
|
|
345
|
+
container.addEventListener('scrollend', onScrollEnd as EventListener);
|
|
346
|
+
container.addEventListener('wheel', onUserInterrupt as EventListener);
|
|
347
|
+
container.addEventListener('touchstart', onUserInterrupt as EventListener);
|
|
348
|
+
document.addEventListener('pointerdown', onUserInterrupt as EventListener);
|
|
349
|
+
container.addEventListener('keydown', onUserInterrupt as EventListener);
|
|
171
350
|
handleScroll();
|
|
172
351
|
|
|
173
352
|
return () => {
|
|
174
353
|
container.removeEventListener('scroll', onScroll as EventListener);
|
|
354
|
+
container.removeEventListener('scrollend', onScrollEnd as EventListener);
|
|
355
|
+
container.removeEventListener('wheel', onUserInterrupt as EventListener);
|
|
356
|
+
container.removeEventListener(
|
|
357
|
+
'touchstart',
|
|
358
|
+
onUserInterrupt as EventListener,
|
|
359
|
+
);
|
|
360
|
+
document.removeEventListener(
|
|
361
|
+
'pointerdown',
|
|
362
|
+
onUserInterrupt as EventListener,
|
|
363
|
+
);
|
|
364
|
+
container.removeEventListener('keydown', onUserInterrupt as EventListener);
|
|
175
365
|
if (rafId !== null) {
|
|
176
366
|
cancelAnimationFrame(rafId);
|
|
177
367
|
}
|
|
178
368
|
};
|
|
179
|
-
}, [
|
|
369
|
+
}, [
|
|
370
|
+
getContainer,
|
|
371
|
+
handleScroll,
|
|
372
|
+
hasReachedTarget,
|
|
373
|
+
scheduleNavigationUnlock,
|
|
374
|
+
clearNavigationSettleTimer,
|
|
375
|
+
clearNavigationLock,
|
|
376
|
+
prefixCls,
|
|
377
|
+
]);
|
|
180
378
|
|
|
181
379
|
// Scroll to target when activeKey changes
|
|
182
380
|
const scrollToAnchor = useCallback(
|
|
183
381
|
(key: string) => {
|
|
184
382
|
const target = document.getElementById(key);
|
|
185
|
-
if (!target) return;
|
|
383
|
+
if (!target) return false;
|
|
186
384
|
|
|
187
385
|
const container = containerRef.current;
|
|
188
|
-
if (!container) return;
|
|
386
|
+
if (!container) return false;
|
|
189
387
|
|
|
190
388
|
const targetTop = getTargetOffsetTop(target) - offsetTop;
|
|
191
389
|
|
|
@@ -197,6 +395,7 @@ const Anchor = forwardRef<HTMLDivElement, AnchorProps>((baseprops, ref) => {
|
|
|
197
395
|
behavior: 'smooth',
|
|
198
396
|
});
|
|
199
397
|
}
|
|
398
|
+
return true;
|
|
200
399
|
},
|
|
201
400
|
[offsetTop, getTargetOffsetTop],
|
|
202
401
|
);
|
|
@@ -210,11 +409,23 @@ const Anchor = forwardRef<HTMLDivElement, AnchorProps>((baseprops, ref) => {
|
|
|
210
409
|
|
|
211
410
|
const handleItemClick = useCallback(
|
|
212
411
|
(key: string) => {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
412
|
+
startNavigationLock(key);
|
|
413
|
+
commitActiveKey(key, true);
|
|
414
|
+
|
|
415
|
+
if (!scrollToAnchor(key)) {
|
|
416
|
+
clearNavigationLock();
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Handles instant scrolling and targets that are already in position.
|
|
421
|
+
handleScroll();
|
|
422
|
+
}, [
|
|
423
|
+
startNavigationLock,
|
|
424
|
+
commitActiveKey,
|
|
425
|
+
scrollToAnchor,
|
|
426
|
+
clearNavigationLock,
|
|
427
|
+
handleScroll,
|
|
428
|
+
],
|
|
218
429
|
);
|
|
219
430
|
|
|
220
431
|
const cls = clsx(
|
|
@@ -250,7 +461,7 @@ const Anchor = forwardRef<HTMLDivElement, AnchorProps>((baseprops, ref) => {
|
|
|
250
461
|
};
|
|
251
462
|
|
|
252
463
|
return (
|
|
253
|
-
<div {...rest} className={cls} style={style} ref={
|
|
464
|
+
<div {...rest} className={cls} style={style} ref={setAnchorRootRef}>
|
|
254
465
|
{renderNavArrow()}
|
|
255
466
|
<AnchorContext.Provider value={contextValue}>
|
|
256
467
|
<div className={`${prefixCls}-content-wrapper`}>
|
|
@@ -35,7 +35,7 @@ Anchor component for linking to specific sections within a page.
|
|
|
35
35
|
| auto | `boolean` | Whether to auto-generate anchors | `false` |
|
|
36
36
|
| name | `string` | Anchor group name (for auto-generation) | - |
|
|
37
37
|
| defaultActiveKey | `string` | Default active anchor key | - |
|
|
38
|
-
| activeKey | `string` | Active anchor key (controlled) | - |
|
|
38
|
+
| activeKey | `string` | Active anchor key (controlled; update it in `onChange`) | - |
|
|
39
39
|
| affix | `boolean` | Whether to fix position | `true` |
|
|
40
40
|
| direction | `'vertical' \| 'horizontal'` | Navigation direction | `'vertical'` |
|
|
41
41
|
| offsetTop | `number` | Offset top to trigger anchor change | `0` |
|
|
@@ -35,7 +35,7 @@ toc: 'content'
|
|
|
35
35
|
| auto | `boolean` | 是否自动生成锚点 | `false` |
|
|
36
36
|
| name | `string` | 锚点组名称(用于自动生成) | - |
|
|
37
37
|
| defaultActiveKey | `string` | 锚点默认位置 | - |
|
|
38
|
-
| activeKey | `string` |
|
|
38
|
+
| activeKey | `string` | 锚点位置(受控,需在 `onChange` 中同步回写) | - |
|
|
39
39
|
| affix | `boolean` | 是否固定 | `true` |
|
|
40
40
|
| direction | `'vertical' \| 'horizontal'` | 设置导航方向 | `'vertical'` |
|
|
41
41
|
| offsetTop | `number` | 距离顶部距离为多少时,触发锚点改变 | `0` |
|
package/src/Anchor/interface.ts
CHANGED
package/src/Input/input.tsx
CHANGED
|
@@ -104,6 +104,9 @@ const Input = forwardRef<HTMLInputElement, InputProps>((baseprops, ref) => {
|
|
|
104
104
|
<span
|
|
105
105
|
className={clsx(`${prefixCls}-clear`, classNames?.clear)}
|
|
106
106
|
style={styles?.clear}
|
|
107
|
+
role="button"
|
|
108
|
+
aria-label="clear"
|
|
109
|
+
tabIndex={0}
|
|
107
110
|
onClick={onClear}
|
|
108
111
|
onKeyDown={(event: React.KeyboardEvent<HTMLSpanElement>) => {
|
|
109
112
|
if (event.key === 'Enter') {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
width: 100%;
|
|
9
9
|
padding: var(--yee-input-padding, 2px 8px);
|
|
10
10
|
font-size: var(--yee-input-font-size);
|
|
11
|
-
line-height: var(--yee-input-line-height);
|
|
11
|
+
// line-height: var(--yee-input-line-height);
|
|
12
12
|
background-color: var(--yee-input-content-bg-color);
|
|
13
13
|
border: var(--yee-input-border-width) solid var(--yee-input-border-color);
|
|
14
14
|
border-radius: var(--yee-input-border-radius, 4px);
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
&-inner {
|
|
50
50
|
width: 100%;
|
|
51
51
|
font-family: var(--yee-font-family);
|
|
52
|
-
line-height: var(--yee-input-line-height);
|
|
52
|
+
// line-height: var(--yee-input-line-height);
|
|
53
53
|
background-color: inherit;
|
|
54
54
|
border: none;
|
|
55
55
|
outline: none;
|
package/src/Select/option.tsx
CHANGED
|
@@ -43,7 +43,8 @@ const Option = (props: OptionProps) => {
|
|
|
43
43
|
[`${prefixCls}-option-focused`]: focused,
|
|
44
44
|
[`${prefixCls}-option-disabled`]: disabled,
|
|
45
45
|
})}
|
|
46
|
-
aria-
|
|
46
|
+
aria-selected={selected}
|
|
47
|
+
aria-disabled={disabled || undefined}
|
|
47
48
|
onClick={handleClick}
|
|
48
49
|
onKeyDown={(e) => {
|
|
49
50
|
if (e.key === 'Enter') {
|
package/src/Select/options.tsx
CHANGED
|
@@ -166,6 +166,8 @@ const Options = forwardRef<HTMLDivElement, OptionsProps>(
|
|
|
166
166
|
)}
|
|
167
167
|
style={popupStyle}
|
|
168
168
|
ref={rootRef}
|
|
169
|
+
role="listbox"
|
|
170
|
+
aria-multiselectable={multiple || undefined}
|
|
169
171
|
tabIndex={-1}
|
|
170
172
|
>
|
|
171
173
|
<OptionsCtx.Provider value={ctxValue}>
|
|
@@ -220,6 +222,8 @@ const Options = forwardRef<HTMLDivElement, OptionsProps>(
|
|
|
220
222
|
)}
|
|
221
223
|
style={popupStyle}
|
|
222
224
|
ref={rootRef}
|
|
225
|
+
role="listbox"
|
|
226
|
+
aria-multiselectable={multiple || undefined}
|
|
223
227
|
tabIndex={-1}
|
|
224
228
|
>
|
|
225
229
|
<OptionsCtx.Provider value={ctxValue}>
|
|
@@ -268,6 +272,8 @@ const Options = forwardRef<HTMLDivElement, OptionsProps>(
|
|
|
268
272
|
: undefined),
|
|
269
273
|
}}
|
|
270
274
|
ref={rootRef}
|
|
275
|
+
role="listbox"
|
|
276
|
+
aria-multiselectable={multiple || undefined}
|
|
271
277
|
tabIndex={-1}
|
|
272
278
|
>
|
|
273
279
|
{isEmpty ? (
|
|
@@ -246,7 +246,18 @@ const Selector = React.forwardRef(
|
|
|
246
246
|
return null;
|
|
247
247
|
}
|
|
248
248
|
return (
|
|
249
|
-
<span
|
|
249
|
+
<span
|
|
250
|
+
className={`${prefixCls}-clear`}
|
|
251
|
+
role="button"
|
|
252
|
+
aria-label="clear"
|
|
253
|
+
tabIndex={0}
|
|
254
|
+
onClick={handleClear}
|
|
255
|
+
onKeyDown={(e) => {
|
|
256
|
+
if (e.key === 'Enter') {
|
|
257
|
+
handleClear(e as unknown as React.MouseEvent<HTMLSpanElement>);
|
|
258
|
+
}
|
|
259
|
+
}}
|
|
260
|
+
>
|
|
250
261
|
<X size={12} strokeWidth={1} />
|
|
251
262
|
</span>
|
|
252
263
|
);
|
|
@@ -258,6 +269,10 @@ const Selector = React.forwardRef(
|
|
|
258
269
|
tabIndex={disabled || searchable ? -1 : 0}
|
|
259
270
|
className={cls}
|
|
260
271
|
style={style}
|
|
272
|
+
role="combobox"
|
|
273
|
+
aria-expanded={open || false}
|
|
274
|
+
aria-haspopup="listbox"
|
|
275
|
+
aria-disabled={disabled || undefined}
|
|
261
276
|
onKeyDown={(event) => {
|
|
262
277
|
if (disabled) return;
|
|
263
278
|
// For non-searchable single select, handle Enter to open dropdown
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
&-ring {
|
|
41
|
-
|
|
41
|
+
@{pls}-ring {
|
|
42
42
|
box-sizing: border-box;
|
|
43
43
|
display: block;
|
|
44
44
|
border-style: solid;
|
|
@@ -53,13 +53,13 @@
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
&-spokes {
|
|
56
|
-
|
|
56
|
+
@{pls}-spokes {
|
|
57
57
|
position: relative;
|
|
58
58
|
width: 100%;
|
|
59
59
|
height: 100%;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
@{pls}-spokes-line {
|
|
63
63
|
position: absolute;
|
|
64
64
|
top: 0;
|
|
65
65
|
left: 50%;
|
|
@@ -101,9 +101,14 @@
|
|
|
101
101
|
|
|
102
102
|
&-blur {
|
|
103
103
|
position: absolute;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
width: 100%;
|
|
108
|
+
height: 100%;
|
|
109
|
+
// top: 50%;
|
|
110
|
+
// left: 50%;
|
|
111
|
+
// transform: translate(-50%, -50%);
|
|
107
112
|
background-color: var(--yee-color-bg-mask-light, rgba(255, 255, 255, 40%));
|
|
108
113
|
}
|
|
109
114
|
|
|
@@ -175,7 +175,7 @@ const HeaderFilter = React.memo((props: any) => {
|
|
|
175
175
|
<Search size={14} strokeWidth={1.5} />
|
|
176
176
|
)
|
|
177
177
|
}
|
|
178
|
-
variant={selectNodes.length ? 'filled' : undefined}
|
|
178
|
+
variant={selectNodes.length || searchValue ? 'filled' : undefined}
|
|
179
179
|
type="text"
|
|
180
180
|
size="small"
|
|
181
181
|
/>
|
package/src/Tag/tag.tsx
CHANGED
|
@@ -56,6 +56,7 @@ const Tag = forwardRef(
|
|
|
56
56
|
style={styles?.close}
|
|
57
57
|
type="text"
|
|
58
58
|
size="small"
|
|
59
|
+
aria-label="close"
|
|
59
60
|
onClick={onClose}
|
|
60
61
|
>
|
|
61
62
|
{typeof closable === 'boolean' ? (
|
|
@@ -69,7 +70,19 @@ const Tag = forwardRef(
|
|
|
69
70
|
const closeNode = renderClose();
|
|
70
71
|
|
|
71
72
|
return (
|
|
72
|
-
<div
|
|
73
|
+
<div
|
|
74
|
+
{...rest}
|
|
75
|
+
className={cls}
|
|
76
|
+
onClick={handleClick}
|
|
77
|
+
ref={ref}
|
|
78
|
+
{...(checkable
|
|
79
|
+
? {
|
|
80
|
+
role: 'checkbox',
|
|
81
|
+
'aria-checked': checked || false,
|
|
82
|
+
tabIndex: 0,
|
|
83
|
+
}
|
|
84
|
+
: undefined)}
|
|
85
|
+
>
|
|
73
86
|
{icon && (
|
|
74
87
|
<span
|
|
75
88
|
className={clsx(`${prefixCls}-icon`, classNames?.icon)}
|
package/src/Tree/interface.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { DataAttributeProps } from '../utils/types';
|
|
2
|
+
|
|
1
3
|
export type SemanticType = '';
|
|
2
4
|
|
|
3
5
|
export type DragPosition = 'before' | 'after' | 'inside';
|
|
@@ -73,7 +75,7 @@ export interface TreeNodeProps<T> {
|
|
|
73
75
|
style?: React.CSSProperties;
|
|
74
76
|
}
|
|
75
77
|
|
|
76
|
-
export interface TreeProps<T> {
|
|
78
|
+
export interface TreeProps<T> extends DataAttributeProps {
|
|
77
79
|
/**
|
|
78
80
|
* Custom class name prefix
|
|
79
81
|
*/
|
package/src/Tree/tree-node.tsx
CHANGED
|
@@ -170,6 +170,11 @@ const Node = <T extends Record<string, unknown> = any>(
|
|
|
170
170
|
[`${prefixCls}-node-drag-over-inside`]: dropPosition === 'inside',
|
|
171
171
|
})}
|
|
172
172
|
style={nodeStyle}
|
|
173
|
+
role="treeitem"
|
|
174
|
+
aria-expanded={isLeaf ? undefined : expanded}
|
|
175
|
+
aria-selected={selected}
|
|
176
|
+
aria-level={depth + 1}
|
|
177
|
+
aria-disabled={disabled || undefined}
|
|
173
178
|
{...dragProps}
|
|
174
179
|
>
|
|
175
180
|
{renderEmptyNodes(depth)}
|
package/src/Tree/tree.tsx
CHANGED
|
@@ -13,6 +13,7 @@ import useEvent from '../hooks/useEvent';
|
|
|
13
13
|
import useMergedState from '../hooks/useMergedState';
|
|
14
14
|
import useVirtualList from '../hooks/useVirtualList';
|
|
15
15
|
import mergeContextToProps from '../utils/mergeContextToProps';
|
|
16
|
+
import { pickDataAttrs } from '../utils/types';
|
|
16
17
|
import type { DragPosition, TreeNode, TreeProps } from './interface';
|
|
17
18
|
import TreeNodeComp from './tree-node';
|
|
18
19
|
import { getCheckedKeys, tree2array } from './utils/tree-tools';
|
|
@@ -205,8 +206,11 @@ const Tree = <T extends Record<string, unknown> = any>(
|
|
|
205
206
|
virtual = false,
|
|
206
207
|
height,
|
|
207
208
|
itemHeight = 28,
|
|
209
|
+
...rest
|
|
208
210
|
} = props;
|
|
209
211
|
|
|
212
|
+
const dataAttrs = pickDataAttrs(rest as Record<string, unknown>);
|
|
213
|
+
|
|
210
214
|
// ======================== Data ========================
|
|
211
215
|
const [flatItems, itemMap] = useMemo(
|
|
212
216
|
() => tree2array(dataSource ?? [], fieldNames),
|
|
@@ -606,7 +610,9 @@ const Tree = <T extends Record<string, unknown> = any>(
|
|
|
606
610
|
<div
|
|
607
611
|
className={clsx(prefixCls, className)}
|
|
608
612
|
style={style}
|
|
613
|
+
role="tree"
|
|
609
614
|
onDragEnd={handleDragEnd}
|
|
615
|
+
{...dataAttrs}
|
|
610
616
|
>
|
|
611
617
|
<TreeContext.Provider value={contextValue}>
|
|
612
618
|
<div
|
|
@@ -675,7 +681,9 @@ const Tree = <T extends Record<string, unknown> = any>(
|
|
|
675
681
|
<div
|
|
676
682
|
className={clsx(prefixCls, className)}
|
|
677
683
|
style={style}
|
|
684
|
+
role="tree"
|
|
678
685
|
onDragEnd={handleDragEnd}
|
|
686
|
+
{...dataAttrs}
|
|
679
687
|
>
|
|
680
688
|
<TreeContext.Provider value={contextValue}>
|
|
681
689
|
<AnimatePresence initial={false}>
|
package/src/Trigger/interface.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TriggerProps as RcTriggerProps } from '@rc-component/trigger';
|
|
2
|
+
import type { DataAttributeProps } from '../utils/types';
|
|
2
3
|
|
|
3
4
|
export type Placement =
|
|
4
5
|
| 'top'
|
|
@@ -31,7 +32,7 @@ export type Point =
|
|
|
31
32
|
| 'cl'
|
|
32
33
|
| 'cr';
|
|
33
34
|
|
|
34
|
-
export interface TriggerProps extends Omit<RcTriggerProps, 'children'
|
|
35
|
+
export interface TriggerProps extends Omit<RcTriggerProps, 'children'>, DataAttributeProps {
|
|
35
36
|
/**
|
|
36
37
|
* Custom class name prefix
|
|
37
38
|
*/
|