Skip to content

Commit

Permalink
Merge branch 'main' into chore/release-to-dingtalk
Browse files Browse the repository at this point in the history
  • Loading branch information
YumoImer authored Dec 24, 2024
2 parents 1fcf7d2 + c941e17 commit ed8e0c0
Show file tree
Hide file tree
Showing 11 changed files with 365 additions and 24 deletions.
25 changes: 25 additions & 0 deletions components/_util/__tests__/hooks.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import { render } from '../../../tests/utils';
import useProxyImperativeHandle from '../hooks/use-proxy-imperative-handle';

const TestComponent = React.forwardRef((_, ref) => {
const divRef = React.useRef(null);
useProxyImperativeHandle(ref, () => ({
nativeElement: divRef.current!,
testMethod: () => 'testMethod called',
testProperty: 'testProperty',
}));
return <div ref={divRef}>Hello World!</div>;
});

describe('useProxyImperativeHandle', () => {
it('should correctly proxy the nativeElement and init methods', () => {
const ref = React.createRef<any>();
render(<TestComponent ref={ref} />);
expect(ref.current).toBeDefined();
expect(ref.current?.testMethod()).toBe('testMethod called');
expect(ref.current?.testProperty).toBe('testProperty');
expect(ref.current?.nativeElement).toBeDefined();
expect(ref.current?.focus === ref.current?.nativeElement.focus).toBeTruthy();
});
});
25 changes: 25 additions & 0 deletions components/_util/hooks/use-proxy-imperative-handle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Proxy the dom ref with `{ nativeElement, otherFn }` type
// ref: https://github.com/ant-design/ant-design/discussions/45242

import { useImperativeHandle } from 'react';
import type { Ref } from 'react';

export default function useProxyImperativeHandle<
NativeELementType extends HTMLElement,
ReturnRefType extends { nativeElement: NativeELementType },
>(ref: Ref<any> | undefined, init: () => ReturnRefType) {
return useImperativeHandle(ref, () => {
const refObj = init();
const { nativeElement } = refObj;

return new Proxy(nativeElement, {
get(obj: any, prop: any) {
if ((refObj as any)[prop]) {
return (refObj as any)[prop];
}

return Reflect.get(obj, prop);
},
});
});
}
6 changes: 3 additions & 3 deletions components/attachments/demo/with-sender.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CloudUploadOutlined, LinkOutlined } from '@ant-design/icons';
import { Attachments, AttachmentsProps, Sender } from '@ant-design/x';
import { App, Badge, Button, Flex, type GetProp, Typography } from 'antd';
import { App, Badge, Button, Flex, type GetProp, type GetRef, Typography } from 'antd';
import React from 'react';

