@rainbow-oh/yee-c 0.8.0 → 0.8.2
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/LICENSE +1 -1
- package/README.md +40 -25
- package/dist/cjs/Card/card.js +7 -3
- package/dist/cjs/Carousel/carousel-item.js +7 -2
- package/dist/cjs/Carousel/carousel.js +31 -4
- package/dist/cjs/Cascader/cascader.js +38 -30
- package/dist/cjs/Cascader/column.js +17 -9
- package/dist/cjs/Cascader/node.js +16 -4
- package/dist/cjs/Cascader/search-list.js +31 -14
- package/dist/cjs/Cascader/utils/index.js +1 -5
- package/dist/cjs/Checkbox/checkbox-group.js +23 -14
- package/dist/cjs/Checkbox/checkbox.js +6 -3
- package/dist/cjs/Collapse/panel.js +10 -1
- package/dist/cjs/Dialog/dialog.js +22 -7
- package/dist/cjs/Dialog/interface.d.ts +1 -1
- package/dist/cjs/Dialog/style/index.less +2 -1
- package/dist/cjs/Drawer/drawer.js +22 -5
- package/dist/cjs/Form/Group.js +1 -1
- package/dist/cjs/Form/demo/tooltip.js +1 -3
- package/dist/cjs/List/hooks/useListKeyboard.js +3 -1
- package/dist/cjs/Menu/menu-item.js +14 -5
- package/dist/cjs/Menu/menu.js +26 -2
- package/dist/cjs/Pagination/items.js +60 -27
- package/dist/cjs/Pagination/pagination.js +33 -11
- package/dist/cjs/PickerPanel/panels/DateTimePanel/index.d.ts +1 -1
- package/dist/cjs/PickerPanel/panels/MonthPanel/MonthHeader.js +7 -1
- package/dist/cjs/Radio/radio-group.js +6 -5
- package/dist/cjs/Radio/radio.js +39 -29
- package/dist/cjs/Rate/rate.js +6 -1
- package/dist/cjs/Rate/star.js +31 -3
- package/dist/cjs/Segmented/demo/variant.js +15 -1
- package/dist/cjs/Segmented/index.d.ts +1 -1
- package/dist/cjs/Segmented/segmented.js +12 -15
- package/dist/cjs/Select/option.js +8 -1
- package/dist/cjs/Select/options.js +9 -1
- package/dist/cjs/Select/select.js +3 -1
- package/dist/cjs/Steps/step.js +19 -5
- package/dist/cjs/Steps/steps.js +11 -1
- package/dist/cjs/Table/demo/components-override.js +31 -2
- package/dist/cjs/Table/demo/grouping.js +7 -1
- package/dist/cjs/Table/hooks/useColumns.d.ts +3 -3
- package/dist/cjs/Table/hooks/useColumns.js +11 -14
- package/dist/cjs/Table/index.d.ts +1 -1
- package/dist/cjs/Table/style/index.less +2 -4
- package/dist/cjs/Table/tbody/row.js +1 -4
- package/dist/cjs/Table/theader/index.js +12 -4
- package/dist/cjs/Tabs/tab-content.js +3 -1
- package/dist/cjs/Tabs/tab-header/index.js +3 -1
- package/dist/cjs/Tabs/tab-header/tab-header-title.js +3 -1
- package/dist/cjs/Tour/index.d.ts +1 -1
- package/dist/cjs/Tree/style/index.less +1 -5
- package/dist/cjs/Tree/tree.js +38 -35
- package/dist/cjs/hooks/useDelayState.js +3 -2
- package/dist/cjs/hooks/useEvent.js +1 -4
- package/dist/cjs/hooks/useFocusManage.d.ts +1 -1
- package/dist/cjs/hooks/useFocusManage.js +27 -22
- package/dist/cjs/style/size.css +2 -0
- package/dist/cjs/style/themes.css +1 -1
- package/dist/cjs/style/variables.css +3 -1
- package/dist/cjs/utils/focusStack.d.ts +6 -2
- package/dist/cjs/utils/focusStack.js +40 -11
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/Card/card.js +7 -3
- package/dist/esm/Carousel/carousel-item.js +7 -2
- package/dist/esm/Carousel/carousel.js +31 -4
- package/dist/esm/Cascader/cascader.js +3 -1
- package/dist/esm/Cascader/column.js +2 -1
- package/dist/esm/Cascader/node.js +18 -4
- package/dist/esm/Cascader/search-list.js +18 -4
- package/dist/esm/Checkbox/checkbox-group.js +3 -1
- package/dist/esm/Checkbox/checkbox.js +6 -3
- package/dist/esm/Collapse/panel.js +11 -2
- package/dist/esm/Dialog/dialog.js +28 -11
- package/dist/esm/Dialog/interface.d.ts +1 -1
- package/dist/esm/Dialog/style/index.less +2 -1
- package/dist/esm/Drawer/drawer.js +16 -7
- package/dist/esm/Form/Group.js +1 -1
- package/dist/esm/Menu/menu-item.js +16 -5
- package/dist/esm/Menu/menu.js +11 -5
- package/dist/esm/Pagination/items.js +14 -5
- package/dist/esm/Pagination/pagination.js +16 -4
- package/dist/esm/PickerPanel/panels/DateTimePanel/index.d.ts +1 -1
- package/dist/esm/Radio/radio-group.js +5 -4
- package/dist/esm/Radio/radio.js +5 -4
- package/dist/esm/Rate/rate.js +6 -1
- package/dist/esm/Rate/star.js +12 -4
- package/dist/esm/Segmented/index.d.ts +1 -1
- package/dist/esm/Segmented/segmented.js +1 -1
- package/dist/esm/Steps/step.js +12 -6
- package/dist/esm/Steps/steps.js +3 -1
- package/dist/esm/Table/demo/components-override.js +1 -0
- package/dist/esm/Table/hooks/useColumns.d.ts +3 -3
- package/dist/esm/Table/hooks/useColumns.js +13 -16
- package/dist/esm/Table/index.d.ts +1 -1
- package/dist/esm/Table/style/index.less +2 -4
- package/dist/esm/Tabs/tab-content.js +3 -1
- package/dist/esm/Tabs/tab-header/index.js +3 -1
- package/dist/esm/Tabs/tab-header/tab-header-title.js +3 -1
- package/dist/esm/Tour/index.d.ts +1 -1
- package/dist/esm/Tree/style/index.less +1 -5
- package/dist/esm/Tree/tree.js +1 -1
- package/dist/esm/hooks/useDelayState.js +5 -2
- package/dist/esm/hooks/useFocusManage.d.ts +1 -1
- package/dist/esm/hooks/useFocusManage.js +31 -13
- package/dist/esm/style/size.css +2 -0
- package/dist/esm/style/themes.css +1 -1
- package/dist/esm/style/variables.css +3 -1
- package/dist/esm/utils/focusStack.d.ts +6 -2
- package/dist/esm/utils/focusStack.js +37 -14
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/umd/yee-c.min.css +2 -2
- package/dist/umd/yee-c.min.js +1 -1
- package/package.json +10 -6
- package/src/Anchor/anchor.tsx +2 -2
- package/src/Card/card.tsx +5 -1
- package/src/Carousel/carousel-item.tsx +7 -1
- package/src/Carousel/carousel.tsx +29 -3
- package/src/Cascader/cascader.tsx +5 -1
- package/src/Cascader/column.tsx +5 -1
- package/src/Cascader/node.tsx +14 -2
- package/src/Cascader/search-list.tsx +19 -3
- package/src/Cascader/utils/index.ts +3 -6
- package/src/Checkbox/checkbox-group.tsx +6 -1
- package/src/Checkbox/checkbox.tsx +3 -0
- package/src/Collapse/panel.tsx +11 -1
- package/src/Dialog/dialog.tsx +35 -6
- package/src/Dialog/interface.ts +1 -1
- package/src/Dialog/style/index.less +2 -1
- package/src/Drawer/drawer.tsx +18 -3
- package/src/Form/Group.tsx +2 -4
- package/src/Form/demo/tooltip.tsx +2 -11
- package/src/Form/utils/validate.ts +1 -4
- package/src/List/hooks/useListKeyboard.ts +3 -3
- package/src/List/list.tsx +2 -1
- package/src/Menu/menu-item.tsx +12 -3
- package/src/Menu/menu.tsx +22 -5
- package/src/Pagination/items.tsx +21 -4
- package/src/Pagination/pagination.tsx +24 -4
- package/src/PickerPanel/panels/DatePanel/DateBody.tsx +1 -1
- package/src/PickerPanel/panels/DateTimePanel/index.tsx +1 -1
- package/src/PickerPanel/panels/MonthPanel/MonthHeader.tsx +7 -2
- package/src/PickerPanel/panels/PanelBody.tsx +1 -1
- package/src/PickerPanel/panels/QuarterPanel/QuarterHeader.tsx +1 -1
- package/src/PickerPanel/panels/RangePanel/index.tsx +1 -1
- package/src/PickerPanel/panels/TimePanel/TimeBody.tsx +1 -1
- package/src/PickerPanel/panels/YearPanel/YearHeader.tsx +1 -1
- package/src/PickerPanel/utils/pickerUtils.ts +2 -1
- package/src/Radio/radio-group.tsx +2 -1
- package/src/Radio/radio.tsx +7 -2
- package/src/RangePicker/range-picker-mobile.tsx +1 -3
- package/src/Rate/rate.tsx +5 -0
- package/src/Rate/star.tsx +20 -4
- package/src/Segmented/demo/variant.tsx +10 -2
- package/src/Segmented/index.ts +2 -2
- package/src/Segmented/segmented.tsx +4 -11
- package/src/Select/interface.ts +0 -1
- package/src/Select/option.tsx +8 -2
- package/src/Select/options.tsx +11 -4
- package/src/Select/select.tsx +4 -4
- package/src/Steps/step.tsx +23 -5
- package/src/Steps/steps.tsx +8 -1
- package/src/Table/demo/components-override.tsx +34 -7
- package/src/Table/demo/grouping.tsx +8 -4
- package/src/Table/hooks/useColumns.ts +14 -18
- package/src/Table/index.ts +3 -3
- package/src/Table/style/index.less +2 -4
- package/src/Table/table.tsx +2 -4
- package/src/Table/tbody/row.tsx +1 -3
- package/src/Table/theader/index.tsx +9 -10
- package/src/Tabs/tab-content.tsx +2 -0
- package/src/Tabs/tab-header/index.tsx +2 -0
- package/src/Tabs/tab-header/tab-header-title.tsx +3 -1
- package/src/Tour/demo/placement.tsx +2 -1
- package/src/Tour/index.ts +1 -1
- package/src/Tree/style/index.less +1 -5
- package/src/Tree/tree.tsx +16 -11
- package/src/Tree/utils/tree-tools.ts +4 -1
- package/src/hooks/useDelayState.ts +4 -2
- package/src/hooks/useEvent.ts +1 -3
- package/src/hooks/useFocusManage.ts +33 -17
- package/src/locale/context.tsx +5 -1
- package/src/locale/interface.ts +3 -1
- package/src/style/size.css +2 -0
- package/src/utils/debounce.ts +1 -3
- package/src/utils/focusStack.ts +55 -12
- package/src/version.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rainbow-oh/yee-c",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "yee basic components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
"design-system",
|
|
11
11
|
"yee"
|
|
12
12
|
],
|
|
13
|
-
"homepage": "https://github.com/
|
|
13
|
+
"homepage": "https://github.com/insureMO/oh-yee/tree/main/packages/yee-c#readme",
|
|
14
14
|
"bugs": {
|
|
15
|
-
"url": "https://github.com/
|
|
15
|
+
"url": "https://github.com/insureMO/oh-yee/issues"
|
|
16
16
|
},
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
19
|
-
"url": "https://github.com/
|
|
19
|
+
"url": "https://github.com/insureMO/oh-yee.git",
|
|
20
20
|
"directory": "packages/yee-c"
|
|
21
21
|
},
|
|
22
22
|
"license": "MIT",
|
|
@@ -94,6 +94,7 @@
|
|
|
94
94
|
"devDependencies": {
|
|
95
95
|
"@commitlint/cli": "^17.1.2",
|
|
96
96
|
"@commitlint/config-conventional": "^17.1.0",
|
|
97
|
+
"@testing-library/react": "16.3.2",
|
|
97
98
|
"@types/react": "^19.2.7",
|
|
98
99
|
"@types/react-dom": "^19.2.3",
|
|
99
100
|
"@types/react-syntax-highlighter": "^15.5.13",
|
|
@@ -102,6 +103,7 @@
|
|
|
102
103
|
"eslint": "^8.23.0",
|
|
103
104
|
"father": "^4.1.0",
|
|
104
105
|
"husky": "^8.0.1",
|
|
106
|
+
"jsdom": "25.0.1",
|
|
105
107
|
"lint-staged": "^13.0.3",
|
|
106
108
|
"prettier": "^3.6.2",
|
|
107
109
|
"prettier-plugin-organize-imports": "^4.3.0",
|
|
@@ -109,7 +111,8 @@
|
|
|
109
111
|
"react": "^19.2.0",
|
|
110
112
|
"react-dom": "^19.2.0",
|
|
111
113
|
"stylelint": "^14.16.1",
|
|
112
|
-
"stylelint-order": "^6.0.4"
|
|
114
|
+
"stylelint-order": "^6.0.4",
|
|
115
|
+
"vitest": "3.2.6"
|
|
113
116
|
},
|
|
114
117
|
"peerDependencies": {
|
|
115
118
|
"react": ">=18.0.0",
|
|
@@ -120,7 +123,7 @@
|
|
|
120
123
|
"registry": "https://registry.npmjs.org/"
|
|
121
124
|
},
|
|
122
125
|
"authors": [
|
|
123
|
-
"
|
|
126
|
+
"insureMO"
|
|
124
127
|
],
|
|
125
128
|
"scripts": {
|
|
126
129
|
"build": "node scripts/generate-version.js && rm -rf dist && father build",
|
|
@@ -138,6 +141,7 @@
|
|
|
138
141
|
"lint:css": "stylelint \"{src,test}/**/*.{css,less}\" --ignore-pattern \"src/style/color.*.css\"",
|
|
139
142
|
"lint:es": "eslint \"{src,test}/**/*.{js,jsx,ts,tsx}\"",
|
|
140
143
|
"start": "npm run dev",
|
|
144
|
+
"test": "vitest run",
|
|
141
145
|
"watch": "father dev"
|
|
142
146
|
}
|
|
143
147
|
}
|
package/src/Anchor/anchor.tsx
CHANGED
|
@@ -139,8 +139,8 @@ const Anchor = forwardRef<HTMLDivElement, AnchorProps>((baseprops, ref) => {
|
|
|
139
139
|
|
|
140
140
|
// Scrolled above the first anchor — reset to the top item.
|
|
141
141
|
if (nextActiveKey === undefined) {
|
|
142
|
-
const first = currentItems.find(
|
|
143
|
-
|
|
142
|
+
const first = currentItems.find((item) =>
|
|
143
|
+
document.getElementById(item.key),
|
|
144
144
|
);
|
|
145
145
|
nextActiveKey = first?.key;
|
|
146
146
|
}
|
package/src/Card/card.tsx
CHANGED
|
@@ -73,12 +73,12 @@ const Card: FC<CardProps> = (baseprops) => {
|
|
|
73
73
|
)}
|
|
74
74
|
style={styles?.expandIcon}
|
|
75
75
|
aria-expanded={mergedExpanded}
|
|
76
|
+
aria-label={mergedExpanded ? 'Collapse content' : 'Expand content'}
|
|
76
77
|
icon={
|
|
77
78
|
icon ? (
|
|
78
79
|
icon
|
|
79
80
|
) : (
|
|
80
81
|
<ChevronUp
|
|
81
|
-
aria-label="expanded"
|
|
82
82
|
strokeWidth={1.5}
|
|
83
83
|
size={16}
|
|
84
84
|
style={{
|
|
@@ -134,6 +134,7 @@ const Card: FC<CardProps> = (baseprops) => {
|
|
|
134
134
|
onKeyDown={handleKeyDown}
|
|
135
135
|
tabIndex={headerClickable ? 0 : undefined}
|
|
136
136
|
role={headerClickable ? 'button' : undefined}
|
|
137
|
+
aria-expanded={headerClickable ? mergedExpanded : undefined}
|
|
137
138
|
>
|
|
138
139
|
{iconPosition === 'left' ? renderExpandIcon() : null}
|
|
139
140
|
{title ? (
|
|
@@ -154,6 +155,9 @@ const Card: FC<CardProps> = (baseprops) => {
|
|
|
154
155
|
animate={mergedExpanded ? { height: 'auto' } : { height: 0 }}
|
|
155
156
|
exit={{ height: 0, display: 'none' }}
|
|
156
157
|
transition={{ duration: animationDuration }}
|
|
158
|
+
role="region"
|
|
159
|
+
aria-labelledby={title ? headerId : undefined}
|
|
160
|
+
aria-hidden={!mergedExpanded}
|
|
157
161
|
>
|
|
158
162
|
{children}
|
|
159
163
|
</motion.div>
|
|
@@ -7,17 +7,23 @@ const CarouselItem = (props: CarouselItemProps) => {
|
|
|
7
7
|
const { style, className, children, index } = props;
|
|
8
8
|
const { prefixCls, current } = React.useContext(CarouselCtx);
|
|
9
9
|
|
|
10
|
+
const isActive = index === current - 1;
|
|
11
|
+
|
|
10
12
|
return (
|
|
11
13
|
<div
|
|
12
14
|
className={clsx(
|
|
13
15
|
`${prefixCls}-item`,
|
|
14
16
|
{
|
|
15
|
-
[`${prefixCls}-item-active`]:
|
|
17
|
+
[`${prefixCls}-item-active`]: isActive,
|
|
16
18
|
},
|
|
17
19
|
className,
|
|
18
20
|
)}
|
|
19
21
|
data-index={index}
|
|
20
22
|
style={style}
|
|
23
|
+
role="tabpanel"
|
|
24
|
+
aria-roledescription="slide"
|
|
25
|
+
aria-label={`Slide ${(index ?? 0) + 1}`}
|
|
26
|
+
aria-hidden={!isActive}
|
|
21
27
|
>
|
|
22
28
|
{children}
|
|
23
29
|
</div>
|
|
@@ -173,6 +173,9 @@ const Carousel = React.forwardRef(
|
|
|
173
173
|
{ [`${prefixCls}-arrows-visible`]: showArrow },
|
|
174
174
|
className,
|
|
175
175
|
),
|
|
176
|
+
role: 'region' as const,
|
|
177
|
+
'aria-roledescription': 'carousel',
|
|
178
|
+
'aria-live': autoplay ? ('off' as const) : ('polite' as const),
|
|
176
179
|
onMouseEnter: handleMouseEnter,
|
|
177
180
|
onMouseLeave: handleMouseLeave,
|
|
178
181
|
};
|
|
@@ -198,6 +201,15 @@ const Carousel = React.forwardRef(
|
|
|
198
201
|
)}
|
|
199
202
|
style={styles?.prev}
|
|
200
203
|
onClick={prev}
|
|
204
|
+
role="button"
|
|
205
|
+
aria-label="Previous slide"
|
|
206
|
+
tabIndex={0}
|
|
207
|
+
onKeyDown={(e) => {
|
|
208
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
209
|
+
e.preventDefault();
|
|
210
|
+
prev();
|
|
211
|
+
}
|
|
212
|
+
}}
|
|
201
213
|
>
|
|
202
214
|
{direction === 'vertical' ? <ChevronUp /> : <ChevronLeft />}
|
|
203
215
|
</div>
|
|
@@ -211,6 +223,15 @@ const Carousel = React.forwardRef(
|
|
|
211
223
|
)}
|
|
212
224
|
style={styles?.next}
|
|
213
225
|
onClick={next}
|
|
226
|
+
role="button"
|
|
227
|
+
aria-label="Next slide"
|
|
228
|
+
tabIndex={0}
|
|
229
|
+
onKeyDown={(e) => {
|
|
230
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
231
|
+
e.preventDefault();
|
|
232
|
+
next();
|
|
233
|
+
}
|
|
234
|
+
}}
|
|
214
235
|
>
|
|
215
236
|
{direction === 'vertical' ? <ChevronDown /> : <ChevronRight />}
|
|
216
237
|
</div>
|
|
@@ -228,17 +249,22 @@ const Carousel = React.forwardRef(
|
|
|
228
249
|
classNames?.dot,
|
|
229
250
|
)}
|
|
230
251
|
style={styles?.dot}
|
|
252
|
+
role="tablist"
|
|
253
|
+
aria-label="Slide controls"
|
|
231
254
|
>
|
|
232
255
|
{new Array(React.Children.count(children))
|
|
233
256
|
.fill(0)
|
|
234
257
|
.map((i, index: number) => {
|
|
258
|
+
const isActive =
|
|
259
|
+
current === index + 1 || (current === 0 && index === count - 1);
|
|
235
260
|
return (
|
|
236
261
|
<li
|
|
237
262
|
className={clsx({
|
|
238
|
-
active:
|
|
239
|
-
current === index + 1 ||
|
|
240
|
-
(current === 0 && index === count),
|
|
263
|
+
active: isActive,
|
|
241
264
|
})}
|
|
265
|
+
role="tab"
|
|
266
|
+
aria-selected={isActive}
|
|
267
|
+
aria-label={`Slide ${index + 1}`}
|
|
242
268
|
tabIndex={0}
|
|
243
269
|
onClick={() => handleIndicator(index + 1, 'click')}
|
|
244
270
|
onKeyDown={(e) => {
|
|
@@ -446,7 +446,11 @@ const Cascader = (baseprops: CascaderProps) => {
|
|
|
446
446
|
|
|
447
447
|
const renderPopup = () => {
|
|
448
448
|
return (
|
|
449
|
-
<div
|
|
449
|
+
<div
|
|
450
|
+
className={clsx(prefixCls)}
|
|
451
|
+
role="group"
|
|
452
|
+
aria-label="Cascader options"
|
|
453
|
+
>
|
|
450
454
|
{isFilter ? (
|
|
451
455
|
<SearchList
|
|
452
456
|
prefixCls={prefixCls}
|
package/src/Cascader/column.tsx
CHANGED
|
@@ -11,7 +11,11 @@ export interface ColumnProps {
|
|
|
11
11
|
const Column = (props: ColumnProps) => {
|
|
12
12
|
const { prefixCls, data, index } = props;
|
|
13
13
|
return (
|
|
14
|
-
<ul
|
|
14
|
+
<ul
|
|
15
|
+
className={`${prefixCls}-menu`}
|
|
16
|
+
role="listbox"
|
|
17
|
+
aria-label={`Level ${index + 1} options`}
|
|
18
|
+
>
|
|
15
19
|
{Array.isArray(data) &&
|
|
16
20
|
data.map((item, idx: number) => {
|
|
17
21
|
return (
|
package/src/Cascader/node.tsx
CHANGED
|
@@ -107,12 +107,24 @@ const Node = (props: NodeProps) => {
|
|
|
107
107
|
className={clsName}
|
|
108
108
|
onMouseEnter={handleMouseEnter}
|
|
109
109
|
onClick={(e: React.MouseEvent<HTMLElement>) => handleClick(false, e)}
|
|
110
|
+
role="option"
|
|
111
|
+
aria-disabled={disabled || undefined}
|
|
112
|
+
aria-selected={checked || expandedPath[level]?.key === uid}
|
|
113
|
+
aria-expanded={isParent ? expandedPath[level]?.key === uid : undefined}
|
|
114
|
+
tabIndex={disabled ? -1 : 0}
|
|
115
|
+
onKeyDown={(e) => {
|
|
116
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
117
|
+
e.preventDefault();
|
|
118
|
+
handleClick(false, e as unknown as React.MouseEvent<HTMLElement>);
|
|
119
|
+
}
|
|
120
|
+
}}
|
|
110
121
|
>
|
|
111
122
|
{multiple && (
|
|
112
123
|
<Checkbox
|
|
113
124
|
checked={isParent ? checkedAll : checked}
|
|
114
125
|
onChange={isParent ? () => handleClick(true) : undefined}
|
|
115
126
|
indeterminate={indeterminate}
|
|
127
|
+
aria-label={`Select ${typeof label === 'string' ? label : String(label)}`}
|
|
116
128
|
/>
|
|
117
129
|
)}
|
|
118
130
|
<span
|
|
@@ -125,9 +137,9 @@ const Node = (props: NodeProps) => {
|
|
|
125
137
|
</span>
|
|
126
138
|
|
|
127
139
|
{load === 1 ? (
|
|
128
|
-
<Spin size="small" />
|
|
140
|
+
<Spin size="small" aria-label="Loading" />
|
|
129
141
|
) : isLeaf === false ? (
|
|
130
|
-
<ChevronRight size={20} />
|
|
142
|
+
<ChevronRight size={20} aria-hidden="true" />
|
|
131
143
|
) : null}
|
|
132
144
|
</li>
|
|
133
145
|
);
|
|
@@ -32,10 +32,15 @@ const SearchList = (props: SearchListProps) => {
|
|
|
32
32
|
const { prefixCls, items, onClick } = props;
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
|
-
<ul
|
|
35
|
+
<ul
|
|
36
|
+
className={`${prefixCls}-filter-menu`}
|
|
37
|
+
role="listbox"
|
|
38
|
+
aria-label="Search results"
|
|
39
|
+
>
|
|
36
40
|
{items.length ? (
|
|
37
41
|
items.map((item) => {
|
|
38
|
-
const title =
|
|
42
|
+
const title =
|
|
43
|
+
item.data.$source?.title || item.data.labelPath.join(' / ');
|
|
39
44
|
|
|
40
45
|
return (
|
|
41
46
|
<li
|
|
@@ -43,13 +48,24 @@ const SearchList = (props: SearchListProps) => {
|
|
|
43
48
|
title={typeof title === 'string' ? title : String(title)}
|
|
44
49
|
onClick={() => onClick(item.data)}
|
|
45
50
|
key={item.data.uid}
|
|
51
|
+
role="option"
|
|
52
|
+
aria-disabled={item.data.$source?.disabled || undefined}
|
|
53
|
+
tabIndex={0}
|
|
54
|
+
onKeyDown={(e) => {
|
|
55
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
56
|
+
e.preventDefault();
|
|
57
|
+
onClick(item.data);
|
|
58
|
+
}
|
|
59
|
+
}}
|
|
46
60
|
>
|
|
47
61
|
{renderHighlightText(item.matches)}
|
|
48
62
|
</li>
|
|
49
63
|
);
|
|
50
64
|
})
|
|
51
65
|
) : (
|
|
52
|
-
<
|
|
66
|
+
<li role="option" aria-disabled="true">
|
|
67
|
+
{'No result'}
|
|
68
|
+
</li>
|
|
53
69
|
)}
|
|
54
70
|
</ul>
|
|
55
71
|
);
|
|
@@ -340,7 +340,8 @@ export const changeToView = (
|
|
|
340
340
|
* conversions share one collision-safe format.
|
|
341
341
|
* @param val - The path array
|
|
342
342
|
*/
|
|
343
|
-
export const formatKey = (val: Array<string | number>): string =>
|
|
343
|
+
export const formatKey = (val: Array<string | number>): string =>
|
|
344
|
+
pathToUid(val);
|
|
344
345
|
|
|
345
346
|
/**
|
|
346
347
|
* Check if a path has the same prefix as another path
|
|
@@ -441,11 +442,7 @@ export const flattenOptions = (
|
|
|
441
442
|
});
|
|
442
443
|
if (hasChild(node, children)) {
|
|
443
444
|
seen.add(node);
|
|
444
|
-
dfs(
|
|
445
|
-
node[children] as Array<Record<string, unknown>>,
|
|
446
|
-
path,
|
|
447
|
-
labelPath,
|
|
448
|
-
);
|
|
445
|
+
dfs(node[children] as Array<Record<string, unknown>>, path, labelPath);
|
|
449
446
|
seen.delete(node);
|
|
450
447
|
}
|
|
451
448
|
});
|
|
@@ -63,7 +63,12 @@ const CheckboxGroup = (baseprops: CheckboxGroupProps) => {
|
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
return (
|
|
66
|
-
<div
|
|
66
|
+
<div
|
|
67
|
+
className={cls}
|
|
68
|
+
style={style}
|
|
69
|
+
role="group"
|
|
70
|
+
aria-disabled={disabled || undefined}
|
|
71
|
+
>
|
|
67
72
|
<CheckboxGroupCtx.Provider
|
|
68
73
|
value={{ name, buttonStyle, onChange: handleChange }}
|
|
69
74
|
>
|
|
@@ -51,6 +51,7 @@ const Checkbox = (baseprops: CheckboxProps) => {
|
|
|
51
51
|
className,
|
|
52
52
|
)}
|
|
53
53
|
style={style}
|
|
54
|
+
aria-disabled={disabled || undefined}
|
|
54
55
|
>
|
|
55
56
|
<span
|
|
56
57
|
className={clsx(`${prefixCls}`, {
|
|
@@ -68,10 +69,12 @@ const Checkbox = (baseprops: CheckboxProps) => {
|
|
|
68
69
|
disabled={disabled}
|
|
69
70
|
checked={mergedChecked}
|
|
70
71
|
onChange={handleChange}
|
|
72
|
+
aria-checked={indeterminate ? 'mixed' : mergedChecked}
|
|
71
73
|
/>
|
|
72
74
|
<span
|
|
73
75
|
className={clsx(`${prefixCls}-inner`, classNames?.inner)}
|
|
74
76
|
style={styles?.inner}
|
|
77
|
+
aria-hidden="true"
|
|
75
78
|
></span>
|
|
76
79
|
</span>
|
|
77
80
|
{children ? (
|
package/src/Collapse/panel.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import { ChevronRight } from 'lucide-react';
|
|
3
3
|
import { AnimatePresence, motion } from 'motion/react';
|
|
4
|
-
import React, { useContext } from 'react';
|
|
4
|
+
import React, { useContext, useId } from 'react';
|
|
5
5
|
import Button from '../Button';
|
|
6
6
|
import { CollapseContext } from './collapse';
|
|
7
7
|
import type { PanelProps } from './interface';
|
|
@@ -12,6 +12,10 @@ const Panel: React.FC<PanelProps & { id: string | number }> = (props) => {
|
|
|
12
12
|
|
|
13
13
|
const { prefixCls, activeKey, onExpand } = useContext(CollapseContext);
|
|
14
14
|
|
|
15
|
+
const panelId = useId();
|
|
16
|
+
const headerId = `${panelId}-header`;
|
|
17
|
+
const contentId = `${panelId}-content`;
|
|
18
|
+
|
|
15
19
|
const expanded = activeKey.includes(id);
|
|
16
20
|
|
|
17
21
|
const itemClassName = clsx(
|
|
@@ -28,7 +32,9 @@ const Panel: React.FC<PanelProps & { id: string | number }> = (props) => {
|
|
|
28
32
|
className={clsx(`${prefixCls}-header`, classNames?.header)}
|
|
29
33
|
role="button"
|
|
30
34
|
style={styles?.header}
|
|
35
|
+
id={headerId}
|
|
31
36
|
aria-expanded={expanded}
|
|
37
|
+
aria-controls={contentId}
|
|
32
38
|
aria-disabled="false"
|
|
33
39
|
tabIndex={0}
|
|
34
40
|
onClick={() => onExpand(id)}
|
|
@@ -44,6 +50,7 @@ const Panel: React.FC<PanelProps & { id: string | number }> = (props) => {
|
|
|
44
50
|
style={styles?.expandIcon}
|
|
45
51
|
animate={{ rotate: expanded ? 90 : 0 }}
|
|
46
52
|
transition={{ duration: 0.15 }}
|
|
53
|
+
aria-hidden="true"
|
|
47
54
|
>
|
|
48
55
|
<Button icon={<ChevronRight size={16} />} type="text" />
|
|
49
56
|
</motion.div>
|
|
@@ -69,6 +76,9 @@ const Panel: React.FC<PanelProps & { id: string | number }> = (props) => {
|
|
|
69
76
|
<motion.div
|
|
70
77
|
className={clsx(`${prefixCls}-content`, classNames?.content)}
|
|
71
78
|
style={styles?.content}
|
|
79
|
+
id={contentId}
|
|
80
|
+
role="region"
|
|
81
|
+
aria-labelledby={headerId}
|
|
72
82
|
initial={{ height: 0, opacity: 0 }}
|
|
73
83
|
animate={{ height: 'auto', opacity: 1 }}
|
|
74
84
|
exit={{ height: 0, opacity: 0 }}
|
package/src/Dialog/dialog.tsx
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import { X } from 'lucide-react';
|
|
3
3
|
import { motion } from 'motion/react';
|
|
4
|
-
import React, {
|
|
4
|
+
import React, {
|
|
5
|
+
useCallback,
|
|
6
|
+
useContext,
|
|
7
|
+
useEffect,
|
|
8
|
+
useId,
|
|
9
|
+
useRef,
|
|
10
|
+
useState,
|
|
11
|
+
} from 'react';
|
|
5
12
|
import Button from '../Button';
|
|
6
13
|
import { GlobalContext } from '../Config-Provider';
|
|
7
14
|
import useEsc from '../hooks/useEsc';
|
|
@@ -55,7 +62,17 @@ const Dialog = (baseprops: DialogProps) => {
|
|
|
55
62
|
} = props;
|
|
56
63
|
|
|
57
64
|
const [delayOpen, setDelayOpen] = useState(open);
|
|
65
|
+
const [contentElement, setContentElement] = useState<HTMLDivElement | null>(
|
|
66
|
+
null,
|
|
67
|
+
);
|
|
58
68
|
const contentRef = useRef<HTMLDivElement>(null);
|
|
69
|
+
const setContentRef = useCallback((element: HTMLDivElement | null) => {
|
|
70
|
+
contentRef.current = element;
|
|
71
|
+
setContentElement(element);
|
|
72
|
+
}, []);
|
|
73
|
+
const dialogId = useId();
|
|
74
|
+
const titleId = `${dialogId}-title`;
|
|
75
|
+
const bodyId = `${dialogId}-body`;
|
|
59
76
|
|
|
60
77
|
// When open changes and openResetLocation is true, reset position
|
|
61
78
|
useEffect(() => {
|
|
@@ -71,7 +88,7 @@ const Dialog = (baseprops: DialogProps) => {
|
|
|
71
88
|
});
|
|
72
89
|
|
|
73
90
|
// lock focus in the dialog
|
|
74
|
-
useLockFocus(
|
|
91
|
+
useLockFocus(contentElement, delayOpen);
|
|
75
92
|
|
|
76
93
|
// enable esc to close dialog
|
|
77
94
|
useEsc({
|
|
@@ -81,8 +98,8 @@ const Dialog = (baseprops: DialogProps) => {
|
|
|
81
98
|
},
|
|
82
99
|
});
|
|
83
100
|
|
|
84
|
-
// manage focus
|
|
85
|
-
useFocusManage(
|
|
101
|
+
// manage focus once per open cycle
|
|
102
|
+
useFocusManage(contentElement, open);
|
|
86
103
|
|
|
87
104
|
const cls = clsx(prefixCls, {
|
|
88
105
|
[`${prefixCls}-open`]: delayOpen,
|
|
@@ -143,6 +160,7 @@ const Dialog = (baseprops: DialogProps) => {
|
|
|
143
160
|
<div
|
|
144
161
|
className={clsx(`${prefixCls}-mask`, classNames?.mask)}
|
|
145
162
|
style={styles?.mask}
|
|
163
|
+
aria-hidden="true"
|
|
146
164
|
></div>
|
|
147
165
|
)}
|
|
148
166
|
<div
|
|
@@ -154,7 +172,11 @@ const Dialog = (baseprops: DialogProps) => {
|
|
|
154
172
|
style={{ width: fullscreen ? '100%' : width, ...styles?.content }}
|
|
155
173
|
tabIndex={0}
|
|
156
174
|
onClick={(e) => e.stopPropagation()}
|
|
157
|
-
ref={
|
|
175
|
+
ref={setContentRef}
|
|
176
|
+
role="dialog"
|
|
177
|
+
aria-modal={showMask ? true : undefined}
|
|
178
|
+
aria-labelledby={title ? titleId : undefined}
|
|
179
|
+
aria-describedby={bodyId}
|
|
158
180
|
>
|
|
159
181
|
{closable ? (
|
|
160
182
|
<Button
|
|
@@ -175,12 +197,19 @@ const Dialog = (baseprops: DialogProps) => {
|
|
|
175
197
|
className={clsx(`${prefixCls}-header`, classNames?.header)}
|
|
176
198
|
style={styles?.header}
|
|
177
199
|
>
|
|
178
|
-
|
|
200
|
+
{typeof title === 'string' ? (
|
|
201
|
+
<div className={`${prefixCls}-title`} id={titleId}>
|
|
202
|
+
{title}
|
|
203
|
+
</div>
|
|
204
|
+
) : (
|
|
205
|
+
title
|
|
206
|
+
)}
|
|
179
207
|
</div>
|
|
180
208
|
) : null}
|
|
181
209
|
<div
|
|
182
210
|
className={clsx(`${prefixCls}-body`, classNames?.body)}
|
|
183
211
|
style={styles?.body}
|
|
212
|
+
id={bodyId}
|
|
184
213
|
>
|
|
185
214
|
{children}
|
|
186
215
|
</div>
|
package/src/Dialog/interface.ts
CHANGED
package/src/Drawer/drawer.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
2
|
import { X } from 'lucide-react';
|
|
3
3
|
import { motion } from 'motion/react';
|
|
4
|
-
import React, { useContext, useRef, useState } from 'react';
|
|
4
|
+
import React, { useContext, useId, useRef, useState } from 'react';
|
|
5
5
|
import Button from '../Button';
|
|
6
6
|
import { GlobalContext } from '../Config-Provider';
|
|
7
7
|
import Portal from '../Portal';
|
|
@@ -81,6 +81,9 @@ const Drawer = (baseprops: DrawerProps) => {
|
|
|
81
81
|
|
|
82
82
|
const [delayOpen, setDelayOpen] = useState(open);
|
|
83
83
|
const contentRef = useRef<HTMLDivElement>(null);
|
|
84
|
+
const drawerId = useId();
|
|
85
|
+
const titleId = `${drawerId}-title`;
|
|
86
|
+
const bodyId = `${drawerId}-body`;
|
|
84
87
|
|
|
85
88
|
useLockFocus(contentRef.current, delayOpen);
|
|
86
89
|
|
|
@@ -149,7 +152,7 @@ const Drawer = (baseprops: DrawerProps) => {
|
|
|
149
152
|
const renderNode = () => {
|
|
150
153
|
const { initial, animate, exit } = getAnimate(placement, open);
|
|
151
154
|
return (
|
|
152
|
-
<div {...rest} className={cls} style={style}
|
|
155
|
+
<div {...rest} className={cls} style={style}>
|
|
153
156
|
{showMask && delayOpen && (
|
|
154
157
|
<motion.div
|
|
155
158
|
className={clsx(`${prefixCls}-mask`, classNames?.mask)}
|
|
@@ -159,6 +162,7 @@ const Drawer = (baseprops: DrawerProps) => {
|
|
|
159
162
|
animate={open ? { opacity: 1 } : { opacity: 0 }}
|
|
160
163
|
exit={{ opacity: 0 }}
|
|
161
164
|
transition={{ duration: ANIMATION_DURATION }}
|
|
165
|
+
aria-hidden="true"
|
|
162
166
|
></motion.div>
|
|
163
167
|
)}
|
|
164
168
|
<motion.div
|
|
@@ -191,6 +195,10 @@ const Drawer = (baseprops: DrawerProps) => {
|
|
|
191
195
|
tabIndex={0}
|
|
192
196
|
style={styles?.content}
|
|
193
197
|
ref={contentRef}
|
|
198
|
+
role="dialog"
|
|
199
|
+
aria-modal={showMask ? true : undefined}
|
|
200
|
+
aria-labelledby={title ? titleId : undefined}
|
|
201
|
+
aria-describedby={bodyId}
|
|
194
202
|
>
|
|
195
203
|
{renderClose()}
|
|
196
204
|
{title ? (
|
|
@@ -198,12 +206,19 @@ const Drawer = (baseprops: DrawerProps) => {
|
|
|
198
206
|
className={clsx(`${prefixCls}-header`, classNames?.header)}
|
|
199
207
|
style={styles?.header}
|
|
200
208
|
>
|
|
201
|
-
<div
|
|
209
|
+
<div
|
|
210
|
+
className={clsx(`${prefixCls}-title`, classNames?.title)}
|
|
211
|
+
style={styles?.title}
|
|
212
|
+
id={titleId}
|
|
213
|
+
>
|
|
214
|
+
{title}
|
|
215
|
+
</div>
|
|
202
216
|
</div>
|
|
203
217
|
) : null}
|
|
204
218
|
<div
|
|
205
219
|
className={clsx(`${prefixCls}-body`, classNames?.body)}
|
|
206
220
|
style={styles?.body}
|
|
221
|
+
id={bodyId}
|
|
207
222
|
>
|
|
208
223
|
{children}
|
|
209
224
|
</div>
|
package/src/Form/Group.tsx
CHANGED
|
@@ -9,10 +9,10 @@ import React, {
|
|
|
9
9
|
useRef,
|
|
10
10
|
} from 'react';
|
|
11
11
|
import Grid from '../Grid';
|
|
12
|
-
import { runValidator } from './utils/validate';
|
|
13
12
|
import FieldContext from './FieldContext';
|
|
14
13
|
import FormContext from './FormContext';
|
|
15
14
|
import type { FieldGroupProps, NamePath, ValidateMessage } from './interface';
|
|
15
|
+
import { runValidator } from './utils/validate';
|
|
16
16
|
|
|
17
17
|
const Group: React.FC<FieldGroupProps> = (props) => {
|
|
18
18
|
const { label, required, rules, cols, children, style, className } = props;
|
|
@@ -39,9 +39,7 @@ const Group: React.FC<FieldGroupProps> = (props) => {
|
|
|
39
39
|
const [, forceValidate] = useReducer((x) => x + 1, 0); // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
40
40
|
|
|
41
41
|
// Group validation
|
|
42
|
-
const validate = async (
|
|
43
|
-
force: boolean,
|
|
44
|
-
): Promise<ValidateMessage[]> => {
|
|
42
|
+
const validate = async (force: boolean): Promise<ValidateMessage[]> => {
|
|
45
43
|
if (!required && (!rules || rules.length === 0)) return [];
|
|
46
44
|
|
|
47
45
|
// Skip if not touched and not forced validation
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Button,
|
|
3
|
-
Form,
|
|
4
|
-
Grid,
|
|
5
|
-
Input,
|
|
6
|
-
Space,
|
|
7
|
-
TextArea,
|
|
8
|
-
} from '@rainbow-oh/yee-c';
|
|
1
|
+
import { Button, Form, Grid, Input, Space, TextArea } from '@rainbow-oh/yee-c';
|
|
9
2
|
import { Info } from 'lucide-react';
|
|
10
3
|
import React from 'react';
|
|
11
4
|
|
|
@@ -29,9 +22,7 @@ export default () => {
|
|
|
29
22
|
name="username"
|
|
30
23
|
label="Username"
|
|
31
24
|
tooltip="Used for login. 4-20 characters."
|
|
32
|
-
rules={[
|
|
33
|
-
{ required: true, message: 'Please input your username!' },
|
|
34
|
-
]}
|
|
25
|
+
rules={[{ required: true, message: 'Please input your username!' }]}
|
|
35
26
|
>
|
|
36
27
|
<Input placeholder="Please input your username" />
|
|
37
28
|
</Form.Field>
|
|
@@ -134,10 +134,7 @@ export async function runValidator(
|
|
|
134
134
|
* Returns { passed, message? }. Sync rules short-circuit; the custom validator
|
|
135
135
|
* is awaited so async validators are supported.
|
|
136
136
|
*/
|
|
137
|
-
async function validate(
|
|
138
|
-
rule: Rule,
|
|
139
|
-
value: unknown,
|
|
140
|
-
): Promise<ValidateResult> {
|
|
137
|
+
async function validate(rule: Rule, value: unknown): Promise<ValidateResult> {
|
|
141
138
|
if (rule.required && isEmpty(value)) {
|
|
142
139
|
return { passed: false };
|
|
143
140
|
}
|