Skip to content
Open
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0c9e573
feat(Select): optimize custom node rendering
RylanBot Oct 14, 2025
a95f2db
refactor: optimize value display logic
RylanBot Oct 15, 2025
8ec8e7d
fix(useSingle): update placeholder logic
RylanBot Oct 15, 2025
259ed00
chore(Option): update deps import orders
RylanBot Oct 15, 2025
ba42885
fix(useSingle): improve label handling and typing state management
RylanBot Oct 16, 2025
5766fce
chore(useSingle): rename variables for clarity
RylanBot Oct 16, 2025
105862d
fix(Cascader): improve title handling
RylanBot Oct 23, 2025
58394d5
fix: `autoWidth`
RylanBot Nov 27, 2025
fb71e06
Merge remote-tracking branch 'origin' into rylan/feat/select/filterable
RylanBot Nov 27, 2025
f784914
Merge remote-tracking branch 'origin' into rylan/feat/select/filterable
RylanBot Dec 18, 2025
5e3edce
chore: update snapshots
RylanBot Dec 19, 2025
8ecbc38
Merge remote-tracking branch 'origin' into rylan/feat/select/filterable
RylanBot May 12, 2026
817211b
fix: calc width
RylanBot May 12, 2026
7abbf3a
chore: update snap
RylanBot May 12, 2026
7179cb0
Merge remote-tracking branch 'origin' into rylan/feat/select/filterable
RylanBot May 20, 2026
0ab0a21
Merge remote-tracking branch 'origin' into rylan/feat/select/filterable
RylanBot Jun 1, 2026
a3a6c55
refactor: use `min-height` instead of `height` for custom element
RylanBot Jun 1, 2026
f362de1
Merge remote-tracking branch 'origin' into rylan/feat/select/filterable
RylanBot Jun 10, 2026
bf2c5d3
Merge remote-tracking branch 'origin' into rylan/feat/select/filterable
RylanBot Jun 16, 2026
2b9024e
fix: avoid `Cannot read properties of null`
RylanBot Jun 16, 2026
7e9bc75
fix: auto width
RylanBot Jun 25, 2026
59e8937
Merge remote-tracking branch 'origin' into rylan/feat/select/filterable
RylanBot Jun 25, 2026
77f5605
fix: revert lint
RylanBot Jun 25, 2026
c7a6af5
fix: min-width
RylanBot Jun 25, 2026
4c00288
fix: calc width
RylanBot Jun 26, 2026
dd9f8a0
Merge remote-tracking branch 'origin' into rylan/feat/select/filterable
RylanBot Jun 26, 2026
cdb87dd
chore: remove comments
RylanBot Jun 26, 2026
8fb5fbc
chore: optimize code
RylanBot Jun 26, 2026
66f3a46
fix: simplify logic
RylanBot Jun 26, 2026
7056f2d
Merge remote-tracking branch 'origin' into rylan/feat/select/filterable
RylanBot Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ static/
packages/common
packages/ai-core
site/engineering/static
packages/components/**/type.ts
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
}
},
"lint-staged": {
"packages/**/*.{ts,tsx}": [
"packages/**/!(type).{ts,tsx}": [
"prettier --write",
"pnpm run lint:fix"
]
Expand Down
14 changes: 14 additions & 0 deletions packages/components/_util/parseTNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,17 @@ export function parseContentTNode<T>(tnode: TNode<T>, props: T) {
return null;
}
}

export function extractTextFromTNode(node: TNode): string {
if (typeof node === 'string' || typeof node === 'number' || typeof node === 'boolean') return String(node);
if (React.isValidElement(node)) {
const { children } = node.props || {};
if (children) return extractTextFromTNode(children);
}
if (Array.isArray(node)) {
return node.map(extractTextFromTNode).join('');
}

// todo:兼容 ((props: T) => ReactNode) 函数类型
Comment thread
RylanBot marked this conversation as resolved.
return '';
}
10 changes: 8 additions & 2 deletions packages/components/cascader/__tests__/cascader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,18 @@ describe('Cascader 组件测试', () => {
expect(spy).toHaveBeenCalled();
fireEvent.click(getByPlaceholderText(placeholderId));
expect(spy).toHaveBeenCalledTimes(2);
await mockTimeout(() => expect(document.querySelector(popupSelector)).toHaveStyle({ display: 'none' }));
await mockTimeout(() =>
expect(document.querySelector(popupSelector)).toHaveStyle({
display: 'none',
}),
);

// disabled 不会展开 popup,且不执行 onPopupVisibleChange
fireEvent.click(getByText(btnText));
fireEvent.click(getByPlaceholderText(placeholderId));
expect(document.querySelector(popupSelector)).toHaveStyle({ display: 'none' });
expect(document.querySelector(popupSelector)).toHaveStyle({
display: 'none',
});
expect(spy).toHaveBeenCalledTimes(2);
});

Expand Down
7 changes: 6 additions & 1 deletion packages/components/cascader/components/Item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,14 @@ const Item = forwardRef(
const RenderLabelContent = (node: TreeNode, cascaderContext: CascaderContextType) => {
const label = RenderLabelInner(node, cascaderContext);

const getTitle = () => {
const title = cascaderContext.inputVal ? getFullPathLabel(node) : node.label;
return typeof title !== 'object' ? title : undefined;
};

const labelCont = (
<span
title={cascaderContext.inputVal ? getFullPathLabel(node) : node.label}
title={getTitle()}
className={classNames(`${COMPONENT_NAME}-label`, `${COMPONENT_NAME}-label--ellipsis`)}
role="label"
>
Expand Down
5 changes: 4 additions & 1 deletion packages/components/dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ const Dialog = forwardRef<DialogInstance, DialogProps>((originalProps, ref) => {
const dialogPosition = useRef(null);
const portalRef = useRef(null);

const [state, setState] = useSetState<DialogProps>({ isPlugin: false, ...restProps });
const [state, setState] = useSetState<DialogProps>({
isPlugin: false,
...restProps,
});
const [local] = useLocaleReceiver('dialog');

const {
Expand Down
30 changes: 24 additions & 6 deletions packages/components/dialog/__tests__/dialog.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,16 @@ describe('Dialog组件测试', () => {
expect(document.querySelector('.t-dialog__modeless')).toBeInTheDocument();
fireEvent.mouseDown(document.querySelector('.t-dialog'));
fireEvent.mouseMove(document.querySelector('.t-dialog'));
expect(document.querySelector('.t-dialog')).toHaveStyle({ cursor: 'move', position: 'absolute' });
expect(document.querySelector('.t-dialog')).toHaveStyle({
cursor: 'move',
position: 'absolute',
});
fireEvent.mouseUp(document.querySelector('.t-dialog'));
userEvent.keyboard('{esc}');
expect(document.querySelector('.t-dialog')).toHaveStyle({ left: '0px', top: '0px' });
expect(document.querySelector('.t-dialog')).toHaveStyle({
left: '0px',
top: '0px',
});
});

test('DialogPlugin', async () => {
Expand Down Expand Up @@ -204,7 +210,11 @@ describe('Dialog组件测试', () => {
value={{
globalConfig: {
...defaultGlobalConfig,
dialog: { ...(defaultGlobalConfig.dialog || {}), placement: 'center', zIndex: 4321 },
dialog: {
...(defaultGlobalConfig.dialog || {}),
placement: 'center',
zIndex: 4321,
},
},
}}
>
Expand All @@ -214,7 +224,9 @@ describe('Dialog组件测试', () => {

expect(document.querySelector('.t-dialog--center')).toBeInTheDocument();
expect(document.querySelector('.t-dialog--top')).not.toBeInTheDocument();
expect(document.querySelector('.t-dialog__ctx')).toHaveStyle({ zIndex: '4321' });
expect(document.querySelector('.t-dialog__ctx')).toHaveStyle({
zIndex: '4321',
});
});

test('dialog props should override global dialog config', async () => {
Expand All @@ -223,7 +235,11 @@ describe('Dialog组件测试', () => {
value={{
globalConfig: {
...defaultGlobalConfig,
dialog: { ...(defaultGlobalConfig.dialog || {}), placement: 'center', zIndex: 4321 },
dialog: {
...(defaultGlobalConfig.dialog || {}),
placement: 'center',
zIndex: 4321,
},
},
}}
>
Expand All @@ -233,6 +249,8 @@ describe('Dialog组件测试', () => {

expect(document.querySelector('.t-dialog--top')).toBeInTheDocument();
expect(document.querySelector('.t-dialog--center')).not.toBeInTheDocument();
expect(document.querySelector('.t-dialog__ctx')).toHaveStyle({ zIndex: '1234' });
expect(document.querySelector('.t-dialog__ctx')).toHaveStyle({
zIndex: '1234',
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ describe('InputNumber 组件测试', () => {
);
expect(container.firstChild.classList.contains('t-input-number')).toBeTruthy();
expect(queryByPlaceholderText(InputNumberPlaceholder)).toBeInTheDocument();
fireEvent.change(queryByPlaceholderText(InputNumberPlaceholder), { target: { value: InputNumberValue } });
fireEvent.change(queryByPlaceholderText(InputNumberPlaceholder), {
target: { value: InputNumberValue },
});
expect(changeFn).toBeCalledTimes(1);
expect(changeFn.mock.calls[0][0]).toBe(InputNumberValue);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/components/input-number/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,4 @@ export interface ChangeContext {
| CompositionEvent<HTMLDivElement>;
}

export type ChangeSource = 'add' | 'reduce' | 'input' | 'blur' | 'enter' | 'clear' | 'props';
export type ChangeSource = 'add' | 'reduce' | 'input' | 'blur' | 'enter' | 'clear' | 'props';
2 changes: 1 addition & 1 deletion packages/components/input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ const Input = forwardRefWithStatics(
) : null;

const updateInputWidth = () => {
if (!autoWidth || !inputRef.current) return;
if (!autoWidth || !inputRef.current || !inputPreRef.current) return;
const { offsetWidth } = inputPreRef.current;
const { width } = inputPreRef.current.getBoundingClientRect();
// 异步渲染场景下 getBoundingClientRect 宽度为 0,需要使用 offsetWidth
Expand Down
9 changes: 7 additions & 2 deletions packages/components/loading/Loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ const Loading: React.FC<LoadingProps> = (props) => {
zIndex,
className,
style,
} = useDefaultProps<LoadingProps>(props, { ...loadingDefaultProps, ...globalLoadingConfig });
} = useDefaultProps<LoadingProps>(props, {
...loadingDefaultProps,
...globalLoadingConfig,
});

const [showLoading, setShowLoading] = useState(() => (delay ? false : loading));

Expand Down Expand Up @@ -143,7 +146,9 @@ const Loading: React.FC<LoadingProps> = (props) => {
<Portal attach={attach}>
{showLoading ? (
<div
className={classnames(name, baseClasses, fullClass, { [overlayClass]: showOverlay })}
className={classnames(name, baseClasses, fullClass, {
[overlayClass]: showOverlay,
})}
style={{ ...calcStyles, ...style }}
>
{commonContent()}
Expand Down
11 changes: 9 additions & 2 deletions packages/components/loading/__tests__/loading.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ describe('Loading 组件测试', () => {
);

expect(container.querySelector('.t-loading__text')).toHaveTextContent('全局加载中');
expect(container.querySelector('.t-loading')).toHaveStyle({ fontSize: '36px', zIndex: '1234' });
expect(container.querySelector('.t-loading')).toHaveStyle({
fontSize: '36px',
zIndex: '1234',
});
});

test('loading props should override global loading config', async () => {
Expand All @@ -86,7 +89,11 @@ describe('Loading 组件测试', () => {
<div>
<div
className="trigger"
onClick={() => loading({ attach: () => document.querySelector('#loading-attach') }) as any}
onClick={() =>
loading({
attach: () => document.querySelector('#loading-attach'),
}) as any
}
>
container to trigger loading
</div>
Expand Down
Loading
Loading