ant-design/components/config-provider/demo/wave.tsx
afc163 59ad48476b
refactor: add boime lint and fix lint errrors (#49536)
* chore: add boime lint

* fix lint

* use files ignore

* revert change

* ignore clarity.js

* fix some errors

* fix some errors

* fix some errors

* fix some errors

* add yml file

* Update clarity.js

Signed-off-by: afc163 <afc163@gmail.com>

* add npm run lint:biome

* add npm run lint:biome

* fix test case

* fix ts errors

* fix ts errors

* fix lint and add .lintstagedrc

* shorten prop name

* chore: update package.json

* update biome.json

* chore: remove stylelint

* chore: useOptionalChain

* fix lint

* biome format

* prettier all code

* prettier all code

* fix site test

---------

Signed-off-by: afc163 <afc163@gmail.com>
2024-06-22 21:59:12 +08:00

128 lines
3.2 KiB
TypeScript

import React from 'react';
import { HappyProvider } from '@ant-design/happy-work-theme';
import { Button, ConfigProvider, Space } from 'antd';
import type { ConfigProviderProps, GetProp } from 'antd';
type WaveConfig = GetProp<ConfigProviderProps, 'wave'>;
// Prepare effect holder
const createHolder = (node: HTMLElement) => {
const { borderWidth } = getComputedStyle(node);
const borderWidthNum = parseInt(borderWidth, 10);
const div = document.createElement('div');
div.style.position = 'absolute';
div.style.inset = `-${borderWidthNum}px`;
div.style.borderRadius = 'inherit';
div.style.background = 'transparent';
div.style.zIndex = '999';
div.style.pointerEvents = 'none';
div.style.overflow = 'hidden';
node.appendChild(div);
return div;
};
const createDot = (holder: HTMLElement, color: string, left: number, top: number, size = 0) => {
const dot = document.createElement('div');
dot.style.position = 'absolute';
dot.style.left = `${left}px`;
dot.style.top = `${top}px`;
dot.style.width = `${size}px`;
dot.style.height = `${size}px`;
dot.style.borderRadius = '50%';
dot.style.background = color;
dot.style.transform = 'translate(-50%, -50%)';
dot.style.transition = 'all 1s ease-out';
holder.appendChild(dot);
return dot;
};
// Inset Effect
const showInsetEffect: WaveConfig['showEffect'] = (node, { event, component }) => {
if (component !== 'Button') {
return;
}
const holder = createHolder(node);
const rect = holder.getBoundingClientRect();
const left = event.clientX - rect.left;
const top = event.clientY - rect.top;
const dot = createDot(holder, 'rgba(255, 255, 255, 0.65)', left, top);
// Motion
requestAnimationFrame(() => {
dot.ontransitionend = () => {
holder.remove();
};
dot.style.width = '200px';
dot.style.height = '200px';
dot.style.opacity = '0';
});
};
// Shake Effect
const showShakeEffect: WaveConfig['showEffect'] = (node, { component }) => {
if (component !== 'Button') {
return;
}
const seq = [0, -15, 15, -5, 5, 0];
const itv = 10;
let steps = 0;
function loop() {
cancelAnimationFrame((node as any).effectTimeout);
(node as any).effectTimeout = requestAnimationFrame(() => {
const currentStep = Math.floor(steps / itv);
const current = seq[currentStep];
const next = seq[currentStep + 1];
if (!next) {
node.style.transform = '';
node.style.transition = '';
return;
}
// Trans from current to next by itv
const angle = current + ((next - current) / itv) * (steps % itv);
node.style.transform = `rotate(${angle}deg)`;
node.style.transition = 'none';
steps += 1;
loop();
});
}
loop();
};
// Component
const Wrapper = ({ name, ...wave }: WaveConfig & { name: string }) => (
<ConfigProvider wave={wave}>
<Button type="primary">{name}</Button>
</ConfigProvider>
);
const App = () => (
<Space style={{ padding: 24 }} size="large">
<Wrapper name="Disabled" disabled />
<Wrapper name="Default" />
<Wrapper name="Inset" showEffect={showInsetEffect} />
<Wrapper name="Shake" showEffect={showShakeEffect} />
<HappyProvider>
<Button type="primary">Happy Work</Button>
</HappyProvider>
</Space>
);
export default App;