knight-ui 1.0.3 → 1.0.5
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/README.md +115 -14
- package/component/feedback/Popconfirm.d.ts +1 -1
- package/component/input/Form.d.ts +22 -0
- package/component/input/Input.d.ts +7 -3
- package/component/input/index.d.ts +1 -1
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -423,19 +423,26 @@ import { Resizable } from "knight-ui";
|
|
|
423
423
|
```tsx
|
|
424
424
|
import { Input } from "knight-ui";
|
|
425
425
|
|
|
426
|
+
// 非受控(浏览器原生管理输入,IME 无干扰)
|
|
426
427
|
<Input placeholder="请输入" onChange={(v) => console.log(v)} />
|
|
427
428
|
<Input showClear defaultValue="可清除" />
|
|
429
|
+
|
|
430
|
+
// 受控(通过 value 管理显示值,Form.Field 自动使用此模式)
|
|
431
|
+
<Input value={text} onChange={(v) => setText(v)} placeholder="受控输入" />
|
|
432
|
+
|
|
428
433
|
<Input prefix={<IconSearch />} placeholder="搜索" />
|
|
429
434
|
<Input addonBefore="https://" addonAfter=".com" placeholder="域名" />
|
|
430
435
|
<Input type="password" placeholder="密码" />
|
|
431
436
|
<Input size="large" placeholder="大尺寸" />
|
|
432
437
|
|
|
433
|
-
//
|
|
438
|
+
// 多行文本(同样支持 value / defaultValue)
|
|
434
439
|
<Input.TextArea rows={4} placeholder="多行文本" onChange={(v) => console.log(v)} />
|
|
435
440
|
```
|
|
436
441
|
|
|
437
442
|
| 属性 | 类型 | 默认值 | 说明 |
|
|
438
443
|
|---|---|---|---|
|
|
444
|
+
| `value` | `string` | — | 受控值(提供后组件变为受控模式) |
|
|
445
|
+
| `defaultValue` | `string` | — | 非受控默认值 |
|
|
439
446
|
| `type` | `"text" \| "password"` | `"text"` | 输入类型 |
|
|
440
447
|
| `placeholder` | `string` | — | 占位符 |
|
|
441
448
|
| `size` | `"small" \| "default" \| "large"` | `"default"` | 尺寸 |
|
|
@@ -838,33 +845,81 @@ import { PinCode } from "knight-ui";
|
|
|
838
845
|
```tsx
|
|
839
846
|
import { Form, Input, Button } from "knight-ui";
|
|
840
847
|
|
|
848
|
+
// 基础用法
|
|
841
849
|
<Form
|
|
842
850
|
layout="horizontal"
|
|
843
851
|
labelWidth={100}
|
|
844
852
|
onSubmit={(values) => console.log(values)}
|
|
845
|
-
onSubmitFail={(
|
|
853
|
+
onSubmitFail={(values) => console.log(values)}
|
|
846
854
|
getFormApi={(api) => (window.formApi = api)}
|
|
847
855
|
>
|
|
848
856
|
<Form.Field field="name" label="姓名" rules={[{ required: true, message: "请输入姓名" }]}>
|
|
849
857
|
<Input placeholder="请输入姓名" />
|
|
850
858
|
</Form.Field>
|
|
851
|
-
<Form.Field field="email" label="邮箱"
|
|
859
|
+
<Form.Field field="email" label="邮箱"
|
|
860
|
+
rules={[{ required: true, message: "请输入邮箱" }, { pattern: /^\S+@\S+$/, message: "邮箱格式不正确" }]}>
|
|
852
861
|
<Input placeholder="请输入邮箱" />
|
|
853
862
|
</Form.Field>
|
|
854
863
|
<Button type="primary" htmlType="submit">提交</Button>
|
|
855
864
|
</Form>
|
|
865
|
+
|
|
866
|
+
// 动态字段(通过 FormApi 控制)
|
|
867
|
+
const formApiRef = useRef<FormApi>(null);
|
|
868
|
+
<Form getFormApi={(api) => (formApiRef.current = api)}>
|
|
869
|
+
<Form.Field field="name" label="名称"><Input /></Form.Field>
|
|
870
|
+
</Form>
|
|
871
|
+
|
|
872
|
+
// 动态添加/移除字段
|
|
873
|
+
formApiRef.current?.addField("dynamic_key", { label: "动态字段", value: "默认值" });
|
|
874
|
+
formApiRef.current?.removeField("dynamic_key");
|
|
875
|
+
|
|
876
|
+
// 程序化读写
|
|
877
|
+
formApiRef.current?.setFieldValue("name", "新值");
|
|
878
|
+
formApiRef.current?.setFieldsValue({ name: "A", email: "B" });
|
|
879
|
+
const allValues = formApiRef.current?.getValues();
|
|
880
|
+
const singleValue = formApiRef.current?.getFieldValue("name");
|
|
881
|
+
|
|
882
|
+
// 手动校验
|
|
883
|
+
const validValues = await formApiRef.current?.validate(); // 通过返回 values,失败返回 null
|
|
884
|
+
formApiRef.current?.reset(); // 重置所有字段
|
|
856
885
|
```
|
|
857
886
|
|
|
858
887
|
| 属性 | 类型 | 默认值 | 说明 |
|
|
859
888
|
|---|---|---|---|
|
|
860
|
-
| `layout` | `"horizontal" \| "vertical"` | `"
|
|
861
|
-
| `labelPosition` | `"left" \| "top"` | `"
|
|
862
|
-
| `
|
|
889
|
+
| `layout` | `"horizontal" \| "vertical"` | `"vertical"` | 布局 |
|
|
890
|
+
| `labelPosition` | `"left" \| "top"` | `"top"` | 标签位置 |
|
|
891
|
+
| `labelAlign` | `"left" \| "right" \| "center"` | `"left"` | 标签对齐 |
|
|
892
|
+
| `labelWidth` | `number` | `80` | 标签宽度 |
|
|
863
893
|
| `getFormApi` | `(api: FormApi) => void` | — | 获取表单 API |
|
|
864
|
-
| `onSubmit` | `(values) => void` | — |
|
|
894
|
+
| `onSubmit` | `(values) => void` | — | 校验通过后回调 |
|
|
865
895
|
| `onSubmitFail` | `(values) => void` | — | 校验失败回调 |
|
|
866
896
|
|
|
867
|
-
**
|
|
897
|
+
**FormApi 方法**:
|
|
898
|
+
|
|
899
|
+
| 方法 | 说明 |
|
|
900
|
+
|---|---|
|
|
901
|
+
| `getValues()` | 获取所有字段值 |
|
|
902
|
+
| `setValues(values)` | 批量设置字段值(合并) |
|
|
903
|
+
| `getFieldValue(field)` | 获取单个字段值 |
|
|
904
|
+
| `setFieldValue(field, value)` | 设置单个字段值 |
|
|
905
|
+
| `setFieldsValue(values)` | 批量设置(仅更新已注册字段) |
|
|
906
|
+
| `addField(field, meta?)` | 动态添加字段(已存在则更新) |
|
|
907
|
+
| `removeField(field)` | 动态移除字段 |
|
|
908
|
+
| `validate()` | 手动校验,通过返回 values,失败返回 null |
|
|
909
|
+
| `reset()` | 重置所有字段值为空 |
|
|
910
|
+
| `setError(field, error)` | 设置字段错误信息 |
|
|
911
|
+
|
|
912
|
+
**Form.Field**:`field`、`label`、`rules?: FormRule[]`、`value?: any`
|
|
913
|
+
|
|
914
|
+
**FormRule**:
|
|
915
|
+
| 属性 | 类型 | 说明 |
|
|
916
|
+
|---|---|---|
|
|
917
|
+
| `required` | `boolean` | 必填 |
|
|
918
|
+
| `message` | `string` | 错误提示 |
|
|
919
|
+
| `min / max` | `number` | 数值范围 |
|
|
920
|
+
| `minLength / maxLength` | `number` | 字符长度范围 |
|
|
921
|
+
| `pattern` | `RegExp` | 正则校验 |
|
|
922
|
+
| `validator` | `(value, values) => string \| null \| Promise<string \| null>` | 自定义校验 |
|
|
868
923
|
|
|
869
924
|
---
|
|
870
925
|
|
|
@@ -874,29 +929,44 @@ import { Form, Input, Button } from "knight-ui";
|
|
|
874
929
|
|
|
875
930
|
```tsx
|
|
876
931
|
import { Navigation } from "knight-ui";
|
|
932
|
+
import { IconStar, IconInfoCircle, IconSetting } from "knight-ui";
|
|
877
933
|
|
|
878
934
|
const items = [
|
|
879
|
-
{ key: "home", label: "首页" },
|
|
935
|
+
{ key: "home", label: "首页", icon: <IconStar size="extraSmall" /> },
|
|
880
936
|
{
|
|
881
|
-
key: "docs", label: "文档",
|
|
937
|
+
key: "docs", label: "文档", icon: <IconInfoCircle size="extraSmall" />,
|
|
882
938
|
children: [
|
|
883
939
|
{ key: "guide", label: "快速开始" },
|
|
884
940
|
{ key: "api", label: "API 参考" },
|
|
885
941
|
],
|
|
886
942
|
},
|
|
887
|
-
{ key: "about", label: "关于" },
|
|
943
|
+
{ key: "about", label: "关于", icon: <IconSetting size="extraSmall" /> },
|
|
888
944
|
];
|
|
889
945
|
|
|
890
|
-
|
|
946
|
+
// 垂直模式 + 折叠切换
|
|
947
|
+
const [collapsed, setCollapsed] = useState(false);
|
|
948
|
+
<Navigation items={items} mode="vertical" isCollapsed={collapsed} onCollapseChange={setCollapsed}
|
|
949
|
+
defaultSelectedKeys={["home"]} onSelect={(k) => console.log(k)} />
|
|
950
|
+
|
|
951
|
+
// 水平模式
|
|
891
952
|
<Navigation items={items} mode="horizontal" trigger="click" />
|
|
892
953
|
```
|
|
893
954
|
|
|
955
|
+
**NavItem**:`key`、`label`、`icon?: React.ReactNode`、`disabled?: boolean`、`children?: NavItem[]`
|
|
956
|
+
|
|
894
957
|
| 属性 | 类型 | 默认值 | 说明 |
|
|
895
958
|
|---|---|---|---|
|
|
896
959
|
| `items` | `NavItem[]` | — | 菜单项 |
|
|
897
960
|
| `mode` | `"horizontal" \| "vertical"` | `"vertical"` | 排列模式 |
|
|
898
961
|
| `trigger` | `"hover" \| "click"` | `"hover"` | 子菜单触发方式 |
|
|
962
|
+
| `isCollapsed` | `boolean` | — | 折叠状态(受控) |
|
|
963
|
+
| `defaultIsCollapsed` | `boolean` | `false` | 默认折叠状态 |
|
|
964
|
+
| `onCollapseChange` | `(isCollapsed: boolean) => void` | — | 折叠切换回调 |
|
|
965
|
+
| `selectedKeys / defaultSelectedKeys` | `string[]` | — | 当前选中 |
|
|
966
|
+
| `openKeys / defaultOpenKeys` | `string[]` | — | 当前展开的子菜单 |
|
|
967
|
+
| `multiple` | `boolean` | `false` | 是否多选 |
|
|
899
968
|
| `onSelect` | `(key: string) => void` | — | 选中回调 |
|
|
969
|
+
| `onOpenChange` | `(openKeys: string[]) => void` | — | 展开变化回调 |
|
|
900
970
|
|
|
901
971
|
### Tabs 标签页
|
|
902
972
|
|
|
@@ -1471,25 +1541,56 @@ import { Tooltip, Button } from "knight-ui";
|
|
|
1471
1541
|
|
|
1472
1542
|
```tsx
|
|
1473
1543
|
import { Popconfirm, Button } from "knight-ui";
|
|
1544
|
+
import { IconAlertTriangle } from "knight-ui";
|
|
1474
1545
|
|
|
1546
|
+
// 基础用法 (默认 position="bottom", trigger="click")
|
|
1475
1547
|
<Popconfirm
|
|
1476
1548
|
title="确定删除?"
|
|
1477
1549
|
content="删除后不可恢复"
|
|
1478
|
-
trigger="click"
|
|
1479
1550
|
onConfirm={() => console.log("confirmed")}
|
|
1480
1551
|
onCancel={() => console.log("cancelled")}
|
|
1481
1552
|
>
|
|
1482
1553
|
<Button type="danger">删除</Button>
|
|
1483
1554
|
</Popconfirm>
|
|
1555
|
+
|
|
1556
|
+
// 自定义按钮文字 + 图标
|
|
1557
|
+
<Popconfirm title="确定保存?" content="保存后覆盖原有数据"
|
|
1558
|
+
icon={<IconAlertTriangle size="extraLarge" color="var(--ku-color-warning)" />}
|
|
1559
|
+
okText="保存" cancelText="取消"
|
|
1560
|
+
onConfirm={() => console.log("saved")}>
|
|
1561
|
+
<Button type="warning">保存</Button>
|
|
1562
|
+
</Popconfirm>
|
|
1563
|
+
|
|
1564
|
+
// 8 方向弹出 (position)
|
|
1565
|
+
<Popconfirm title="确认?" position="leftTop" onConfirm={() => {}}>
|
|
1566
|
+
<Button>左上弹出</Button>
|
|
1567
|
+
</Popconfirm>
|
|
1568
|
+
<Popconfirm title="确认?" position="rightBottom" onConfirm={() => {}}>
|
|
1569
|
+
<Button>右下弹出</Button>
|
|
1570
|
+
</Popconfirm>
|
|
1571
|
+
|
|
1572
|
+
// hover 触发 + 带箭头
|
|
1573
|
+
<Popconfirm title="提示" content="悬停即可查看" trigger="hover" showArrow position="top"
|
|
1574
|
+
onConfirm={() => {}}>
|
|
1575
|
+
<Button type="secondary">悬停触发</Button>
|
|
1576
|
+
</Popconfirm>
|
|
1484
1577
|
```
|
|
1485
1578
|
|
|
1486
1579
|
| 属性 | 类型 | 默认值 | 说明 |
|
|
1487
1580
|
|---|---|---|---|
|
|
1488
1581
|
| `title` | `React.ReactNode` | — | 标题 |
|
|
1489
1582
|
| `content` | `React.ReactNode` | — | 内容 |
|
|
1490
|
-
| `
|
|
1583
|
+
| `position` | `"top" \| "bottom" \| "left" \| "right" \| "leftTop" \| "rightTop" \| "leftBottom" \| "rightBottom"` | `"bottom"` | 弹出位置(命名规则: 第一个词=左右, 第二个词=上下) |
|
|
1584
|
+
| `trigger` | `"click" \| "hover" \| "focus" \| "custom"` | `"click"` | 触发方式 |
|
|
1585
|
+
| `icon` | `React.ReactNode` | — | 自定义图标 |
|
|
1586
|
+
| `showArrow` | `boolean` | `false` | 显示箭头 |
|
|
1587
|
+
| `okText / cancelText` | `string` | `"确认" / "取消"` | 按钮文字 |
|
|
1588
|
+
| `okButtonProps / cancelButtonProps` | `ButtonHTMLAttributes` | — | 按钮额外属性 |
|
|
1589
|
+
| `visible / defaultVisible` | `boolean` | — | 受控/非受控显示 |
|
|
1590
|
+
| `offset` | `number` | `4` | 弹出偏移距离 |
|
|
1491
1591
|
| `onConfirm` | `(e) => void` | — | 确认回调 |
|
|
1492
1592
|
| `onCancel` | `(e) => void` | — | 取消回调 |
|
|
1593
|
+
| `onVisibleChange` | `(visible: boolean) => void` | — | 显示状态变化回调 |
|
|
1493
1594
|
|
|
1494
1595
|
### Calendar 日历
|
|
1495
1596
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { AbstractUI, type UIProps, type UIState } from "../../base";
|
|
3
|
-
type PopconfirmPosition = "top" | "
|
|
3
|
+
type PopconfirmPosition = "top" | "bottom" | "left" | "right" | "leftTop" | "rightTop" | "leftBottom" | "rightBottom";
|
|
4
4
|
type PopconfirmTrigger = "click" | "hover" | "focus" | "custom";
|
|
5
5
|
/**
|
|
6
6
|
* 气泡确认框。
|
|
@@ -28,6 +28,7 @@ interface FormContextValue {
|
|
|
28
28
|
labelWidth: number;
|
|
29
29
|
disabled: boolean;
|
|
30
30
|
validating: boolean;
|
|
31
|
+
formKey: number;
|
|
31
32
|
}
|
|
32
33
|
declare class FormField extends AbstractUI<FormFieldProps, FormFieldState> {
|
|
33
34
|
static displayName: string;
|
|
@@ -55,6 +56,20 @@ export interface FormApi {
|
|
|
55
56
|
validate: () => Promise<Record<string, any> | null>;
|
|
56
57
|
reset: () => void;
|
|
57
58
|
setError: (field: string, error: string | null) => void;
|
|
59
|
+
/** 动态添加字段(若已存在则更新) */
|
|
60
|
+
addField: (field: string, meta?: {
|
|
61
|
+
label?: React.ReactNode;
|
|
62
|
+
rules?: FormRule[];
|
|
63
|
+
value?: any;
|
|
64
|
+
}) => void;
|
|
65
|
+
/** 动态移除字段 */
|
|
66
|
+
removeField: (field: string) => void;
|
|
67
|
+
/** 获取单个字段值 */
|
|
68
|
+
getFieldValue: (field: string) => any;
|
|
69
|
+
/** 设置单个字段值 */
|
|
70
|
+
setFieldValue: (field: string, value: any) => void;
|
|
71
|
+
/** 批量设置字段值(合并, 仅更新已注册字段) */
|
|
72
|
+
setFieldsValue: (values: Record<string, any>) => void;
|
|
58
73
|
}
|
|
59
74
|
/**
|
|
60
75
|
* 表单。
|
|
@@ -69,7 +84,13 @@ export declare class Form extends AbstractUI<FormProps, FormState> {
|
|
|
69
84
|
private registerField;
|
|
70
85
|
private updateField;
|
|
71
86
|
private getValues;
|
|
87
|
+
private bumpFormKey;
|
|
72
88
|
private setValues;
|
|
89
|
+
private addField;
|
|
90
|
+
private removeField;
|
|
91
|
+
private getFieldValue;
|
|
92
|
+
private setFieldValue;
|
|
93
|
+
private setFieldsValue;
|
|
73
94
|
private validate;
|
|
74
95
|
private reset;
|
|
75
96
|
private setError;
|
|
@@ -93,5 +114,6 @@ export interface FormProps extends UIProps {
|
|
|
93
114
|
}
|
|
94
115
|
interface FormState extends UIState {
|
|
95
116
|
validating: boolean;
|
|
117
|
+
formKey: number;
|
|
96
118
|
}
|
|
97
119
|
export {};
|
|
@@ -4,11 +4,13 @@ import type { ValidateStatus } from "../types";
|
|
|
4
4
|
declare class TextArea extends AbstractUI<TextAreaProps, TextAreaState> {
|
|
5
5
|
static displayName: string;
|
|
6
6
|
private textareaRef;
|
|
7
|
+
private _isComposing;
|
|
7
8
|
constructor(props: TextAreaProps);
|
|
8
9
|
focus(): void;
|
|
9
10
|
protected OnRenderContent(): React.ReactElement;
|
|
10
11
|
}
|
|
11
12
|
export interface TextAreaProps extends UIProps {
|
|
13
|
+
value?: string;
|
|
12
14
|
defaultValue?: string;
|
|
13
15
|
placeholder?: string;
|
|
14
16
|
maxLength?: number;
|
|
@@ -18,15 +20,17 @@ export interface TextAreaProps extends UIProps {
|
|
|
18
20
|
onChange?: (value: string, event?: React.ChangeEvent<HTMLTextAreaElement>) => void;
|
|
19
21
|
}
|
|
20
22
|
interface TextAreaState extends UIState {
|
|
21
|
-
value: string;
|
|
22
23
|
focused: boolean;
|
|
23
24
|
}
|
|
24
25
|
/**
|
|
25
|
-
*
|
|
26
|
+
* 输入框。
|
|
27
|
+
* - 受控模式: 传入 value,值完全由父组件控制
|
|
28
|
+
* - 非受控模式: 传入 defaultValue,浏览器原生管理输入内容,IME 无干扰
|
|
26
29
|
*/
|
|
27
30
|
export declare class Input extends AbstractUI<InputProps, InputState> {
|
|
28
31
|
static TextArea: typeof TextArea;
|
|
29
32
|
private inputRef;
|
|
33
|
+
private _isComposing;
|
|
30
34
|
constructor(props: InputProps);
|
|
31
35
|
focus(): void;
|
|
32
36
|
blur(): void;
|
|
@@ -34,6 +38,7 @@ export declare class Input extends AbstractUI<InputProps, InputState> {
|
|
|
34
38
|
}
|
|
35
39
|
export interface InputProps extends UIProps {
|
|
36
40
|
type?: "text" | "password";
|
|
41
|
+
value?: string;
|
|
37
42
|
defaultValue?: string;
|
|
38
43
|
placeholder?: string;
|
|
39
44
|
size?: "small" | "default" | "large";
|
|
@@ -49,7 +54,6 @@ export interface InputProps extends UIProps {
|
|
|
49
54
|
onChange?: (value: string, event?: React.ChangeEvent<HTMLInputElement>) => void;
|
|
50
55
|
}
|
|
51
56
|
interface InputState extends UIState {
|
|
52
|
-
value: string;
|
|
53
57
|
showPassword: boolean;
|
|
54
58
|
focused: boolean;
|
|
55
59
|
}
|
|
@@ -9,7 +9,7 @@ export type { ColorPickerProps, ColorValue } from "./ColorPicker";
|
|
|
9
9
|
export { DatePicker } from "./DatePicker";
|
|
10
10
|
export type { DatePickerProps } from "./DatePicker";
|
|
11
11
|
export { Form } from "./Form";
|
|
12
|
-
export type { FormProps } from "./Form";
|
|
12
|
+
export type { FormProps, FormApi, FormRule } from "./Form";
|
|
13
13
|
export { KeyValueEditor } from "./KeyValueEditor";
|
|
14
14
|
export type { KeyValueEditorProps, KeyValueRow } from "./KeyValueEditor";
|
|
15
15
|
export { Input } from "./Input";
|