@rc-component/cascader 1.1.0 → 1.2.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/es/Cascader.d.ts CHANGED
@@ -55,7 +55,15 @@ export interface FieldNames<OptionType extends DefaultOptionType = DefaultOption
55
55
  export type ValueType<OptionType extends DefaultOptionType = DefaultOptionType, ValueField extends keyof OptionType = keyof OptionType> = keyof OptionType extends ValueField ? unknown extends OptionType['value'] ? OptionType[ValueField] : OptionType['value'] : OptionType[ValueField];
56
56
  export type GetValueType<OptionType extends DefaultOptionType = DefaultOptionType, ValueField extends keyof OptionType = keyof OptionType, Multiple extends boolean | React.ReactNode = false> = false extends Multiple ? ValueType<Required<OptionType>, ValueField>[] : ValueType<Required<OptionType>, ValueField>[][];
57
57
  export type GetOptionType<OptionType extends DefaultOptionType = DefaultOptionType, Multiple extends boolean | React.ReactNode = false> = false extends Multiple ? OptionType[] : OptionType[][];
58
+ type SemanticName = 'input' | 'prefix' | 'suffix';
59
+ type PopupSemantic = 'list' | 'listItem';
58
60
  export interface CascaderProps<OptionType extends DefaultOptionType = DefaultOptionType, ValueField extends keyof OptionType = keyof OptionType, Multiple extends boolean | React.ReactNode = false> extends BaseCascaderProps<OptionType, ValueField> {
61
+ styles?: Partial<Record<SemanticName, React.CSSProperties>> & {
62
+ popup?: Partial<Record<PopupSemantic, React.CSSProperties>>;
63
+ };
64
+ classNames?: Partial<Record<SemanticName, string>> & {
65
+ popup?: Partial<Record<PopupSemantic, string>>;
66
+ };
59
67
  checkable?: Multiple;
60
68
  value?: GetValueType<OptionType, ValueField, Multiple>;
61
69
  defaultValue?: GetValueType<OptionType, ValueField, Multiple>;
package/es/Cascader.js CHANGED
@@ -45,6 +45,8 @@ const Cascader = /*#__PURE__*/React.forwardRef((props, ref) => {
45
45
  popupClassName,
46
46
  popupMenuColumnStyle,
47
47
  popupStyle: customPopupStyle,
48
+ classNames,
49
+ styles,
48
50
  placement,
49
51
  onPopupVisibleChange,
50
52
  // Icon
@@ -147,6 +149,8 @@ const Cascader = /*#__PURE__*/React.forwardRef((props, ref) => {
147
149
 
148
150
  // ========================== Context ===========================
149
151
  const cascaderContext = React.useMemo(() => ({
152
+ classNames,
153
+ styles,
150
154
  options: mergedOptions,
151
155
  fieldNames: mergedFieldNames,
152
156
  values: checkedValues,
@@ -184,6 +188,16 @@ const Cascader = /*#__PURE__*/React.forwardRef((props, ref) => {
184
188
  prefixCls: prefixCls,
185
189
  autoClearSearchValue: autoClearSearchValue,
186
190
  popupMatchSelectWidth: popupMatchSelectWidth,
191
+ classNames: {
192
+ prefix: classNames?.prefix,
193
+ suffix: classNames?.suffix,
194
+ input: classNames?.input
195
+ },
196
+ styles: {
197
+ prefix: styles?.prefix,
198
+ suffix: styles?.suffix,
199
+ input: styles?.input
200
+ },
187
201
  popupStyle: {
188
202
  ...popupStyle,
189
203
  ...customPopupStyle
@@ -1,4 +1,4 @@
1
- import classNames from 'classnames';
1
+ import cls from 'classnames';
2
2
  import * as React from 'react';
3
3
  import CascaderContext from "../context";
4
4
  import { SEARCH_MARK } from "../hooks/useSearchOptions";
@@ -22,6 +22,7 @@ export default function Column({
22
22
  }) {
23
23
  const menuPrefixCls = `${prefixCls}-menu`;
24
24
  const menuItemPrefixCls = `${prefixCls}-menu-item`;
25
+ const menuRef = React.useRef(null);
25
26
  const {
26
27
  fieldNames,
27
28
  changeOnSelect,
@@ -29,7 +30,9 @@ export default function Column({
29
30
  expandIcon,
30
31
  loadingIcon,
31
32
  popupMenuColumnStyle,
32
- optionRender
33
+ optionRender,
34
+ classNames,
35
+ styles
33
36
  } = React.useContext(CascaderContext);
34
37
  const hoverOpen = expandTrigger === 'hover';
35
38
  const isOptionDisabled = disabled => propsDisabled || disabled;
@@ -69,10 +72,24 @@ export default function Column({
69
72
  fullPathKey
70
73
  };
71
74
  }), [options, checkedSet, fieldNames, halfCheckedSet, loadingKeys, prevValuePath]);
75
+ React.useEffect(() => {
76
+ if (menuRef.current) {
77
+ const selector = `.${menuItemPrefixCls}-active`;
78
+ const activeElement = menuRef.current.querySelector(selector);
79
+ if (activeElement) {
80
+ activeElement.scrollIntoView({
81
+ block: 'nearest',
82
+ inline: 'nearest'
83
+ });
84
+ }
85
+ }
86
+ }, [activeValue, menuItemPrefixCls]);
72
87
 
73
88
  // ============================ Render ============================
74
89
  return /*#__PURE__*/React.createElement("ul", {
75
- className: menuPrefixCls,
90
+ className: cls(menuPrefixCls, classNames?.popup?.list),
91
+ style: styles?.popup?.list,
92
+ ref: menuRef,
76
93
  role: "menu"
77
94
  }, optionInfoList.map(({
78
95
  disabled,
@@ -117,13 +134,16 @@ export default function Column({
117
134
  // >>>>> Render
118
135
  return /*#__PURE__*/React.createElement("li", {
119
136
  key: fullPathKey,
120
- className: classNames(menuItemPrefixCls, {
137
+ className: cls(menuItemPrefixCls, classNames?.popup?.listItem, {
121
138
  [`${menuItemPrefixCls}-expand`]: !isMergedLeaf,
122
139
  [`${menuItemPrefixCls}-active`]: activeValue === value || activeValue === fullPathKey,
123
140
  [`${menuItemPrefixCls}-disabled`]: isOptionDisabled(disabled),
124
141
  [`${menuItemPrefixCls}-loading`]: isLoading
125
142
  }),
126
- style: popupMenuColumnStyle,
143
+ style: {
144
+ ...popupMenuColumnStyle,
145
+ ...styles?.popup?.listItem
146
+ },
127
147
  role: "menuitemcheckbox",
128
148
  title: title,
129
149
  "aria-checked": checked,
package/es/context.d.ts CHANGED
@@ -16,6 +16,8 @@ export interface CascaderContextProps {
16
16
  loadingIcon?: React.ReactNode;
17
17
  popupMenuColumnStyle?: React.CSSProperties;
18
18
  optionRender?: CascaderProps['optionRender'];
19
+ classNames?: CascaderProps['classNames'];
20
+ styles?: CascaderProps['styles'];
19
21
  }
20
22
  declare const CascaderContext: React.Context<CascaderContextProps>;
21
23
  export default CascaderContext;
package/lib/Cascader.d.ts CHANGED
@@ -55,7 +55,15 @@ export interface FieldNames<OptionType extends DefaultOptionType = DefaultOption
55
55
  export type ValueType<OptionType extends DefaultOptionType = DefaultOptionType, ValueField extends keyof OptionType = keyof OptionType> = keyof OptionType extends ValueField ? unknown extends OptionType['value'] ? OptionType[ValueField] : OptionType['value'] : OptionType[ValueField];
56
56
  export type GetValueType<OptionType extends DefaultOptionType = DefaultOptionType, ValueField extends keyof OptionType = keyof OptionType, Multiple extends boolean | React.ReactNode = false> = false extends Multiple ? ValueType<Required<OptionType>, ValueField>[] : ValueType<Required<OptionType>, ValueField>[][];
57
57
  export type GetOptionType<OptionType extends DefaultOptionType = DefaultOptionType, Multiple extends boolean | React.ReactNode = false> = false extends Multiple ? OptionType[] : OptionType[][];
58
+ type SemanticName = 'input' | 'prefix' | 'suffix';
59
+ type PopupSemantic = 'list' | 'listItem';
58
60
  export interface CascaderProps<OptionType extends DefaultOptionType = DefaultOptionType, ValueField extends keyof OptionType = keyof OptionType, Multiple extends boolean | React.ReactNode = false> extends BaseCascaderProps<OptionType, ValueField> {
61
+ styles?: Partial<Record<SemanticName, React.CSSProperties>> & {
62
+ popup?: Partial<Record<PopupSemantic, React.CSSProperties>>;
63
+ };
64
+ classNames?: Partial<Record<SemanticName, string>> & {
65
+ popup?: Partial<Record<PopupSemantic, string>>;
66
+ };
59
67
  checkable?: Multiple;
60
68
  value?: GetValueType<OptionType, ValueField, Multiple>;
61
69
  defaultValue?: GetValueType<OptionType, ValueField, Multiple>;
package/lib/Cascader.js CHANGED
@@ -54,6 +54,8 @@ const Cascader = /*#__PURE__*/React.forwardRef((props, ref) => {
54
54
  popupClassName,
55
55
  popupMenuColumnStyle,
56
56
  popupStyle: customPopupStyle,
57
+ classNames,
58
+ styles,
57
59
  placement,
58
60
  onPopupVisibleChange,
59
61
  // Icon
@@ -156,6 +158,8 @@ const Cascader = /*#__PURE__*/React.forwardRef((props, ref) => {
156
158
 
157
159
  // ========================== Context ===========================
158
160
  const cascaderContext = React.useMemo(() => ({
161
+ classNames,
162
+ styles,
159
163
  options: mergedOptions,
160
164
  fieldNames: mergedFieldNames,
161
165
  values: checkedValues,
@@ -193,6 +197,16 @@ const Cascader = /*#__PURE__*/React.forwardRef((props, ref) => {
193
197
  prefixCls: prefixCls,
194
198
  autoClearSearchValue: autoClearSearchValue,
195
199
  popupMatchSelectWidth: popupMatchSelectWidth,
200
+ classNames: {
201
+ prefix: classNames?.prefix,
202
+ suffix: classNames?.suffix,
203
+ input: classNames?.input
204
+ },
205
+ styles: {
206
+ prefix: styles?.prefix,
207
+ suffix: styles?.suffix,
208
+ input: styles?.input
209
+ },
196
210
  popupStyle: {
197
211
  ...popupStyle,
198
212
  ...customPopupStyle
@@ -32,6 +32,7 @@ function Column({
32
32
  }) {
33
33
  const menuPrefixCls = `${prefixCls}-menu`;
34
34
  const menuItemPrefixCls = `${prefixCls}-menu-item`;
35
+ const menuRef = React.useRef(null);
35
36
  const {
36
37
  fieldNames,
37
38
  changeOnSelect,
@@ -39,7 +40,9 @@ function Column({
39
40
  expandIcon,
40
41
  loadingIcon,
41
42
  popupMenuColumnStyle,
42
- optionRender
43
+ optionRender,
44
+ classNames,
45
+ styles
43
46
  } = React.useContext(_context.default);
44
47
  const hoverOpen = expandTrigger === 'hover';
45
48
  const isOptionDisabled = disabled => propsDisabled || disabled;
@@ -79,10 +82,24 @@ function Column({
79
82
  fullPathKey
80
83
  };
81
84
  }), [options, checkedSet, fieldNames, halfCheckedSet, loadingKeys, prevValuePath]);
85
+ React.useEffect(() => {
86
+ if (menuRef.current) {
87
+ const selector = `.${menuItemPrefixCls}-active`;
88
+ const activeElement = menuRef.current.querySelector(selector);
89
+ if (activeElement) {
90
+ activeElement.scrollIntoView({
91
+ block: 'nearest',
92
+ inline: 'nearest'
93
+ });
94
+ }
95
+ }
96
+ }, [activeValue, menuItemPrefixCls]);
82
97
 
83
98
  // ============================ Render ============================
84
99
  return /*#__PURE__*/React.createElement("ul", {
85
- className: menuPrefixCls,
100
+ className: (0, _classnames.default)(menuPrefixCls, classNames?.popup?.list),
101
+ style: styles?.popup?.list,
102
+ ref: menuRef,
86
103
  role: "menu"
87
104
  }, optionInfoList.map(({
88
105
  disabled,
@@ -127,13 +144,16 @@ function Column({
127
144
  // >>>>> Render
128
145
  return /*#__PURE__*/React.createElement("li", {
129
146
  key: fullPathKey,
130
- className: (0, _classnames.default)(menuItemPrefixCls, {
147
+ className: (0, _classnames.default)(menuItemPrefixCls, classNames?.popup?.listItem, {
131
148
  [`${menuItemPrefixCls}-expand`]: !isMergedLeaf,
132
149
  [`${menuItemPrefixCls}-active`]: activeValue === value || activeValue === fullPathKey,
133
150
  [`${menuItemPrefixCls}-disabled`]: isOptionDisabled(disabled),
134
151
  [`${menuItemPrefixCls}-loading`]: isLoading
135
152
  }),
136
- style: popupMenuColumnStyle,
153
+ style: {
154
+ ...popupMenuColumnStyle,
155
+ ...styles?.popup?.listItem
156
+ },
137
157
  role: "menuitemcheckbox",
138
158
  title: title,
139
159
  "aria-checked": checked,
package/lib/context.d.ts CHANGED
@@ -16,6 +16,8 @@ export interface CascaderContextProps {
16
16
  loadingIcon?: React.ReactNode;
17
17
  popupMenuColumnStyle?: React.CSSProperties;
18
18
  optionRender?: CascaderProps['optionRender'];
19
+ classNames?: CascaderProps['classNames'];
20
+ styles?: CascaderProps['styles'];
19
21
  }
20
22
  declare const CascaderContext: React.Context<CascaderContextProps>;
21
23
  export default CascaderContext;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rc-component/cascader",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "cascade select ui component for react",
5
5
  "keywords": [
6
6
  "react",
@@ -46,7 +46,8 @@
46
46
  "@rc-component/select": "~1.0.0",
47
47
  "@rc-component/tree": "~1.0.0",
48
48
  "@rc-component/util": "^1.2.1",
49
- "classnames": "^2.3.1"
49
+ "classnames": "^2.3.1",
50
+ "eslint-plugin-unicorn": "^47.0.0"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@rc-component/father-plugin": "^2.0.2",
@@ -70,7 +71,7 @@
70
71
  "enzyme-to-json": "^3.2.1",
71
72
  "eslint": "^8.54.0",
72
73
  "eslint-plugin-jest": "^28.8.3",
73
- "eslint-plugin-unicorn": "^52.0.0",
74
+ "eslint-plugin-unicorn": "^58.0.0",
74
75
  "father": "^4.0.0",
75
76
  "gh-pages": "^6.1.1",
76
77
  "glob": "^7.1.6",