@blueking/bk-user-selector 0.1.3 → 0.1.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 CHANGED
@@ -20,6 +20,8 @@
20
20
  | 👥 **用户组** | 支持用户组/角色分组显示 |
21
21
  | ✏️ **自定义输入** | 支持创建自定义用户和自由粘贴 |
22
22
  | 🎭 **自定义渲染** | 支持自定义标签和列表项渲染 |
23
+ | 📝 **多行输入** | 支持 textarea 模式,完整展示所有标签 |
24
+ | ⌨️ **键盘导航** | 支持上下键切换选项、Enter 快速选中 |
23
25
 
24
26
  ## 📦 安装
25
27
 
@@ -231,6 +233,37 @@ export default {
231
233
  </script>
232
234
  ```
233
235
 
236
+ ### 多行输入模式(Textarea)
237
+
238
+ 当需要展示大量已选用户时,可使用 textarea 模式完整展示所有标签:
239
+
240
+ ```vue
241
+ <template>
242
+ <BkUserSelector
243
+ v-model="selectedUsers"
244
+ :api-base-url="apiBaseUrl"
245
+ :tenant-id="tenantId"
246
+ :multiple="true"
247
+ type="textarea"
248
+ :rows="4"
249
+ :resize="true"
250
+ @change="handleChange"
251
+ />
252
+ </template>
253
+
254
+ <script setup>
255
+ import { ref } from 'vue';
256
+
257
+ const apiBaseUrl = ref('https://api.example.com');
258
+ const tenantId = ref('default');
259
+ const selectedUsers = ref([]);
260
+
261
+ const handleChange = users => {
262
+ console.log('Selected:', users);
263
+ };
264
+ </script>
265
+ ```
266
+
234
267
  ### 排除指定用户
235
268
 
236
269
  从下拉列表中排除特定用户:
@@ -265,7 +298,7 @@ export default {
265
298
  | --------------------- | --------------------------------- | ------------------------------------------------ | ---------------------- | ---- |
266
299
  | modelValue / v-model | 绑定值,单选为字符串,多选为数组 | `string` / `string[]` | `''` / `[]` | 是 |
267
300
  | apiBaseUrl | API 基础 URL | `string` | `''` | 是 |
268
- | tenantId | 租户 ID | `string` | `''` | |
301
+ | tenantId | 租户 ID | `string` | `'default'` | |
269
302
  | hasAvatar | 是否显示头像 | `boolean` | `false` | 否 |
270
303
  | avatarBaseUrl | 头像基础 URL | `string` | `` | 否 |
271
304
  | label | 文本标签 | `string` | `'人员选择'` | 否 |
@@ -285,6 +318,9 @@ export default {
285
318
  | allowCreate | 是否允许自定义输入,按 Enter 确认 | `boolean` | `false` | 否 |
286
319
  | freePaste | 是否允许粘贴任意文本 | `boolean` | `false` | 否 |
287
320
  | maxCount | 最大可选数量(0 表示不限制) | `number` | `0` | 否 |
321
+ | type | 输入框类型 | `'input'` / `'textarea'` | `'input'` | 否 |
322
+ | rows | 默认行数(仅 textarea 模式生效) | `number` | `4` | 否 |
323
+ | resize | 是否允许拖拽调整高度(仅 textarea 模式生效) | `boolean` | `true` | 否 |
288
324
 
289
325
  #### exactSearchKey 说明
290
326
 
@@ -359,6 +395,16 @@ type RenderFunction = (
359
395
  - **开启(默认)**:使用多租户用户管理接口查询,支持跨租户显示
360
396
  - **关闭**:使用原有用户管理接口查询
361
397
 
398
+ ### 多行输入模式(Textarea)
399
+
400
+ 通过 `type="textarea"` 启用多行模式:
401
+
402
+ - **完整展示**:未聚焦时不折叠标签,完整展示所有已选用户
403
+ - **高度可配**:通过 `rows` 设置默认行数,每行约 32px
404
+ - **可拖拽调整**:默认允许拖拽调整容器高度,可通过 `resize=false` 禁用
405
+ - **自动滚动**:内容超出容器高度时自动出现滚动条
406
+ - **聚焦同步**:切换聚焦/失焦状态时自动同步容器高度
407
+
362
408
  ### 拖拽排序
363
409
 
364
410
  在多选模式下启用 `draggable`:
@@ -367,6 +413,21 @@ type RenderFunction = (
367
413
  - 拖拽时会有视觉反馈
368
414
  - 拖拽完成后会触发 `change` 事件
369
415
 
416
+ ### 键盘导航
417
+
418
+ 组件支持完整的键盘操作:
419
+
420
+ | 按键 | 功能 |
421
+ | ----------- | --------------------------------------------------------- |
422
+ | `↑` / `↓` | 在下拉列表中切换高亮选项 |
423
+ | `Enter` | 选中当前高亮的选项(`allowCreate=true` 时创建自定义用户) |
424
+ | `←` / `→` | 在已选标签之间移动光标 |
425
+ | `Backspace` | 删除光标前的已选用户 |
426
+
427
+ - 输入搜索内容后,第一个选项会自动高亮
428
+ - 高亮选项会自动滚动到可视区域
429
+ - 支持用户组、普通用户、虚拟账号的键盘选择
430
+
370
431
  ## ⚠️ 注意事项
371
432
 
372
433
  1. **API 配置**:使用前必须正确配置 `apiBaseUrl` 和 `tenantId`
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@blueking/bk-user-selector",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "蓝鲸用户选择器",
5
5
  "license": "MIT",
6
6
  "author": "Tencent BlueKing",
7
7
  "scripts": {
8
8
  "prepublishOnly": "run-p build dts",
9
9
  "dev": "vite --mode development -c scripts/vite.dev.ts",
10
- "build": "tsx ./scripts/vite.build.ts",
10
+ "build": "vite-node ./scripts/vite.build.ts",
11
11
  "dts": "vue-tsc --project tsconfig.dts.json",
12
12
  "prettier": "prettier ./src ./scripts ./playground --write",
13
13
  "visualize": "vite-bundle-visualizer -c scripts/vite.visualizer.ts"
@@ -58,10 +58,7 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "bkui-vue": "2.0.2-beta.63",
61
- "lodash": "^4.17.21",
61
+ "lodash": "^4.17.23",
62
62
  "sortablejs": "^1.15.6"
63
- },
64
- "engines": {
65
- "node": ">=18.16.0"
66
63
  }
67
64
  }
@@ -7,7 +7,7 @@ interface MeTagProps {
7
7
  /** 是否禁用 */
8
8
  isDisabled?: boolean;
9
9
  }
10
- declare const _default: import("vue").DefineComponent<MeTagProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
10
+ declare const __VLS_export: import("vue").DefineComponent<MeTagProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
11
  click: () => any;
12
12
  }, string, import("vue").PublicProps, Readonly<MeTagProps> & Readonly<{
13
13
  onClick?: (() => any) | undefined;
@@ -15,4 +15,5 @@ declare const _default: import("vue").DefineComponent<MeTagProps, {}, {}, {}, {}
15
15
  currentUserId: string;
16
16
  isDisabled: boolean;
17
17
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ declare const _default: typeof __VLS_export;
18
19
  export default _default;
@@ -9,8 +9,12 @@ interface SelectionPopoverProps {
9
9
  containerWidth?: number | string;
10
10
  /** 无匹配人员时的提示文本 */
11
11
  emptyText?: string;
12
+ /** 扁平化选项列表(用于键盘导航高亮) */
13
+ flatOptions?: FormattedUser[];
12
14
  /** 是否显示头像 */
13
15
  hasAvatar?: boolean;
16
+ /** 当前高亮选项索引 */
17
+ highlightedIndex?: number;
14
18
  /** 是否显示下拉菜单 */
15
19
  isShow?: boolean;
16
20
  /** 是否加载中 */
@@ -30,21 +34,11 @@ interface SelectionPopoverProps {
30
34
  /** 用户组名称 */
31
35
  userGroupName?: string;
32
36
  }
33
- declare var __VLS_20: {};
34
- declare var __VLS_inheritedAttrs: {};
35
- declare const __VLS_refs: {
36
- contentContainerRef: any;
37
- slotContainerRef: any;
37
+ declare var __VLS_22: {};
38
+ type __VLS_Slots = {} & {
39
+ default?: (props: typeof __VLS_22) => any;
38
40
  };
39
- declare const __VLS_templateResult: {
40
- slots: {
41
- default?(_: typeof __VLS_20): any;
42
- };
43
- refs: __VLS_PickRefsExpose<typeof __VLS_refs>;
44
- attrs: Partial<typeof __VLS_inheritedAttrs>;
45
- };
46
- type __VLS_Slots = typeof __VLS_templateResult['slots'];
47
- declare const __VLS_component: import("vue").DefineComponent<SelectionPopoverProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
41
+ declare const __VLS_base: import("vue").DefineComponent<SelectionPopoverProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
48
42
  "click-outside": (event: MouseEvent) => any;
49
43
  "select-user": (user: FormattedUser) => any;
50
44
  }, string, import("vue").PublicProps, Readonly<SelectionPopoverProps> & Readonly<{
@@ -59,19 +53,17 @@ declare const __VLS_component: import("vue").DefineComponent<SelectionPopoverPro
59
53
  avatarBaseUrl: string;
60
54
  containerWidth: number | string;
61
55
  emptyText: string;
56
+ flatOptions: FormattedUser[];
57
+ highlightedIndex: number;
62
58
  isShow: boolean;
63
59
  loading: boolean;
64
60
  options: FormattedUser[];
65
61
  userGroupName: string;
66
62
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
67
- declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_Slots>;
63
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
64
+ declare const _default: typeof __VLS_export;
68
65
  export default _default;
69
- type __VLS_PickRefsExpose<T> = T extends object ? {
70
- [K in keyof T]: (T[K] extends any[] ? Parameters<T[K][0]['expose']>[0][] : T[K] extends {
71
- expose?: (exposed: infer E) => void;
72
- } ? E : T[K]) | null;
73
- } : never;
74
- type __VLS_WithTemplateSlots<T, S> = T & {
66
+ type __VLS_WithSlots<T, S> = T & {
75
67
  new (): {
76
68
  $slots: S;
77
69
  };
@@ -1,5 +1,5 @@
1
1
  import { FormattedUser, UserSelectorProps } from '../types';
2
- declare const _default: import("vue").DefineComponent<UserSelectorProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
2
+ declare const __VLS_export: import("vue").DefineComponent<UserSelectorProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
3
3
  blur: () => any;
4
4
  change: (user: FormattedUser | FormattedUser[] | null) => any;
5
5
  focus: () => any;
@@ -15,6 +15,7 @@ declare const _default: import("vue").DefineComponent<UserSelectorProps, {}, {},
15
15
  "onUpdate:modelValue"?: ((value: string | string[]) => any) | undefined;
16
16
  }>, {
17
17
  userGroup: import("../types").UserGroupConfig[];
18
+ type: "input" | "textarea";
18
19
  apiBaseUrl: string;
19
20
  tenantId: string;
20
21
  enableMultiTenantMode: boolean;
@@ -24,14 +25,17 @@ declare const _default: import("vue").DefineComponent<UserSelectorProps, {}, {},
24
25
  freePaste: boolean;
25
26
  maxCount: number;
26
27
  excludeUserIds: string[];
27
- disabled: boolean;
28
+ resize: boolean;
28
29
  hasAvatar: boolean;
29
30
  avatarBaseUrl: string;
30
31
  emptyText: string;
31
32
  userGroupName: string;
33
+ disabled: boolean;
32
34
  draggable: boolean;
33
35
  modelValue: string | string[];
34
36
  multiple: boolean;
37
+ rows: number;
35
38
  placeholder: string;
36
39
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
40
+ declare const _default: typeof __VLS_export;
37
41
  export default _default;
@@ -1,6 +1,9 @@
1
1
  import { createVNode, VNode } from 'vue';
2
2
  import { FormattedUser } from '../types';
3
- declare const _default: import("vue").DefineComponent<{
3
+ /**
4
+ * 组件属性
5
+ */
6
+ type __VLS_Props = {
4
7
  /**
5
8
  * 是否激活状态
6
9
  */
@@ -37,48 +40,13 @@ declare const _default: import("vue").DefineComponent<{
37
40
  * 用户信息
38
41
  */
39
42
  user: FormattedUser;
40
- }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
43
+ };
44
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
41
45
  click: (...args: any[]) => void;
42
46
  close: (...args: any[]) => void;
43
- }, string, import("vue").PublicProps, Readonly<{
44
- /**
45
- * 是否激活状态
46
- */
47
- active?: boolean;
48
- /**
49
- * 头像基础URL
50
- */
51
- avatarBaseUrl?: string;
52
- /**
53
- * 当前租户ID
54
- */
55
- currentTenantId: string;
56
- /**
57
- * 是否可拖拽
58
- */
59
- draggable?: boolean;
60
- /**
61
- * 是否显示头像
62
- */
63
- hasAvatar?: boolean;
64
- /**
65
- * 渲染标签
66
- */
67
- renderTag?: (h: typeof createVNode, userInfo: FormattedUser) => VNode;
68
- /**
69
- * 是否显示租户信息
70
- */
71
- showTenant?: boolean;
72
- /**
73
- * 租户数据映射
74
- */
75
- tenants: Record<string, string>;
76
- /**
77
- * 用户信息
78
- */
79
- user: FormattedUser;
80
- }> & Readonly<{
47
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
81
48
  onClick?: ((...args: any[]) => any) | undefined;
82
49
  onClose?: ((...args: any[]) => any) | undefined;
83
50
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
51
+ declare const _default: typeof __VLS_export;
84
52
  export default _default;
@@ -220,6 +220,23 @@ export interface UserSelectorProps extends BaseSelectorProps {
220
220
  * 是否多选
221
221
  */
222
222
  multiple?: boolean;
223
+ /**
224
+ * 是否允许拖拽调整高度(仅 type='textarea' 时生效)
225
+ * @default true
226
+ */
227
+ resize?: boolean;
228
+ /**
229
+ * 默认行数(仅 type='textarea' 时生效,每行约 32px)
230
+ * @default 4
231
+ */
232
+ rows?: number;
233
+ /**
234
+ * 输入框类型
235
+ * - input: 单行模式(默认),固定高度,未聚焦时折叠标签
236
+ * - textarea: 多行模式,高度可配置,完整展示所有标签
237
+ * @default 'input'
238
+ */
239
+ type?: 'input' | 'textarea';
223
240
  }
224
241
  /**
225
242
  * 用户类型
package/vue2/config.json CHANGED
@@ -1 +1,22 @@
1
- {"type":"bk-user-selector","name":"bk-user-selector","displayName":"人员选择器","framework":"vue2","styles":[],"props":{"modelValue":{"type":["number","string"],"tips":"值"},"dataUrl":{"type":"string","tips":"数据源接口"}},"events":[],"slots":{}}
1
+ {
2
+ "type": "bk-user-selector",
3
+ "name": "bk-user-selector",
4
+ "displayName": "人员选择器",
5
+ "framework": "vue2",
6
+ "styles": [],
7
+ "props": {
8
+ "modelValue": {
9
+ "type": [
10
+ "number",
11
+ "string"
12
+ ],
13
+ "tips": "值"
14
+ },
15
+ "dataUrl": {
16
+ "type": "string",
17
+ "tips": "数据源接口"
18
+ }
19
+ },
20
+ "events": [],
21
+ "slots": {}
22
+ }