@baishuyun/ai-design 2.0.15 → 2.0.17
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/CHANGELOG.md +18 -0
- package/dist/ai-design.js +3253 -3213
- package/dist/ai-design.js.map +1 -1
- package/dist/ai-design.umd.cjs +29 -29
- package/dist/ai-design.umd.cjs.map +1 -1
- package/dist/src/components/agent-helper/app-select/index.d.ts +5 -1
- package/dist/src/components/agent-helper/app-select/index.d.ts.map +1 -1
- package/dist/src/components/agent-helper/field-select/index.d.ts +3 -2
- package/dist/src/components/agent-helper/field-select/index.d.ts.map +1 -1
- package/dist/src/components/agent-helper/form-select/index.d.ts +4 -0
- package/dist/src/components/agent-helper/form-select/index.d.ts.map +1 -1
- package/dist/src/stories/AppSelect.stories.d.ts +3 -0
- package/dist/src/stories/AppSelect.stories.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/components/agent-helper/app-select/index.tsx +26 -1
- package/src/components/agent-helper/field-select/index.tsx +1 -1
- package/src/components/agent-helper/form-select/index.tsx +38 -3
- package/src/components/agent-helper/trigger-time-preference-select/index.tsx +1 -1
- package/src/stories/AppSelect.stories.tsx +13 -0
- package/src/stories/FormSelect.stories.tsx +16 -1
|
@@ -33,7 +33,11 @@ export interface AppSelectProps {
|
|
|
33
33
|
className?: string;
|
|
34
34
|
/** Show a "全部应用" (All Apps) item at the top. Only effective in single mode. */
|
|
35
35
|
showAll?: boolean;
|
|
36
|
+
/** Allow selecting an empty value as the first option. Only effective in single mode. */
|
|
37
|
+
allowEmpty?: boolean;
|
|
38
|
+
/** Label for the empty option. Default "无". */
|
|
39
|
+
emptyLabel?: string;
|
|
36
40
|
popoverContentOnly?: boolean;
|
|
37
41
|
}
|
|
38
|
-
export declare const AppSelect: ({ nodes, mode, popoverContentOnly, showAll, value: controlledValue, defaultValue, onChange, placeholder, searchPlaceholder, disabled, maxVisibleChips, className, }: AppSelectProps) => import("react").JSX.Element;
|
|
42
|
+
export declare const AppSelect: ({ nodes, mode, popoverContentOnly, showAll, allowEmpty, emptyLabel, value: controlledValue, defaultValue, onChange, placeholder, searchPlaceholder, disabled, maxVisibleChips, className, }: AppSelectProps) => import("react").JSX.Element;
|
|
39
43
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/agent-helper/app-select/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMjE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAID,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,WAAW,EAAE,CAavE;AAyED,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,MAAM,WAAW,cAAc;IAC7B,+EAA+E;IAC/E,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,qBAAqB;IACrB,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACjC,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9C,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAmBD,eAAO,MAAM,SAAS,GAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/agent-helper/app-select/index.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMjE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAID,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,WAAW,EAAE,CAavE;AAyED,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,MAAM,WAAW,cAAc;IAC7B,+EAA+E;IAC/E,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,qBAAqB;IACrB,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACjC,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9C,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yFAAyF;IACzF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAmBD,eAAO,MAAM,SAAS,GAAI,6LAevB,cAAc,gCAiYhB,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JSX } from 'react';
|
|
1
2
|
import { IField } from '@baishuyun/types';
|
|
2
3
|
export interface FieldSelectPopoverProps {
|
|
3
4
|
fields: IField[];
|
|
@@ -8,7 +9,7 @@ export interface FieldSelectPopoverProps {
|
|
|
8
9
|
width?: number;
|
|
9
10
|
className?: string;
|
|
10
11
|
}
|
|
11
|
-
export declare const FieldSelectPopover: ({ fields, selectedKey, onSelect, searchPlaceholder, showTypeBadge, width, className, }: FieldSelectPopoverProps) =>
|
|
12
|
+
export declare const FieldSelectPopover: ({ fields, selectedKey, onSelect, searchPlaceholder, showTypeBadge, width, className, }: FieldSelectPopoverProps) => JSX.Element;
|
|
12
13
|
export interface FieldSelectProps {
|
|
13
14
|
fields: IField[];
|
|
14
15
|
value?: string;
|
|
@@ -20,5 +21,5 @@ export interface FieldSelectProps {
|
|
|
20
21
|
showTypeBadge?: boolean;
|
|
21
22
|
className?: string;
|
|
22
23
|
}
|
|
23
|
-
export declare const FieldSelect: ({ fields, value: controlledValue, defaultValue, onChange, placeholder, searchPlaceholder, disabled, showTypeBadge, className, }: FieldSelectProps) =>
|
|
24
|
+
export declare const FieldSelect: ({ fields, value: controlledValue, defaultValue, onChange, placeholder, searchPlaceholder, disabled, showTypeBadge, className, }: FieldSelectProps) => JSX.Element;
|
|
24
25
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/agent-helper/field-select/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/agent-helper/field-select/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0C,GAAG,EAAE,MAAM,OAAO,CAAC;AAIpE,OAAO,KAAK,EAAE,MAAM,EAA4B,MAAM,kBAAkB,CAAC;AAmJzE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,kBAAkB,GAAI,wFAQhC,uBAAuB,gBAwIzB,CAAC;AAmCF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,WAAW,GAAI,iIAUzB,gBAAgB,gBAoGlB,CAAC"}
|
|
@@ -17,6 +17,10 @@ export interface FormSelectProps {
|
|
|
17
17
|
placeholder?: string;
|
|
18
18
|
disabled?: boolean;
|
|
19
19
|
className?: string;
|
|
20
|
+
/** Allow selecting an empty value as the first option. */
|
|
21
|
+
allowEmpty?: boolean;
|
|
22
|
+
/** Label for the empty option. Default "无". */
|
|
23
|
+
emptyLabel?: string;
|
|
20
24
|
}
|
|
21
25
|
export declare const FormSelect: import('react').ForwardRefExoticComponent<FormSelectProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
22
26
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/agent-helper/form-select/index.tsx"],"names":[],"mappings":"AAuBA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,cAAc,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/agent-helper/form-select/index.tsx"],"names":[],"mappings":"AAuBA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,cAAc,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAmSD,eAAO,MAAM,UAAU,4GAqQtB,CAAC"}
|
|
@@ -5,6 +5,9 @@ export default meta;
|
|
|
5
5
|
type Story = StoryObj<typeof meta>;
|
|
6
6
|
export declare const Default: Story;
|
|
7
7
|
export declare const SingleSelected: Story;
|
|
8
|
+
export declare const AllowEmpty: Story;
|
|
9
|
+
export declare const AllowEmptyCustomLabel: Story;
|
|
10
|
+
export declare const AllowEmptyWithShowAll: Story;
|
|
8
11
|
export declare const MultiSelect: Story;
|
|
9
12
|
export declare const MultiSelectOverflow: Story;
|
|
10
13
|
export declare const EmptyGroups: Story;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppSelect.stories.d.ts","sourceRoot":"","sources":["../../../src/stories/AppSelect.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAwB,MAAM,uCAAuC,CAAC;AAmGxF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,SAAS,CAiBhC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAInC,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,KAMjC,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAM3B,CAAC;AAIF,eAAO,MAAM,aAAa,EAAE,KAM3B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KAO/B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAQ7B,CAAC;AAIF,eAAO,MAAM,WAAW,EAAE,KA2CzB,CAAC"}
|
|
1
|
+
{"version":3,"file":"AppSelect.stories.d.ts","sourceRoot":"","sources":["../../../src/stories/AppSelect.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAwB,MAAM,uCAAuC,CAAC;AAmGxF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,SAAS,CAiBhC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAInC,eAAO,MAAM,OAAO,EAAE,KAAU,CAAC;AAEjC,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,KAEnC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,KAGnC,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,KAMjC,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAM3B,CAAC;AAIF,eAAO,MAAM,aAAa,EAAE,KAM3B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KAO/B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAQ7B,CAAC;AAIF,eAAO,MAAM,WAAW,EAAE,KA2CzB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baishuyun/ai-design",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.17",
|
|
4
4
|
"description": "AI 功能 UI 组件库 - 所有 AI 功能的 UI 表现唯一真相来源",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"tw-animate-css": "^1.4.0",
|
|
61
61
|
"vaul": "^1.1.2",
|
|
62
62
|
"zod": "^4.1.13",
|
|
63
|
-
"@baishuyun/ai-feat-utils": "2.0.
|
|
64
|
-
"@baishuyun/types": "3.0.
|
|
63
|
+
"@baishuyun/ai-feat-utils": "2.0.17",
|
|
64
|
+
"@baishuyun/types": "3.0.17"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"react": "^19.0.0",
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"vite": "^5.1.4",
|
|
85
85
|
"vite-plugin-dts": "^4.5.4",
|
|
86
86
|
"@baishuyun/tailwind-config": "3.0.9",
|
|
87
|
-
"@baishuyun/
|
|
88
|
-
"@baishuyun/
|
|
87
|
+
"@baishuyun/typescript-config": "2.0.9",
|
|
88
|
+
"@baishuyun/types": "3.0.17"
|
|
89
89
|
},
|
|
90
90
|
"keywords": [],
|
|
91
91
|
"author": "",
|
|
@@ -132,6 +132,10 @@ export interface AppSelectProps {
|
|
|
132
132
|
className?: string;
|
|
133
133
|
/** Show a "全部应用" (All Apps) item at the top. Only effective in single mode. */
|
|
134
134
|
showAll?: boolean;
|
|
135
|
+
/** Allow selecting an empty value as the first option. Only effective in single mode. */
|
|
136
|
+
allowEmpty?: boolean;
|
|
137
|
+
/** Label for the empty option. Default "无". */
|
|
138
|
+
emptyLabel?: string;
|
|
135
139
|
popoverContentOnly?: boolean; // for testing: render only the popover content without the trigger
|
|
136
140
|
}
|
|
137
141
|
|
|
@@ -157,6 +161,8 @@ export const AppSelect = ({
|
|
|
157
161
|
mode = 'single',
|
|
158
162
|
popoverContentOnly,
|
|
159
163
|
showAll = false,
|
|
164
|
+
allowEmpty = false,
|
|
165
|
+
emptyLabel = '无',
|
|
160
166
|
value: controlledValue,
|
|
161
167
|
defaultValue,
|
|
162
168
|
onChange,
|
|
@@ -410,6 +416,25 @@ export const AppSelect = ({
|
|
|
410
416
|
/>
|
|
411
417
|
</div>
|
|
412
418
|
|
|
419
|
+
{/* Empty option */}
|
|
420
|
+
{allowEmpty && mode === 'single' && !searchQuery.trim() && (
|
|
421
|
+
<button
|
|
422
|
+
type="button"
|
|
423
|
+
onClick={() => {
|
|
424
|
+
updateValue('');
|
|
425
|
+
setOpen(false);
|
|
426
|
+
}}
|
|
427
|
+
className={cn(
|
|
428
|
+
'flex items-center w-full h-[34px] rounded-[4px] text-left',
|
|
429
|
+
'px-[10px]',
|
|
430
|
+
transCls,
|
|
431
|
+
'text-[#030303] hover:bg-[#EFF0F6]'
|
|
432
|
+
)}
|
|
433
|
+
>
|
|
434
|
+
<span className="text-[14px] leading-[normal]">{emptyLabel}</span>
|
|
435
|
+
</button>
|
|
436
|
+
)}
|
|
437
|
+
|
|
413
438
|
{/* "全部应用" item */}
|
|
414
439
|
{showAll && mode === 'single' && !searchQuery.trim() && (
|
|
415
440
|
<button
|
|
@@ -512,7 +537,7 @@ export const AppSelect = ({
|
|
|
512
537
|
selectedAppLabel ? 'text-[#030303]' : 'text-[#999999]'
|
|
513
538
|
)}
|
|
514
539
|
>
|
|
515
|
-
{selectedAppLabel ?? placeholder}
|
|
540
|
+
{selectedAppLabel ?? (allowEmpty ? emptyLabel : placeholder)}
|
|
516
541
|
</span>
|
|
517
542
|
<DropdownChevron open={open} />
|
|
518
543
|
</>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useCallback, useMemo, useRef } from 'react';
|
|
1
|
+
import { useState, useCallback, useMemo, useRef, JSX } from 'react';
|
|
2
2
|
import { cn } from '../../../lib/utils';
|
|
3
3
|
import { transCls } from '../../../const/ui';
|
|
4
4
|
import { Popover, PopoverTrigger, PopoverContent } from '../../ui/popover';
|
|
@@ -31,7 +31,7 @@ export interface FormSelectItem {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export interface FormSelectChangeResult {
|
|
34
|
-
form
|
|
34
|
+
form?: FormSelectItem;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export interface FormSelectProps {
|
|
@@ -42,6 +42,10 @@ export interface FormSelectProps {
|
|
|
42
42
|
placeholder?: string;
|
|
43
43
|
disabled?: boolean;
|
|
44
44
|
className?: string;
|
|
45
|
+
/** Allow selecting an empty value as the first option. */
|
|
46
|
+
allowEmpty?: boolean;
|
|
47
|
+
/** Label for the empty option. Default "无". */
|
|
48
|
+
emptyLabel?: string;
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
// ── Tree types ────────────────────────────────────────────────────
|
|
@@ -259,6 +263,9 @@ function FormPopover({
|
|
|
259
263
|
selectedFormId,
|
|
260
264
|
onSelect,
|
|
261
265
|
hasSearch,
|
|
266
|
+
allowEmpty,
|
|
267
|
+
emptyLabel,
|
|
268
|
+
onEmptySelect,
|
|
262
269
|
}: {
|
|
263
270
|
searchQuery: string;
|
|
264
271
|
onSearchChange: (v: string) => void;
|
|
@@ -266,6 +273,9 @@ function FormPopover({
|
|
|
266
273
|
selectedFormId: string | undefined;
|
|
267
274
|
onSelect: (result: FormSelectChangeResult) => void;
|
|
268
275
|
hasSearch: boolean;
|
|
276
|
+
allowEmpty: boolean;
|
|
277
|
+
emptyLabel: string;
|
|
278
|
+
onEmptySelect: () => void;
|
|
269
279
|
}) {
|
|
270
280
|
return (
|
|
271
281
|
<div
|
|
@@ -286,6 +296,20 @@ function FormPopover({
|
|
|
286
296
|
/>
|
|
287
297
|
</div>
|
|
288
298
|
|
|
299
|
+
{/* Empty option */}
|
|
300
|
+
{allowEmpty && !hasSearch && (
|
|
301
|
+
<div
|
|
302
|
+
className={cn(
|
|
303
|
+
'flex items-center h-[34px] px-[10px] cursor-pointer rounded-[4px] shrink-0',
|
|
304
|
+
!selectedFormId ? 'bg-[#F0F6FF] text-[#0265FF]' : 'text-[#030303] hover:bg-[#EFF0F6]',
|
|
305
|
+
transCls,
|
|
306
|
+
)}
|
|
307
|
+
onClick={onEmptySelect}
|
|
308
|
+
>
|
|
309
|
+
<span className="text-[14px] leading-[normal] truncate">{emptyLabel}</span>
|
|
310
|
+
</div>
|
|
311
|
+
)}
|
|
312
|
+
|
|
289
313
|
{/* Form list */}
|
|
290
314
|
<div className="flex flex-col gap-0 max-h-[400px] overflow-y-auto">
|
|
291
315
|
{tree.length > 0 ? (
|
|
@@ -323,6 +347,8 @@ export const FormSelect = forwardRef<HTMLDivElement, FormSelectProps>(
|
|
|
323
347
|
placeholder = '请选择表单',
|
|
324
348
|
disabled = false,
|
|
325
349
|
className,
|
|
350
|
+
allowEmpty = false,
|
|
351
|
+
emptyLabel = '无',
|
|
326
352
|
},
|
|
327
353
|
ref,
|
|
328
354
|
) => {
|
|
@@ -400,13 +426,19 @@ export const FormSelect = forwardRef<HTMLDivElement, FormSelectProps>(
|
|
|
400
426
|
|
|
401
427
|
const handleSelect = useCallback(
|
|
402
428
|
(result: FormSelectChangeResult) => {
|
|
403
|
-
setInternalValue(result.form
|
|
429
|
+
setInternalValue(result.form?.id || '');
|
|
404
430
|
onChange?.(result);
|
|
405
431
|
handleClose();
|
|
406
432
|
},
|
|
407
433
|
[onChange, handleClose],
|
|
408
434
|
);
|
|
409
435
|
|
|
436
|
+
const handleEmptySelect = useCallback(() => {
|
|
437
|
+
setInternalValue('');
|
|
438
|
+
onChange?.({});
|
|
439
|
+
handleClose();
|
|
440
|
+
}, [onChange, handleClose]);
|
|
441
|
+
|
|
410
442
|
// ── Event listeners ───────────────────────────────────────────
|
|
411
443
|
|
|
412
444
|
// Click-outside: close popover when clicking outside both the trigger and popover.
|
|
@@ -531,7 +563,7 @@ export const FormSelect = forwardRef<HTMLDivElement, FormSelectProps>(
|
|
|
531
563
|
</>
|
|
532
564
|
) : (
|
|
533
565
|
<span className="text-[14px] text-[#999999] leading-[normal] truncate">
|
|
534
|
-
{placeholder}
|
|
566
|
+
{allowEmpty ? emptyLabel : placeholder}
|
|
535
567
|
</span>
|
|
536
568
|
)}
|
|
537
569
|
</span>
|
|
@@ -557,6 +589,9 @@ export const FormSelect = forwardRef<HTMLDivElement, FormSelectProps>(
|
|
|
557
589
|
selectedFormId={selectedFormId}
|
|
558
590
|
onSelect={handleSelect}
|
|
559
591
|
hasSearch={hasSearch}
|
|
592
|
+
allowEmpty={allowEmpty}
|
|
593
|
+
emptyLabel={emptyLabel}
|
|
594
|
+
onEmptySelect={handleEmptySelect}
|
|
560
595
|
/>
|
|
561
596
|
</div>,
|
|
562
597
|
portalContainer || document.body,
|
|
@@ -92,7 +92,7 @@ export function TriggerTimePreferenceSelect({
|
|
|
92
92
|
const handleFormChange = useCallback(
|
|
93
93
|
(result: FormSelectChangeResult) => {
|
|
94
94
|
const payload = buildDateFieldPayload(
|
|
95
|
-
{ formId: result.form
|
|
95
|
+
{ formId: result.form?.id || '' },
|
|
96
96
|
dateFieldPayload,
|
|
97
97
|
);
|
|
98
98
|
onChange?.({ type: 'date_field', customTriggerTimePayload: payload });
|
|
@@ -129,6 +129,19 @@ export const SingleSelected: Story = {
|
|
|
129
129
|
args: { defaultValue: 'app2' },
|
|
130
130
|
};
|
|
131
131
|
|
|
132
|
+
export const AllowEmpty: Story = {
|
|
133
|
+
args: { allowEmpty: true },
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export const AllowEmptyCustomLabel: Story = {
|
|
137
|
+
args: { allowEmpty: true, emptyLabel: '不限' },
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const AllowEmptyWithShowAll: Story = {
|
|
141
|
+
name: 'Allow Empty + Show All',
|
|
142
|
+
args: { allowEmpty: true, showAll: true },
|
|
143
|
+
};
|
|
144
|
+
|
|
132
145
|
export const MultiSelect: Story = {
|
|
133
146
|
args: {
|
|
134
147
|
mode: 'multiple',
|
|
@@ -60,6 +60,21 @@ export const WithSelection: Story = {
|
|
|
60
60
|
},
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
+
export const AllowEmpty: Story = {
|
|
64
|
+
args: {
|
|
65
|
+
items: mockFormItems,
|
|
66
|
+
allowEmpty: true,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const AllowEmptyCustomLabel: Story = {
|
|
71
|
+
args: {
|
|
72
|
+
items: mockFormItems,
|
|
73
|
+
allowEmpty: true,
|
|
74
|
+
emptyLabel: '不限',
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
63
78
|
export const Disabled: Story = {
|
|
64
79
|
args: {
|
|
65
80
|
items: mockFormItems,
|
|
@@ -97,7 +112,7 @@ export const Interactive: Story = {
|
|
|
97
112
|
return (
|
|
98
113
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
|
99
114
|
<FormSelect {...args} onChange={setSelected} />
|
|
100
|
-
{selected && (
|
|
115
|
+
{selected?.form && (
|
|
101
116
|
<div
|
|
102
117
|
style={{
|
|
103
118
|
padding: 12,
|