Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(1.6.1): weekly sync update to naruto #2705

Merged
merged 8 commits into from
Aug 17, 2023
Merged
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@ toc: false
docClass: timeline
---

## 🌈 1.6.1 `2023-08-15`
### 🚀 Features
- `Menu`: menu-item `click` 事件参数增加 value @dexterBo ([#2689](https://github.com/Tencent/tdesign-vue/pull/2689))
- `键盘操作`: @chaishi ([#2683](https://github.com/Tencent/tdesign-vue/pull/2683))
- `Checkbox`: 支持使用空格键选中或取消选中
- `Radio`: 支持使用空格键选中或取消选中
- `SelectInput`: 支持键盘事件
- `Select`: 支持键盘操作聚焦和显示下拉框,可通过上下键切换选项
### 🐞 Bug Fixes
- `SelectInput`: 修复多选情况下按下 Enter 键后触发了 focus 事件而不是 enter 事件的问题 @dexterBo ([#2694](https://github.com/Tencent/tdesign-vue/pull/2694))
- `Select`: 远程搜索场景下不再进行内部过滤 @uyarn ([#2699](https://github.com/Tencent/tdesign-vue/pull/2699))
- `Menu`: 修复激活菜单项未发生变化时也会触发 change 事件的的问题 @dexterBo ([#2693](https://github.com/Tencent/tdesign-vue/pull/2693))
- `ImageViewer`: 前后浏览及关闭浏览时重置图片状态 @sinbadmaster ([#2685](https://github.com/Tencent/tdesign-vue/pull/2685))
- `Table`: @chaishi ([#2683](https://github.com/Tencent/tdesign-vue/pull/2683))
- 拖拽排序在使用懒加载 `lazyLoad` 时,失效问题
- 虚拟滚动场景,修复默认滚动条长度和滚动后的长度不一致问题
- 补充 SSR 场景,window 变量判断

## 🌈 1.6.0 `2023-08-10`
### 🚀 Features
- `Icon`: 新增 960 个图标;调整图标命名 `photo` 为 `camera`,`books`为`bookmark`, `stop-cirle-1`为`stop-circle-stroke`;移除`money-circle`图标,具体请查看图标页面 @uyarn ([#2677](https://github.com/Tencent/tdesign-vue/pull/2677))
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "tdesign-vue",
"purename": "tdesign",
"version": "1.6.0-naruto",
"version": "1.6.1-naruto",
"description": "tdesign-vue",
"title": "tdesign-vue",
"keywords": [
Expand Down
8 changes: 4 additions & 4 deletions src/affix/affix.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

name | type | default | description | required
-- | -- | -- | -- | --
container | String / Function | () => (() => window) | Typescript:`ScrollContainer` | N
content(暂未实现) | String / Slot / Function | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
container | String / Function | () => (() => window) | Typescript:`ScrollContainer`。[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
content(暂未实现) | String / Slot / Function | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
default | String / Slot / Function | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
offsetBottom | Number | 0 | \- | N
offsetTop | Number | 0 | \- | N
offsetBottom | Number | 0 | When the distance from the bottom of the container reaches the specified distance, the trigger is fixed | N
offsetTop | Number | 0 | When the distance from the top of the container reaches the specified distance, the trigger is fixed | N
zIndex | Number | - | \- | N
onFixedChange | Function | | Typescript:`(affixed: boolean, context: { top: number }) => void`<br/> | N

Expand Down
6 changes: 3 additions & 3 deletions src/affix/affix.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
container | String / Function | () => (() => window) | 指定滚动的容器。数据类型为 String 时,会被当作选择器处理,进行节点查询。示例:'body' 或 () => document.body。TS 类型:`ScrollContainer` | N
container | String / Function | () => (() => window) | 指定滚动的容器。数据类型为 String 时,会被当作选择器处理,进行节点查询。示例:'body' 或 () => document.body。TS 类型:`ScrollContainer`。[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
content(暂未实现) | String / Slot / Function | - | 内容。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
default | String / Slot / Function | - | 内容,同 content。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
offsetBottom | Number | 0 | 距离容器顶部达到指定距离后触发固定 | N
offsetTop | Number | 0 | 距离容器底部达到指定距离后触发固定 | N
offsetBottom | Number | 0 | 距离容器底部达到指定距离后触发固定 | N
offsetTop | Number | 0 | 距离容器顶部达到指定距离后触发固定 | N
zIndex | Number | - | 固钉定位层级,样式默认为 500 | N
onFixedChange | Function | | TS 类型:`(affixed: boolean, context: { top: number }) => void`<br/>固定状态发生变化时触发 | N

Expand Down
15 changes: 11 additions & 4 deletions src/affix/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* updated at 2021-11-19 10:44:26
* */

import { TdAffixProps } from './type';
Expand All @@ -12,14 +11,22 @@ export default {
/** 指定滚动的容器。数据类型为 String 时,会被当作选择器处理,进行节点查询。示例:'body' 或 () => document.body */
container: {
type: [String, Function] as PropType<TdAffixProps['container']>,
default: () => (() => window),
default: () => () => window,
},
/** 距离容器顶部达到指定距离后触发固定 */
/** 内容 */
content: {
type: [String, Function] as PropType<TdAffixProps['content']>,
},
/** 内容,同 content */
default: {
type: [String, Function] as PropType<TdAffixProps['default']>,
},
/** 距离容器底部达到指定距离后触发固定 */
offsetBottom: {
type: Number,
default: 0,
},
/** 距离容器底部达到指定距离后触发固定 */
/** 距离容器顶部达到指定距离后触发固定 */
offsetTop: {
type: Number,
default: 0,
Expand Down
17 changes: 12 additions & 5 deletions src/affix/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* updated at 2021-11-19 10:44:26
* */

import { ScrollContainer } from '../common';
import { TNode, ScrollContainer } from '../common';

export interface TdAffixProps {
/**
Expand All @@ -14,12 +13,20 @@ export interface TdAffixProps {
*/
container?: ScrollContainer;
/**
* 距离容器顶部达到指定距离后触发固定
* 内容
*/
content?: string | TNode;
/**
* 内容,同 content
*/
default?: string | TNode;
/**
* 距离容器底部达到指定距离后触发固定
* @default 0
*/
offsetBottom?: number;
/**
* 距离容器底部达到指定距离后触发固定
* 距离容器顶部达到指定距离后触发固定
* @default 0
*/
offsetTop?: number;
Expand All @@ -31,4 +38,4 @@ export interface TdAffixProps {
* 固定状态发生变化时触发
*/
onFixedChange?: (affixed: boolean, context: { top: number }) => void;
};
}
6 changes: 5 additions & 1 deletion src/checkbox/hooks/useKeyboardEvent.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
export const CHECKED_CODE_REG = /(enter|space)/i;

export function useKeyboardEvent(handleChange: (e: Event) => void) {
const keyboardEventListener = (e: KeyboardEvent) => {
if (e.code === 'Enter') {
const isCheckedCode = CHECKED_CODE_REG.test(e.key) || CHECKED_CODE_REG.test(e.code);
if (isCheckedCode) {
e.preventDefault();
const { disabled } = (e.currentTarget as HTMLElement).querySelector('input');
!disabled && handleChange(e);
}
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/useElementLazyRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export function useElementLazyRender(labelRef: Ref<HTMLElement>, lazyLoad: Ref<b
const showElement = ref(true);

const handleLazyLoad = () => {
if (!lazyLoad.value) return;
if (!lazyLoad.value || !labelRef.value || ioObserver.value) return;
showElement.value = false;
const io = observe(
labelRef.value,
Expand All @@ -23,11 +23,11 @@ export function useElementLazyRender(labelRef: Ref<HTMLElement>, lazyLoad: Ref<b

onMounted(handleLazyLoad);

lazyLoad.value && watch([lazyLoad], handleLazyLoad);
lazyLoad.value && watch([lazyLoad, labelRef], handleLazyLoad);

onBeforeUnmount(() => {
if (!lazyLoad.value) return;
ioObserver.value?.unobserve(labelRef.value);
ioObserver.value?.unobserve?.(labelRef.value);
});

return {
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useVirtualScrollNew.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const useVirtualScroll = (container: Ref<HTMLElement>, params: UseVirtualScrollP
/** 注意测试:数据长度为空;数据长度小于表格高度等情况。即期望只有数据量达到一定程度才允许开启虚拟滚动 */
const visibleData = ref<any[]>([]);
// 用于显示表格列
const translateY = ref(0);
const translateY = ref((params.value.data?.length || 0) * (params.value.scroll?.rowHeight || 50));
// 滚动高度,用于显示滚动条
const scrollHeight = ref(0);
const trScrollTopHeightList = ref<number[]>([]);
Expand Down
3 changes: 3 additions & 0 deletions src/image-viewer/image-viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,13 @@ export default defineComponent({

const prevImage = () => {
const newIndex = indexValue.value - 1;
onRest();
setIndexValue(newIndex < 0 ? 0 : newIndex, { trigger: 'prev' });
};

const nextImage = () => {
const newIndex = indexValue.value + 1;
onRest();
setIndexValue(newIndex >= imagesList.value.length ? indexValue.value : newIndex, { trigger: 'next' });
};

Expand Down Expand Up @@ -145,6 +147,7 @@ export default defineComponent({
() => visibleValue.value,
(val) => {
if (val) {
onRest();
window.addEventListener('keydown', keydownHandler);
mountContent();
return;
Expand Down
23 changes: 11 additions & 12 deletions src/input/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -525,18 +525,17 @@ export default mixins(
<span class={[`${this.componentName}__prefix`, `${this.componentName}__prefix-icon`]}>{prefixIcon}</span>
) : null}
{labelContent}
{this.showInput && (
<input
// @ts-ignore
attrs={this.inputAttrs}
on={inputEvents}
ref="inputRef"
class={`${this.componentName}__inner`}
value={inputTextValue}
onInput={this.handleInput}
title={this.disabled ? inputTextValue : undefined}
/>
)}
{/* input element must exist, or other select components can not focus by keyboard operation */}
<input
// @ts-ignore
attrs={this.inputAttrs}
on={inputEvents}
ref="inputRef"
class={[`${this.componentName}__inner`, { [`${this.componentName}--soft-hidden`]: !this.showInput }]}
value={inputTextValue}
onInput={this.handleInput}
title={this.disabled ? inputTextValue : undefined}
/>
{this.autoWidth && (
<span ref="inputPreRef" class={`${this.classPrefix}-input__input-pre`}>
{this.preValue || this.tPlaceholder}
Expand Down
8 changes: 5 additions & 3 deletions src/menu/menu-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ export default defineComponent({
const handleClick = (e: MouseEvent) => {
e.stopPropagation();
if (props.disabled) return;
menu.select(props.value);
ctx.emit('click', { e });
props.onClick?.({ e });
if (menu.activeValue.value !== props.value) {
menu.select(props.value);
}
ctx.emit('click', { e, value: props.value });
props.onClick?.({ e, value: props.value });

if (props.href) {
window.open(props.href, props.target);
Expand Down
4 changes: 2 additions & 2 deletions src/menu/menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ router | Object | - | 路由对象。如果项目存在 Router,则默认使用
target | String | - | 链接或路由跳转方式。可选项:_blank/_self/_parent/_top | N
to | String / Object | - | 路由跳转目标,当且仅当 Router 存在时,该 API 有效。TS 类型:`MenuRoute` `interface MenuRoute { path?: string; name?: string; hash?: string; query?: MenuQueryData; params?: MenuQueryData }` `type MenuQueryData = { [key: string]: string \| string[] }`。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/menu/type.ts) | N
value | String / Number | - | 菜单项唯一标识。TS 类型:`MenuValue` | N
onClick | Function | | TS 类型:`(context: { e: MouseEvent }) => void`<br/>点击时触发 | N
onClick | Function | | TS 类型:`(context: { e: MouseEvent, value: MenuValue }) => void`<br/>点击时触发 | N

### MenuItem Events

名称 | 参数 | 描述
-- | -- | --
click | `(context: { e: MouseEvent })` | 点击时触发
click | `(context: { e: MouseEvent, value: MenuValue })` | 点击时触发

### MenuGroup Props

Expand Down
2 changes: 1 addition & 1 deletion src/menu/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ export interface TdMenuItemProps {
/**
* 点击时触发
*/
onClick?: (context: { e: MouseEvent }) => void;
onClick?: (context: { e: MouseEvent; value: MenuValue }) => void;
}

export interface TdMenuGroupProps {
Expand Down
5 changes: 4 additions & 1 deletion src/radio/group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { emitEvent } from '../utils/event';
import { getClassPrefixMixins } from '../config-provider/config-receiver';
import mixins from '../utils/mixins';
import { off, on } from '../utils/dom';
import { CHECKED_CODE_REG } from '../checkbox/hooks/useKeyboardEvent';

const classPrefixMixins = getClassPrefixMixins('radio-group');

Expand Down Expand Up @@ -113,7 +114,9 @@ export default mixins(classPrefixMixins).extend({

// 注意:此处会还原区分 数字 和 数字字符串
checkRadioInGroup(e: KeyboardEvent) {
if (/enter/i.test(e.key) || /enter/i.test(e.code)) {
const isCheckedCode = CHECKED_CODE_REG.test(e.key) || CHECKED_CODE_REG.test(e.code);
if (isCheckedCode) {
e.preventDefault();
const inputNode = (e.target as HTMLElement).querySelector('input');
const data = inputNode.dataset;
if (inputNode.checked && data.allowUncheck) {
Expand Down
4 changes: 4 additions & 0 deletions src/select-input/_example/single.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
@popup-visible-change="onPopupVisibleChange"
@clear="onClear"
@input-change="onInputChange"
@focus="onFocus"
>
<template #panel>
<ul class="tdesign-demo__select-input-ul-single">
Expand Down Expand Up @@ -61,6 +62,9 @@ export default {
// 过滤功能
console.log(val, context);
},
onFocus(val, context) {
console.log('focus:', val, context);
},
},
};
</script>
Expand Down
51 changes: 47 additions & 4 deletions src/select-input/select-input.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import {
computed, defineComponent, Ref, ref, SetupContext, toRef, toRefs,
computed,
defineComponent,
onBeforeUnmount,
onMounted,
ref,
SetupContext,
toRefs,
watch,
toRef,
Ref,
} from 'vue';
import Popup, { PopupProps, PopupVisibleChangeContext } from '../popup';
import props from './props';
Expand Down Expand Up @@ -31,20 +40,27 @@ export default defineComponent({
const popupProps = toRef(props, 'popupProps') as Ref<PopupProps>;

const {
commonInputProps, singleInputValue, onInnerClear, renderSelectSingle,
} = useSingle(props, context);
const { multipleInputValue, renderSelectMultiple } = useMultiple(props, context);
isSingleFocus, commonInputProps, singleInputValue, onInnerClear, renderSelectSingle,
} = useSingle(
props,
context,
);
const { multipleInputValue, isMultipleFocus, renderSelectMultiple } = useMultiple(props, context);
const { tOverlayInnerStyle, innerPopupVisible, onInnerPopupVisibleChange } = useOverlayInnerStyle(props, {
afterHidePopup: onInnerBlur,
});

const isFocus = computed(() => (props.multiple ? isMultipleFocus.value : isSingleFocus.value));

// SelectInput.blur is not equal to Input or TagInput, example: click popup panel.
// if trigger blur on click popup panel, filter data of tree select can not be checked.
function onInnerBlur(ctx: PopupVisibleChangeContext) {
const inputValue = props.multiple ? multipleInputValue.value : singleInputValue.value;
const params: Parameters<TdSelectInputProps['onBlur']>[1] = { e: ctx.e, inputValue };
props.onBlur?.(props.value, params);
context.emit('blur', props.value, params);
isSingleFocus.value = false;
isMultipleFocus.value = false;
}

const classes = computed(() => [
Expand All @@ -57,6 +73,33 @@ export default defineComponent({
},
]);

const addKeyboardEventListener = (e: KeyboardEvent) => {
if (/(ArrowDown|ArrowUp)/.test(e.code || e.key)) {
const ctx: PopupVisibleChangeContext = { ...context, trigger: 'trigger-element-focus' };
props.onPopupVisibleChange?.(true, ctx);
context.emit('popup-visible-change', true, ctx);
}
};

watch([isFocus], ([isFocus]) => {
if (popupVisible.value) return;
if (isFocus) {
selectInputRef.value.addEventListener('keydown', addKeyboardEventListener);
} else {
selectInputRef.value.removeEventListener('keydown', addKeyboardEventListener);
}
});

onMounted(() => {
if (!popupVisible.value && isFocus) {
selectInputRef.value.addEventListener('keydown', addKeyboardEventListener);
}
});

onBeforeUnmount(() => {
selectInputRef.value.removeEventListener('keydown', addKeyboardEventListener);
});

return {
selectInputRef,
innerPopupVisible,
Expand Down
Loading
Loading