@rainbow-oh/yee-c 0.15.0 → 0.15.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rainbow-oh/yee-c",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
4
4
  "description": "yee basic components",
5
5
  "keywords": [
6
6
  "react",
@@ -8,7 +8,7 @@ import React from 'react';
8
8
  export default () => {
9
9
  return (
10
10
  <InputNumber
11
- defaultValue={0}
11
+ defaultValue={123}
12
12
  placeholder="Enter a number"
13
13
  onChange={(value) => console.log('value:', value)}
14
14
  />
@@ -63,8 +63,8 @@ Enter a number within certain range with the mouse or keyboard.
63
63
  | Property | Type | Description | Default |
64
64
  | --- | --- | --- | --- |
65
65
  | prefixCls | `string` | Custom class name prefix | - |
66
- | value | `number \| null` | Current value | - |
67
- | defaultValue | `number \| null` | Default value | - |
66
+ | value | `number \| string \| null` | Current value (`''` is treated as empty and never renders as 0 with a formatter) | - |
67
+ | defaultValue | `number \| string \| null` | Default value | - |
68
68
  | min | `number` | Minimum value | -Infinity |
69
69
  | max | `number` | Maximum value | Infinity |
70
70
  | step | `number` | Step value | `1` |
@@ -67,8 +67,8 @@ toc: 'content'
67
67
  | 属性名 | 类型 | 描述 | 默认值 |
68
68
  | --- | --- | --- | --- |
69
69
  | prefixCls | `string` | 自定义类名前缀 | - |
70
- | value | `number \| null` | 受控的值 | - |
71
- | defaultValue | `number \| null` | 默认值 | - |
70
+ | value | `number \| string \| null` | 受控的值(`''` 视为空值,配 formatter 也不会渲染成 0) | - |
71
+ | defaultValue | `number \| string \| null` | 默认值 | - |
72
72
  | min | `number` | 最小值 | -Infinity |
73
73
  | max | `number` | 最大值 | Infinity |
74
74
  | step | `number` | 步长 | `1` |
@@ -49,7 +49,7 @@ const InputNumber = forwardRef<HTMLInputElement, InputNumberProps>(
49
49
  ...rest
50
50
  } = props;
51
51
 
52
- const [mergedValue, setMergedValue] = useMergedState<number | null>(null, {
52
+ const [mergedValue, setMergedValue] = useMergedState<number | string | null>(null, {
53
53
  value,
54
54
  defaultValue,
55
55
  });
@@ -57,9 +57,24 @@ const InputNumber = forwardRef<HTMLInputElement, InputNumberProps>(
57
57
  const [focused, setFocused] = useState(false);
58
58
  const inputRef = useRef<HTMLInputElement>(null);
59
59
 
60
+ /** 字符串值(表单 store 常见)参与算术/比较前转数字;不可解析返回 null */
61
+ function toNumber(val: number | string | null | undefined): number | null {
62
+ if (val === null || val === undefined || val === '') return null;
63
+ const n = Number(val);
64
+ return Number.isNaN(n) ? null : n;
65
+ }
66
+
60
67
  // Format value
61
- function formatValue(val: number | null | undefined): string {
62
- if (val === null || val === undefined || isNaN(val)) return '';
68
+ function formatValue(val: number | string | null | undefined): string {
69
+ // '' 与 null/undefined 同为空值:Number('') === 0,若不拦截会被
70
+ // formatter/precision 格式化成 '0'(如全局千分位 formatter 场景)
71
+ if (
72
+ val === null ||
73
+ val === undefined ||
74
+ val === '' ||
75
+ isNaN(val as number)
76
+ )
77
+ return '';
63
78
 
64
79
  let formattedVal =
65
80
  precision !== undefined ? Number(val).toFixed(precision) : val;
@@ -149,7 +164,7 @@ const InputNumber = forwardRef<HTMLInputElement, InputNumberProps>(
149
164
  if (disabled || readOnly) return;
150
165
 
151
166
  const offset = type === 'up' ? step : -step;
152
- const currentValue = mergedValue ?? 0;
167
+ const currentValue = toNumber(mergedValue) ?? 0;
153
168
  const newValue = currentValue + offset;
154
169
 
155
170
  updateValue(newValue);
@@ -259,7 +274,10 @@ const InputNumber = forwardRef<HTMLInputElement, InputNumberProps>(
259
274
  {
260
275
  [`${prefixCls}-handler-disabled`]:
261
276
  disabled ||
262
- (mergedValue !== null && mergedValue >= max),
277
+ (() => {
278
+ const n = toNumber(mergedValue);
279
+ return n !== null && n >= max;
280
+ })(),
263
281
  },
264
282
  )}
265
283
  onClick={() => handleStep('up')}
@@ -273,7 +291,10 @@ const InputNumber = forwardRef<HTMLInputElement, InputNumberProps>(
273
291
  {
274
292
  [`${prefixCls}-handler-disabled`]:
275
293
  disabled ||
276
- (mergedValue !== null && mergedValue <= min),
294
+ (() => {
295
+ const n = toNumber(mergedValue);
296
+ return n !== null && n <= min;
297
+ })(),
277
298
  },
278
299
  )}
279
300
  onClick={() => handleStep('down')}
@@ -34,13 +34,13 @@ export interface InputNumberProps extends Omit<
34
34
  */
35
35
  size?: 'small' | 'default' | 'large';
36
36
  /**
37
- * Controlled value
37
+ * Controlled value('' 视为空值,配合 formatter 不会渲染成 0)
38
38
  */
39
- value?: number | null;
39
+ value?: number | string | null;
40
40
  /**
41
41
  * Default value
42
42
  */
43
- defaultValue?: number | null;
43
+ defaultValue?: number | string | null;
44
44
  /**
45
45
  * Minimum value
46
46
  */
@@ -104,7 +104,7 @@ Filter configuration of `ColumnProps.filter`.
104
104
  | searchable | `boolean` | Whether searchable; renders a search input when `items` is unset | `true` |
105
105
  | filterOnClose | `boolean` | Whether to apply the filter when the panel closes | `true` |
106
106
  | icon | `(filtered: boolean) => React.ReactNode` | Custom filter icon | - |
107
- | render | `() => React.ReactNode` | Custom filter panel content | - |
107
+ | render | `(ctx: { close: () => void }) => React.ReactNode` | Custom filter panel content; `ctx.close()` closes the filter popover | - |
108
108
  | onFilter | `(value: FilterValue, record: object) => boolean` | Local filter function; falls back to default string-includes matching when unset | - |
109
109
  | filtered | `boolean` | Force the filter icon highlight (takes precedence over `filteredValue`) | - |
110
110
  | filteredValue | `FilterValue \| FilterValue[]` | (Controlled) Filter value. When set, the column's filter state is fully controlled: panel echo, icon highlight and the `filters` in `onChange` all derive from it; reset with `''` / `[]` | - |
@@ -109,7 +109,7 @@ toc: 'content'
109
109
  | searchable | `boolean` | 是否可搜索;未配置 `items` 时渲染搜索输入框 | `true` |
110
110
  | filterOnClose | `boolean` | 关闭筛选面板时是否自动应用筛选 | `true` |
111
111
  | icon | `(filtered: boolean) => React.ReactNode` | 自定义筛选图标 | - |
112
- | render | `() => React.ReactNode` | 自定义筛选面板内容 | - |
112
+ | render | `(ctx: { close: () => void }) => React.ReactNode` | 自定义筛选面板内容;`ctx.close()` 关闭筛选弹层 | - |
113
113
  | onFilter | `(value: FilterValue, record: object) => boolean` | 本地过滤函数;不配置时使用默认的字符串包含匹配 | - |
114
114
  | filtered | `boolean` | 强制筛选图标高亮(优先级高于由 `filteredValue` 派生的高亮) | - |
115
115
  | filteredValue | `FilterValue \| FilterValue[]` | (受控)筛选值。配置后该列筛选状态完全受控:面板回显、图标高亮、`onChange` 的 `filters` 均以其为准;重置传 `''` / `[]` | - |
@@ -234,7 +234,7 @@ export interface ColumnProps {
234
234
  /**
235
235
  * Custom filter function, e.g. custom search
236
236
  */
237
- render?: () => React.ReactNode;
237
+ render?: (ctx: { close: () => void }) => React.ReactNode;
238
238
  /**
239
239
  * Filter callback function
240
240
  */
@@ -149,7 +149,7 @@ const HeaderFilter = React.memo((props: any) => {
149
149
  ) : null;
150
150
 
151
151
  if (render) {
152
- popup = render();
152
+ popup = render({ close: () => setOpen(false) });
153
153
  } else if (items) {
154
154
  let dataSource = [];
155
155
  const inputValue = getStrLower(searchValue);
package/src/version.ts CHANGED
@@ -4,7 +4,7 @@ declare global {
4
4
  }
5
5
  }
6
6
 
7
- export const version = "0.15.0";
7
+ export const version = "0.15.2";
8
8
 
9
9
  if (typeof window !== 'undefined') {
10
10
  window.__yee_c_version__ = version;