const Demo = () => {
Expand All @@ -10,7 +10,7 @@ const Demo = () => {

const { notification } = App.useApp();

const senderRef = React.useRef<HTMLDivElement>(null);
const senderRef = React.useRef<GetRef<typeof Sender>>(null);

const senderHeader = (
<Sender.Header
Expand Down Expand Up @@ -39,7 +39,7 @@ const Demo = () => {
description: 'Click or drag files to this area to upload',
}
}
getDropContainer={() => senderRef.current}
getDropContainer={() => senderRef.current?.nativeElement}
/>
</Sender.Header>
);
Expand Down
100 changes: 100 additions & 0 deletions components/sender/__tests__/__snapshots__/demo-extend.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,106 @@ exports[`renders components/sender/demo/basic.tsx extend context correctly 1`] =

exports[`renders components/sender/demo/basic.tsx extend context correctly 2`] = `[]`;

exports[`renders components/sender/demo/focus.tsx extend context correctly 1`] = `
<div
class="ant-flex ant-flex-wrap-wrap"
style="gap: 12px;"
>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
type="button"
>
<span>
Focus at first
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
type="button"
>
<span>
Focus at last
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
type="button"
>
<span>
Focus to select all
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
type="button"
>
<span>
Focus prevent scroll
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
type="button"
>
<span>
Blur
</span>
</button>
<div
class="ant-sender"
>
<div
class="ant-sender-content"
>
<textarea
class="ant-input ant-input-borderless ant-sender-input"
style="overflow-y: hidden; resize: none;"
>
Hello, welcome to use Ant Design X!
</textarea>
<div
class="ant-sender-actions-list"
>
<div
class="ant-sender-actions-list-presets ant-flex"
>
<button
class="ant-btn ant-btn-circle ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-icon-only ant-sender-actions-btn"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="arrow-up"
class="anticon anticon-arrow-up"
role="img"
>
<svg
aria-hidden="true"
data-icon="arrow-up"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M868 545.5L536.1 163a31.96 31.96 0 00-48.3 0L156 545.5a7.97 7.97 0 006 13.2h81c4.6 0 9-2 12.1-5.5L474 300.9V864c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V300.9l218.9 252.3c3 3.5 7.4 5.5 12.1 5.5h81c6.8 0 10.5-8 6-13.2z"
/>
</svg>
</span>
</span>
</button>
</div>
</div>
</div>
</div>
</div>
`;

exports[`renders components/sender/demo/focus.tsx extend context correctly 2`] = `[]`;

exports[`renders components/sender/demo/header.tsx extend context correctly 1`] = `
<div
class="ant-app"
Expand Down
97 changes: 97 additions & 0 deletions components/sender/__tests__/__snapshots__/demo.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,103 @@ exports[`renders components/sender/demo/basic.tsx correctly 1`] = `
</div>
`;

exports[`renders components/sender/demo/focus.tsx correctly 1`] = `
<div
class="ant-flex ant-flex-wrap-wrap"
style="gap:12px"
>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
type="button"
>
<span>
Focus at first
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
type="button"
>
<span>
Focus at last
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
type="button"
>
<span>
Focus to select all
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
type="button"
>
<span>
Focus prevent scroll
</span>
</button>
<button
class="ant-btn ant-btn-default ant-btn-color-default ant-btn-variant-outlined"
type="button"
>
<span>
Blur
</span>
</button>
<div
class="ant-sender"
>
<div
class="ant-sender-content"
>
<textarea
class="ant-input ant-input-borderless ant-sender-input"
>
Hello, welcome to use Ant Design X!
</textarea>
<div
class="ant-sender-actions-list"
>
<div
class="ant-sender-actions-list-presets ant-flex"
>
<button
class="ant-btn ant-btn-circle ant-btn-primary ant-btn-color-primary ant-btn-variant-solid ant-btn-icon-only ant-sender-actions-btn"
type="button"
>
<span
class="ant-btn-icon"
>
<span
aria-label="arrow-up"
class="anticon anticon-arrow-up"
role="img"
>
<svg
aria-hidden="true"
data-icon="arrow-up"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M868 545.5L536.1 163a31.96 31.96 0 00-48.3 0L156 545.5a7.97 7.97 0 006 13.2h81c4.6 0 9-2 12.1-5.5L474 300.9V864c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V300.9l218.9 252.3c3 3.5 7.4 5.5 12.1 5.5h81c6.8 0 10.5-8 6-13.2z"
/>
</svg>
</span>
</span>
</button>
</div>
</div>
</div>
</div>
</div>
`;

exports[`renders components/sender/demo/header.tsx correctly 1`] = `
<div
class="ant-app"
Expand Down
7 changes: 7 additions & 0 deletions components/sender/demo/focus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## zh-CN

使用 `ref` 选项控制聚焦。

## en-US

Focus with `ref` option.
63 changes: 63 additions & 0 deletions components/sender/demo/focus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Sender } from '@ant-design/x';
import { Button, Flex, type GetRef } from 'antd';
import React, { useRef } from 'react';

const App: React.FC = () => {
const senderRef = useRef<GetRef<typeof Sender>>(null);

const senderProps = {
defaultValue: 'Hello, welcome to use Ant Design X!',
ref: senderRef,
};

return (
<Flex wrap gap={12}>
<Button
onClick={() => {
senderRef.current!.focus({
cursor: 'start',
});
}}
>
Focus at first
</Button>
<Button
onClick={() => {
senderRef.current!.focus({
cursor: 'end',
});
}}
>
Focus at last
</Button>
<Button
onClick={() => {
senderRef.current!.focus({
cursor: 'all',
});
}}
>
Focus to select all
</Button>
<Button
onClick={() => {
senderRef.current!.focus({
preventScroll: true,
});
}}
>
Focus prevent scroll
</Button>
<Button
onClick={() => {
senderRef.current!.blur();
}}
>
Blur
</Button>
<Sender {...senderProps} />
</Flex>
);
};

export default App;
4 changes: 2 additions & 2 deletions components/sender/demo/paste-image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const Demo = () => {

const attachmentsRef = React.useRef<GetRef<typeof Attachments>>(null);

const senderRef = React.useRef<HTMLDivElement>(null);
const senderRef = React.useRef<GetRef<typeof Sender>>(null);

const senderHeader = (
<Sender.Header
Expand Down Expand Up @@ -41,7 +41,7 @@ const Demo = () => {
description: 'Click or drag files to this area to upload',
}
}
getDropContainer={() => senderRef.current}
getDropContainer={() => senderRef.current?.nativeElement}
/>
</Sender.Header>
);
Expand Down
Loading

0 comments on commit ed8e0c0

Please sign in to comment.