generated from template/astro-template
init 新范式
This commit is contained in:
45
src/components/b/button/button.tsx
Normal file
45
src/components/b/button/button.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import React from 'react';
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
const button = cva('button', {
|
||||
variants: {
|
||||
intent: {
|
||||
primary: ['bg-blue-500', 'text-white', 'border-transparent'],
|
||||
secondary: ['bg-white', 'text-gray-800', 'border-gray-400'],
|
||||
},
|
||||
size: {
|
||||
small: ['text-sm', 'py-1', 'px-2'],
|
||||
medium: ['text-base', 'py-2', 'px-4'],
|
||||
},
|
||||
disabled: {
|
||||
false: null,
|
||||
true: ['opacity-50', 'cursor-not-allowed'],
|
||||
},
|
||||
},
|
||||
compoundVariants: [
|
||||
{
|
||||
intent: 'primary',
|
||||
disabled: false,
|
||||
class: 'hover:bg-blue-600',
|
||||
},
|
||||
{
|
||||
intent: 'secondary',
|
||||
disabled: false,
|
||||
class: 'hover:bg-gray-100',
|
||||
},
|
||||
{ intent: 'primary', size: 'medium', class: 'uppercase' },
|
||||
],
|
||||
defaultVariants: {
|
||||
disabled: false,
|
||||
intent: 'primary',
|
||||
size: 'medium',
|
||||
},
|
||||
});
|
||||
|
||||
export interface ButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'disabled'>, VariantProps<typeof button> {}
|
||||
|
||||
export const Button: React.FC<ButtonProps> = ({ className, intent, size, disabled, ...props }) => (
|
||||
<button className={twMerge('cursor-pointer', button({ intent, size, disabled, className }))} disabled={disabled || undefined} {...props} />
|
||||
);
|
||||
56
src/components/b/card/card.tsx
Normal file
56
src/components/b/card/card.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
// components/card.ts
|
||||
import type { VariantProps } from 'class-variance-authority';
|
||||
import { cva, cx } from 'class-variance-authority';
|
||||
import { cn } from '@/lib/utils';
|
||||
/**
|
||||
* Box
|
||||
*/
|
||||
export type BoxProps = VariantProps<typeof box>;
|
||||
export const box = cva(['box', 'box-border'], {
|
||||
variants: {
|
||||
margin: { 0: 'm-0', 2: 'm-2', 4: 'm-4', 8: 'm-8' },
|
||||
padding: { 0: 'p-0', 2: 'p-2', 4: 'p-4', 8: 'p-8' },
|
||||
},
|
||||
defaultVariants: {
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Card
|
||||
*/
|
||||
type CardBaseProps = VariantProps<typeof cardBase>;
|
||||
const cardBase = cva(['card', 'border-solid', 'border-slate-300', 'rounded'], {
|
||||
variants: {
|
||||
shadow: {
|
||||
md: 'drop-shadow-md',
|
||||
lg: 'drop-shadow-lg',
|
||||
xl: 'drop-shadow-xl',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export interface CardProps extends BoxProps, CardBaseProps {}
|
||||
export const card = ({ margin, padding, shadow }: CardProps = {}) => cx(box({ margin, padding }), cardBase({ shadow }));
|
||||
|
||||
type CardBlankProps = {
|
||||
number?: number;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* CardBlank 空的卡片,用于占位
|
||||
* @param props
|
||||
* @returns
|
||||
*/
|
||||
export const CardBlank = (props: CardBlankProps) => {
|
||||
const { number = 4, className } = props;
|
||||
return (
|
||||
<>
|
||||
{new Array(number).fill(0).map((_, index) => {
|
||||
return <div key={index} className={cn('w-[300px] shark-0', className)}></div>;
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
74
src/components/b/i18n/index.tsx
Normal file
74
src/components/b/i18n/index.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import Backend from 'i18next-http-backend'; // 引入 Backend 插件
|
||||
import { useLayoutEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
export { useTranslation };
|
||||
type I18NextProviderProps = {
|
||||
children: React.ReactNode;
|
||||
basename?: string;
|
||||
noUse?: boolean;
|
||||
};
|
||||
|
||||
export const initI18n = async (basename: string) => {
|
||||
// 初始化 i18n
|
||||
return new Promise((resolve) => {
|
||||
i18n
|
||||
.use(Backend) // 使用 Backend 插件
|
||||
.use(initReactI18next)
|
||||
.init(
|
||||
{
|
||||
backend: {
|
||||
loadPath: `${basename}/locales/{{lng}}/{{ns}}.json`, // 指定 JSON 文件的路径
|
||||
},
|
||||
lng: 'zh', // 默认语言
|
||||
fallbackLng: 'en', // 备用语言
|
||||
interpolation: {
|
||||
escapeValue: false, // react 已经安全地处理了转义
|
||||
},
|
||||
},
|
||||
(e) => {
|
||||
console.log('e', e);
|
||||
resolve(true);
|
||||
},
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 国际化组件,初始化
|
||||
* @param props
|
||||
* @returns
|
||||
*/
|
||||
export const I18NextProvider = (props: I18NextProviderProps) => {
|
||||
const { children, basename, noUse } = props;
|
||||
if (noUse) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
const [init, setInit] = useState(false);
|
||||
useLayoutEffect(() => {
|
||||
initCheck();
|
||||
}, []);
|
||||
const initCheck = async () => {
|
||||
let _currentBasename = '';
|
||||
if (typeof basename === 'undefined') {
|
||||
const local = localStorage.getItem('locale-basename');
|
||||
if (local) {
|
||||
_currentBasename = local;
|
||||
} else {
|
||||
_currentBasename = '';
|
||||
}
|
||||
} else {
|
||||
_currentBasename = basename;
|
||||
}
|
||||
if (_currentBasename === '/') {
|
||||
_currentBasename = '';
|
||||
}
|
||||
initI18n(_currentBasename);
|
||||
setInit(true);
|
||||
};
|
||||
if (!init) {
|
||||
return <></>;
|
||||
}
|
||||
return <>{children}</>;
|
||||
};
|
||||
40
src/components/b/render/ReactRender.tsx
Normal file
40
src/components/b/render/ReactRender.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
export class ReactRenderer {
|
||||
component: any;
|
||||
element: HTMLElement;
|
||||
ref: React.RefObject<any>;
|
||||
props: any;
|
||||
root: any;
|
||||
|
||||
constructor(component: any, { props }: any) {
|
||||
this.component = component;
|
||||
this.element = document.createElement('div');
|
||||
this.ref = React.createRef();
|
||||
this.props = {
|
||||
...props,
|
||||
ref: this.ref,
|
||||
};
|
||||
this.root = createRoot(this.element);
|
||||
this.render();
|
||||
}
|
||||
|
||||
updateProps(props: any) {
|
||||
this.props = {
|
||||
...this.props,
|
||||
...props,
|
||||
};
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
this.root.render(React.createElement(this.component, this.props));
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.root.unmount();
|
||||
}
|
||||
}
|
||||
|
||||
export default ReactRenderer;
|
||||
Reference in New Issue
Block a user